Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Excel VBA中创建循环中的新词典集合?_Excel_Vba - Fatal编程技术网

如何在Excel VBA中创建循环中的新词典集合?

如何在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 =

我想把一个有两列的范围转换成一个字典集合。例如,如果范围为

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 = 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
    @SJR
    out\u collection
    current\u row
    将它们初始化为
    New
    ,这应该将它们初始化为空集合/字典。问题似乎是,只有在循环的第一次迭代中,字典才是真正新的,在随后的迭代中,现有对象被重用。
    Dim x作为***新***……
    的陷阱你能详细说明一下引擎盖下发生了什么吗?使用
    Dim x As New…
    与使用
    Dim x As…,两者之间会发生什么不同:使用Set x=…
    吗?@ZevSpitz
    Dim 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