克隆集合

Cal*_*mDA 0 excel vba excel-vba

我有两个系列 - collection1collection2

collection1其中有许多类对象,我试图collection2使用以下命令填充相同对象的副本:

Set collection2 = collection1
Run Code Online (Sandbox Code Playgroud)

这不会给我想要的结果,因为当我使用时

collection2.Remove 1      
Run Code Online (Sandbox Code Playgroud)

它从两个集合中删除索引1处的对象.

下面是完整的代码,我希望10collection1从collection2中删除一个后输出对象

Sub test()
    Dim collection1 As Collection
    Dim collection2 As Collection
    Dim testObj As Worksheet
    Dim i As Integer

    Set collection1 = New Collection
    Set collection2 = New Collection

    For i = 1 To 10
        collection1.Add testObj
    Next i

    Set collection2 = collection1
    collection2.Remove 1
    Debug.Print collection1.Count
End Sub
Run Code Online (Sandbox Code Playgroud)


我尝试了下面的代码并且它有效,但我希望尽可能避免逐个填充两个集合:

...
For i = 1 To 10
    collection1.Add testObj
    collection2.Add testObj
Next i
...
Run Code Online (Sandbox Code Playgroud)

我不太热衷于这个选项的原因是因为最终我打算使用多个集合,操纵它们并在不同的点上复制,所以我最终会在代码中使用大量的for循环,而不仅仅是一个.

Mat*_*don 6

我试图使用以下命令用相同对象的副本填充collection2:

Set collection2 = collection1
Run Code Online (Sandbox Code Playgroud)

然而,这不是那个命令的作用.该Set关键字不"复制对象",并且不会自动地知道(甚至关心),它在处理一个Collection包含项目对象.

所述Set关键字分配一个参考.没有更多,没有更少.

那么Set collection2 = collection1字面意思是:

获取collection1对象的指针,并用它替换collection2所指的任何内容.

Set当你这样做时,该指令实际上丢弃了你创建的对象:

Set collection2 = New Collection
Run Code Online (Sandbox Code Playgroud)

你不是"复制对象"或"填充collection2" -你改写它的对象引用,使得collection2指向同一个对象collection1.

并且由于两个指针指向同一个对象 ...使用其中任何一个删除项目Collection确实会从"两个"集合中删除它,...因为只涉及一个集合对象.


(未记录的?)ObjPtr关键字可以帮助揭示正在发生的事情:

Set collection1 = New Collection
Debug.Print "collection1: " & ObjPtr(collection1)

Set collection2 = New Collection
Debug.Print "collection2: " & ObjPtr(collection2)

'the debug output contains 2 different addresses at this point

Set collection2 = collection1
Debug.Print "collection1: " & ObjPtr(collection1)
Debug.Print "collection2: " & ObjPtr(collection2)

'now the debug output clearly shows that 
'both collection1 and collection2 are pointing to the same object
Run Code Online (Sandbox Code Playgroud)

如果您需要集合的副本,则需要一个获取集合并返回一个全新对象的函数:

Public Function CopyCollection(ByVal source As Collection) As Collection
    Dim result As New Collection
    Dim item As Variant
    For Each item In source
        result.Add item
    Next
    Set CopyCollection = result
End Function
Run Code Online (Sandbox Code Playgroud)

正如在评论中已经指出的那样,这仅在您的馆藏没有键入时才有效.由于a Collection是有限的(你不能迭代其键)Scripting.Dictionary,如果你需要克隆一个键控集合,你将不得不使用一个.