【发布时间】: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
所以上面会改变集合内第一个二维数组的第一个元素...
【问题讨论】:
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
所以上面会改变集合内第一个二维数组的第一个元素...
【问题讨论】:
嗯...语法看起来足够合法,没有 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 数组很复杂且容易出错。
【讨论】:
@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
【讨论】:
也许 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
【讨论】:
我最近遇到了这个确切的问题。我通过用相关项数组填充一个数组、对此数组进行更改、从集合中删除项数组然后将更改后的数组添加到集合中来解决它。不漂亮,但它有效....我找不到其他方法。
【讨论】:
如果您希望集合具有数组的副本,而不是对数组的引用,则使用 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() 的累积集合。
【讨论】: