vba 使用索引/项目编号循环遍历 Scripting.Dictionary
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11296522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Looping through a Scripting.Dictionary using index/item number
提问by Gaffi
Similar to this issue, when using a Scripting.Dictionary
object in VBA, the outcome of the code below is unexpected.
与此问题类似,Scripting.Dictionary
在 VBA 中使用对象时,以下代码的结果出乎意料。
Option Explicit
Sub test()
Dim d As Variant
Dim i As Integer
Dim s As String
Set d = CreateObject("Scripting.Dictionary")
d.Add "a", "a"
Debug.Print d.Count ' Prints '1' as expected
For i = 1 To d.Count
s = d.Item(i)
Debug.Print s ' Prints ' ' (null) instead of 'a'
Next i
Debug.Print d.Count ' Prints '2' instead of '1'
End Sub
Using a zero-based index, the same outcome is achieved:
使用基于零的索引,可以获得相同的结果:
For i = 0 To d.Count - 1
s = d.Item(i)
Debug.Print s
Next i
Watching the object, I can actually see that it has two items, the key for the newly added is 1
, as added from i
. If I increase this loop to a higher number, then the number of items in the dictionary is increased, once for each loop.
观察这个对象,我其实可以看到它有两个项目,新添加的键是1
,从i
. 如果我将此循环增加到更高的数字,则字典中的项目数会增加,每个循环一次。
I have tested this in Office/VBA 2003, 2010, and 2013. All exhibit the same behavior, and I expect other versions (2007) will as well.
我已经在 Office/VBA 2003、2010 和 2013 中对此进行了测试。所有这些都表现出相同的行为,我希望其他版本 (2007) 也会如此。
I can work around this with other looping methods, but this caught me off guard when I was trying to store objects and was getting an object expected erroron the s = d.Item(i)
line.
我可以使用其他循环方法来解决这个问题,但是当我尝试存储对象并在行上收到一个对象预期错误时,这让我措手不及s = d.Item(i)
。
For the record, I know that I can do things like this:
为了记录,我知道我可以做这样的事情:
For Each v In d.Keys
Set o = d.item(v)
Next v
But I'm more curious about why I can't seem to iterate through the items by number.
但我更好奇为什么我似乎无法按数字遍历项目。
采纳答案by assylias
According to the documentation of the Item
property:
根据该Item
物业的文件:
Sets or returns an item for a specified key in a Dictionary object.
为 Dictionary 对象中的指定键设置或返回一个项目。
In your case, you don't have an item whose key is 1
so doing:
在你的情况下,你没有一个项目的关键是1
这样做:
s = d.Item(i)
actually creates a new key / value pair in your dictionary, and the value is empty because you have not used the optional newItem
argument.
实际上在您的字典中创建了一个新的键/值对,该值是空的,因为您没有使用可选newItem
参数。
The Dictionary also has the Items
methodwhich allows looping over the indices:
该词典还具有Items
方法,其允许遍历索引:
a = d.Items
For i = 0 To d.Count - 1
s = a(i)
Next i
回答by Craig Hatmaker
Adding to assylias's answer - assylias shows us D.ITEMS is a method that returns an array. Knowing that, we don't need the variant array a(i) [See caveat below]. We just need to use the proper array syntax.
添加到 assylias 的答案 - assylias 向我们展示了 D.ITEMS 是一种返回数组的方法。知道这一点,我们不需要变体数组 a(i) [见下面的警告]。我们只需要使用正确的数组语法。
For i = 0 To d.Count - 1
s = d.Items()(i)
Debug.Print s
Next i()
KEYS works the same way
KEYS 的工作方式相同
For i = 0 To d.Count - 1
Debug.Print d.Keys()(i), d.Items()(i)
Next i
This syntax is also useful for the SPLIT function which may help make this clearer. SPLIT also returns an array with lower bounds at 0. Thus, the following prints "C".
此语法对于 SPLIT 函数也很有用,这可能有助于使这一点更清晰。SPLIT 还返回一个下限为 0 的数组。因此,以下打印“C”。
Debug.Print Split("A,B,C,D", ",")(2)
SPLIT is a function. Its parameters are in the first set of parentheses. Methods and Functions always use the first set of parentheses for parameters, even if no parameters are needed. In the example SPLIT returns the array {"A","B","C","D"}. Since it returns an array we can use a second set of parentheses to identify an element within the returned array just as we would any array.
SPLIT 是一个函数。它的参数在第一组括号中。方法和函数总是使用第一组括号作为参数,即使不需要参数。在示例中,SPLIT 返回数组 {"A","B","C","D"}。由于它返回一个数组,我们可以使用第二组括号来标识返回数组中的元素,就像我们识别任何数组一样。
Caveat: This shorter syntax may not be as efficient as using the variant array a() when iterating through the entire dictionary since the shorter syntax invokes the dictionary's Items method with each iteration. The shorter syntax is best for plucking a single item by number from a dictionary.
警告:在遍历整个字典时,这种较短的语法可能不如使用变体数组 a() 有效,因为较短的语法在每次迭代时都会调用字典的 Items 方法。较短的语法最适合按数字从字典中提取单个项目。
回答by Alex Dragokas
Using d.Keys()(i)
method is a very bad idea, because on each call it will re-create a new array (you will have significant speed reduction).
使用d.Keys()(i)
方法是一个非常糟糕的主意,因为每次调用它都会重新创建一个新数组(您将显着降低速度)。
Here is an analogue of Scripting.Dictionary
called "Hash Table" class from @"The Trick", that support such enumerator: http://www.cyberforum.ru/blogs/354370/blog2905.html
这是Scripting.Dictionary
来自@“The Trick”的名为“Hash Table”的类,它支持这样的枚举器:http: //www.cyberforum.ru/blogs/354370/blog2905.html
Dim oDict As clsTrickHashTable
Sub aaa()
Set oDict = New clsTrickHashTable
oDict.Add "a", "aaa"
oDict.Add "b", "bbb"
For i = 0 To oDict.Count - 1
Debug.Print oDict.Keys(i) & " - " & oDict.Items(i)
Next
End Sub
回答by Tony Hopkinson
It's zero based so your loop should be from 0 to d.Count - 1
它是基于零的所以你的循环应该是从 0 到 d.Count - 1