如何在Excel VBA中创建循环中的新词典集合?
我想把一个有两列的范围转换成一个字典集合。例如,如果范围为 A. B 1. 2. 3. 4. 5. 6.如何在Excel VBA中创建循环中的新词典集合?,excel,vba,Excel,Vba,我想把一个有两列的范围转换成一个字典集合。例如,如果范围为 A. B 1. 2. 3. 4. 5. 6. 欢迎来到避免由于意外/不需要的行为而自动实例化的世界。删除自动实例化并每次设置一个新引用 Option Explicit Public Sub test() Dim c As Collection, rng As Range, i As Long Set rng = ActiveSheet.Range("A1:B3") Set c =
欢迎来到避免由于意外/不需要的行为而自动实例化的世界。删除自动实例化并每次设置一个新引用
Option Explicit
Public Sub test()
Dim c As Collection, rng As Range, i As Long
Set rng = ActiveSheet.Range("A1:B3")
Set c = Make_Collection(rng)
For i = 1 To c.Count
Debug.Print c.Item(i)("first"), " ", c.Item(i)("second")
Next
End Sub
Function Make_Collection(r As Range) As Collection
Dim out_collection As Collection, arr() As Variant
Dim i As Long, current_row As Scripting.Dictionary
Set out_collection = New Collection
arr = r.Value
For i = LBound(arr, 1) To UBound(arr, 1)
Set current_row = New Dictionary
current_row.Item("first") = arr(i, 1)
current_row.Item("second") = arr(i, 2)
out_collection.Add current_row
Next
Set Make_Collection = out_collection
End Function
从奇妙的Chip Pearson网站上可以看到: 不要使用自动实例化对象变量 对于对象类型变量,可以在Dim语句中包含新关键字。这样做会创建一个称为自动实例化变量的变量。同样,虽然这看起来很方便,但应该避免。与一些程序员可能相信的相反,处理变量声明时不会创建对象。相反,对象是在代码中首次遇到时创建的。这意味着,首先,您在创建对象时拥有有限的控制权。第二,这意味着您无法测试对象是否为空,这是代码中的常见测试以及常见的测试和诊断技术。如果编译器的输出是VBA代码,则处理自动实例化变量的代码如下所示:
Dim FSO As New Scripting.FileSystemObject
'''''''''''
' more code
'''''''''''
If FSO Is Nothing Then ' The compiler does something like this
Set FSO = New Scripting.FileSystemObject
End If
在这里,简单地测试FSO的Nothing会导致创建对象,因此FSO永远不会正确地测试Nothing状态。不要在变量的声明中使用New,而是使用Set New语法:
Dim FSO As Scripting.FileSystemObject
Set FSO = New Scripting.FileSystemObject
以及:
这称为自动实例化变量。在代码中首次遇到变量C时,将创建一个新实例。通常,应避免自动实例化变量,原因有两个:
首先,它增加了代码的开销,因为每次在代码中遇到变量时都必须对其进行测试
其次,您无法测试自动实例化变量是否为空,因为在If Obj is Nothing-Then语句中使用变量名的行为将自动创建该变量的实例
相关利益:
您声明了一个集合和字典,但从未使用
Set
@SJRout\u collection
和current\u row
将它们初始化为New
,这应该将它们初始化为空集合/字典。问题似乎是,只有在循环的第一次迭代中,字典才是真正新的,在随后的迭代中,现有对象被重用。Dim x作为***新***……
的陷阱你能详细说明一下引擎盖下发生了什么吗?使用Dim x As New…
与使用Dim x As…,两者之间会发生什么不同:使用Set x=…
吗?@ZevSpitzDim x作为新的…
是用于创建“自动实例化”(ai)变量的特殊语法。每次引用ai变量(例如,x.foo()
)时,VBA都会检查该变量x是否为空,如果为空,则会创建一个对象,并在调用foo
之前在同一行将其分配给x。所有对象变量(ai和“normal”)初始化为Nothing
,这意味着Set current\u row=New Dictionary
调用隐式发生在current\u row.Item(“first”)=…
行上。但是每一次后续循环迭代,当前行ai变量都不是空的,因此不会重新初始化为新字典。@ZevSpitz在仍然使用自动实例化语法的情况下,另一个选项是在循环的每次迭代中手动将当前行
变量设置为空。这样,当VBA在x.foo
之前检查x=Nothing?
时,将触发重新初始化。值得注意的是,Dim语句仅在第一次命中时运行一次,而不是循环的每一步,因此它不会自动将当前_行重置为空。有趣的是,您永远不能手动检查ai变量为Nothing
,因为它总是在检查之前自动实例化,所以检查总是false@Greedo希望能够对你的两条评论进行投票;这值得一个自我回答的问题:-)
Dim C As New Class1