证明Excel VBA Scripting.Dictionary不保留项目插入的顺序

Joh*_*hnM 2 arrays excel vba dictionary excel-vba

我正在尝试决定是否将Excel VBA Collection或Dictionary用于我的项目.由于几个原因,我倾向于字典,但我继续阅读当使用For.. Each循环来检索字典项或从字典Items()数组中读取项时,检索的顺序可能不是添加项的顺序.对于我的应用程序来说这将是一个严重的问题,所以我尝试了许多测试用例,试图证明实际发生了这种顺序不匹配.到目前为止,我还没有能够创建出现这种情况的场景,包括以随机顺序添加和删除项目.

任何人都可以提供一个示例,证明检索顺序与Excel VBA Scripting.Dictionary的插入顺序不匹配吗?

小智 5

没有人可以提供Scripting.Dictionary对象的示例,其返回键/项的顺序与添加它们的顺序不同,因为Scripting.Dictionary 不会这样做.决不.如果以渐进顺序添加以下键/项对,那么这就是它们的返回方式.

key  item
 1    A
 2    B
 3    C
 4    D

'enumerate by key
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")

dict.Add Key:=1, Item:="A"
dict.Add Key:=2, Item:="B"
dict.Add Key:=3, Item:="C"
dict.Add Key:=4, Item:="D"

Dim k As Variant
For Each k In dict.Keys
    Debug.Print k & " - " & dict.Item(k)
Next k
Run Code Online (Sandbox Code Playgroud)

您可能指的是添加键的简写'覆盖'方法,而不检查它们是否存在.如果您尝试.新增存在误差457抛出的关键.但是,如果您只是将写入字典中,则如果该键不存在,则将创建新的键和项,但如果该键存在,则该键保持不变并且该项将被覆盖.

key  item
 1    A
 2    B
 3    C
 4    D
 2    E

'enumerate by key
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")

dict.Item(1) = "A"
dict.Item(2) = "B"
dict.Item(3) = "C"
dict.Item(4) = "D"
dict.Item(2) = "E"     'the second entry's item is overwritten

Dim k As Variant
For Each k In dict.Keys
    Debug.Print k & " - " & dict.Item(k)
Next k
Run Code Online (Sandbox Code Playgroud)

覆写方法比,如果一个关键检查快一点.Exists但行为应该被理解.我已经使用覆盖来故​​意检索列表中具有重复键的任何键的最后一项,但这是一种特殊情况.请注意,2 .Key不是原始顺序; 它只是将它的.Item替换为后者.

如果已添加Microsoft Scripting Runtime参考库,则可以在变量声明中使用Early Binding.这样做的好处是可以创建一个稍快的字典对象并公开其他索引枚举方法.

Dim dict As New Scripting.Dictionary

'enumerate by index position (zero-based index)
Dim i As Long
For i = 0 To dict.Count - 1
    Debug.Print dict.Keys(i) & " - " & dict.Items(i)
Next i

'enumerate as elements of an array
Dim a As Long
For a = LBound(dict.Keys) To UBound(dict.Keys)
    Debug.Print dict.Keys(a) & " - " & dict.Items(a)
Next a
Run Code Online (Sandbox Code Playgroud)

fwiw,我发现当字典的.Count超过有符号整数(32,767)时,这个索引枚举是不可靠的.

最后,键/项对可以一次删除一个,也可以一次删除.

dict.Remove 2                              'remove by key

dict.Remove dict.Keys(0)                   'remove first key/item by index position
dict.Remove dict.Keys(UBound(dict.Keys))   'remove last key/item by index position

dict.RemoveAll                             'remove all
Run Code Online (Sandbox Code Playgroud)

  • ...并且所有键或项目都可以在 [Range.AutoFilter 方法](https://msdn.microsoft.com/en-us/library/office/ff193884.aspx) 中使用,例如 `.AutoFilter Field:=2 , Criteria1:=dict.Keys, Operator:=xlFilterValues`。是的,字典是一个强大的工具。 (2认同)