【问题标题】:Populating collection with arrays用数组填充集合
【发布时间】:2010-11-27 00:51:15
【问题描述】:
Dim A As Collection
Set A = New Collection

Dim Arr2(15, 5)
Arr2(1,1) = 0
' ...

A.Add (Arr2)

如何通过A 访问Arr2?例如,我想做以下事情:

A.Item(1) (1,1) = 15

所以上面会改变集合内第一个二维数组的第一个元素...

【问题讨论】:

    标签: vb.net vba vb6 excel


    【解决方案1】:

    嗯...语法看起来足够合法,没有 VBA 在我面前。我是否正确,您的问题是您的代码“编译”并执行而不会引发错误,但集合中的数组永远不会改变?如果是这样,我认为那是因为您的 A.Item(1) 可能会返回您存储在集合中的数组的 copy。然后您就可以访问和修改所选元素,但它没有达到您想要的效果,因为它是错误的数组实例。

    一般来说,VBA 集合在存储对象时效果最好。然后它们会像你想要的那样工作,因为它们存储引用。它们可以很好地存储值,但我认为它们总是复制它们,即使是像数组变体这样的“大”值,这意味着你不能改变存储数组的内容。

    认为这个答案只是一个猜测,直到有人更好地了解底层 COM 内容。嗯......分页 Joel Spolsky?

    编辑:在 Excel VBA 中尝试后,我认为我是对的。将数组变体放入集合中会产生副本,取出一个也是如此。因此,似乎没有直接的方法来编码您实际要求的内容。

    看起来您真正想要的是一个 3-D 数组,但您试图在第一个维度上使用集合这一事实意味着您希望能够在该维度上更改它的大小。 VBA 只会让您更改数组最后一维的大小(请参阅帮助中的“redim preserve”)。你可以将你的二维数组放在一个你可以改变大小的一维数组中,但是:

    ReDim a(5)
    Dim b(2, 2)
    a(2) = b
    a(2)(1, 1) = 42
    ReDim Preserve a(6)
    

    注意 a 是用 ReDim 声明的,在这种情况下不是 Dim。

    最后,对于您正在尝试做的任何事情,其他一些方法很可能会更好。至少可以说,可增长、可变的 3-D 数组很复杂且容易出错。

    【讨论】:

      【解决方案2】:

      @jtolle 是正确的。如果您运行下面的代码并检查 Arr2 和 x 的值(快速观察是 Shift-F9),您会发现它们是不同的:

      Dim A As Collection
      Set A = New Collection
      Dim Arr2(15, 5)
      
      Arr2(1, 1) = 99
      
      ' ...
      
      A.Add (Arr2) ' adds a copy of Arr2 to teh collection
      
      Arr2(1, 1) = 11  ' this alters the value in Arr2, but not the copy in the collection
      
      Dim x As Variant
      
      x = A.Item(1)
      x(1, 1) = 15  ' this does not alter Arr2
      

      【讨论】:

      • 我认为 Arr2(1, 1) = 11 实际上并没有改变集合中的数组。请参阅我编辑的答案,但看起来 VBA 在添加和读取集合时会复制数组。
      • 也许我只是被你的评论误导了?该行确实会改变 Arr2,但不会改变存储在集合中的数组。我看到它改变了 Arr2,但不是 A.Item(1),它只是 A.Add(Arr2) 制作的 Arr2 的副本。
      • @jtolle:抱歉,我刚刚重新检查过,你是绝对正确的。我将更新上面的代码。它是集合中 Arr2 的副本。
      【解决方案3】:

      也许 VBA 在将数组分配给集合时会复制该数组? VB.net 不这样做。在这段代码之后,a(3,3) 在 vba 中为 20,在 vb.net 中为 5。

      Dim c As New Collection
      Dim a(10, 10) As Integer
      
      a(3, 3) = 20
      c.Add(a)
      c(1)(3, 3) = 5
      

      【讨论】:

        【解决方案4】:

        我最近遇到了这个确切的问题。我通过用相关项数组填充一个数组、对此数组进行更改、从集合中删除项数组然后将更改后的数组添加到集合中来解决它。不漂亮,但它有效....我找不到其他方法。

        【讨论】:

          【解决方案5】:

          如果您希望集合具有数组的副本,而不是对数组的引用,则使用 array.clone 方法:-

          Dim myCollection As New Collection
          Dim myDates() as Date
          Dim i As Integer
          
          Do
             i = 0
             Array.Resize(myDates, 0)
             Do
                 Array.Resize(myDates, i + 1)
                 myDates(i) = Now
                 ...
                 i += 1
             Loop
             myCollection.Add(myDates.Clone)
          Loop
          

          最后,myCollection 将包含 myDates() 的累积集合。

          【讨论】:

            猜你喜欢
            • 2019-06-11
            • 1970-01-01
            • 1970-01-01
            • 2022-01-15
            • 1970-01-01
            • 1970-01-01
            • 2012-02-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多