克隆集合

时间:2016-12-09 16:55:47

标签: excel vba excel-vba

我有两个收藏集 - collection1collection2

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

Set collection2 = collection1

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

collection2.Remove 1      

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

以下是完整代码,我希望在从{collection> 2中删除一个10之后输出collection1个对象

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

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

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

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

2 个答案:

答案 0 :(得分:6)

  

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

Set collection2 = collection1

然而,那不是那个命令的作用。 Set关键字不会“复制对象”,也不会自动知道(甚至关心)它正在处理包含项目的Collection对象。

Set关键字分配参考。没什么,没什么。

所以Set collection2 = collection1的确如此,字面意思是:

  

获取collection1对象的指针,并将collection2所引用的内容替换为该内容。

当您执行此操作时,Set指令实际上会丢弃您首先创建的对象:

Set collection2 = New Collection

您不是“复制对象”或“填充集合2” - 您覆盖其对象引用,使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

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

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

As already noted in comments但是,只有在您的馆藏没有键入时,这才有效。由于Collection的限制(您无法迭代其键),如果您需要克隆键控集合,则必须使用Scripting.Dictionary

答案 1 :(得分:1)

首先,您不需要Dim collection1 As CollectionSet collection1 = New Collection。这可以由Dim collection1 As New Collection

替换

现在,您正在做的是使collection2包含collection1。它就像在一个盒子(collection1)上放了很多帽子,然后将这个盒子放在另一个盒子里(collection2)。

另一种方法是同时填充它们或者执行代码来复制像

这样的内容
for i = 1 to collection1.count
    collection2.add collection1.item(i)
next i