VBA是否有字典结构?

VBA是否有字典结构? 像关键的<>值数组?

是。

设置对MS Scripting运行时的引用('Microsoft Scripting Runtime')

Set dict = CreateObject("Scripting.Dictionary") 

要么

 Dim dict As New Scripting.Dictionary 

使用示例:

 If Not dict.Exists(key) Then dict.Add key, value End If 

不要忘记在完成使用后将字典设置为Nothing

 Set dict = Nothing 

VBA具有集合对象:

  Dim c As Collection Set c = New Collection c.Add "Data1", "Key1" c.Add "Data2", "Key2" c.Add "Data3", "Key3" 'Insert data via key into cell A1 Range("A1").Value = c.Item("Key2") 

Collection对象使用散列执行基于键的查找,所以它很快。


您可以使用Contains()函数来检查特定集合是否包含密钥:

 Public Function Contains(col As Collection, key As Variant) As Boolean On Error Resume Next col(key) ' Just try it. If it fails, Err.Number will be nonzero. Contains = (Err.Number = 0) Err.Clear End Function 

编辑2015年6月24日 :更短的Contains()感谢@TWiStErRob。

编辑2015年9月25日 :增加Err.Clear()感谢@ scipilot。

VBA没有字典的内部实现,但是从VBA中仍然可以使用MS Scripting Runtime Library中的字典对象。

 Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "aaa" d.Add "b", "bbb" d.Add "c", "ccc" If d.Exists("c") Then MsgBox d("c") End If 

一个额外的字典例子,用于包含频率的发生。

循环之外:

 Dim dict As New Scripting.dictionary Dim MyVar as String 

在一个循环中:

 'dictionary If dict.Exists(MyVar) Then dict.Item(MyVar) = dict.Item(MyVar) + 1 'increment Else dict.Item(MyVar) = 1 'set as 1st occurence End If 

检查频率:

 Dim i As Integer For i = 0 To dict.Count - 1 ' lower index 0 (instead of 1) Debug.Print dict.Items(i) & " " & dict.Keys(i) Next i 

build立cjrh的答案 ,我们可以build立一个不需要标签(我不喜欢使用标签)的包含function。

 Public Function Contains(Col As Collection, Key As String) As Boolean Contains = True On Error Resume Next err.Clear Col (Key) If err.Number <> 0 Then Contains = False err.Clear End If On Error GoTo 0 End Function 

对于我的一个项目,我写了一套帮助函数来使一个Collection更像一个Dictionary 。 它仍然允许recursion集合。 你会注意到Key始终是第一位的,因为它是强制性的,在我的实现中更有意义。 我也只用了String键。 如果你喜欢,你可以把它改回来。

我重命名这个设置,因为它会覆盖旧的值。

 Private Sub cSet(ByRef Col As Collection, Key As String, Item As Variant) If (cHas(Col, Key)) Then Col.Remove Key Col.Add Array(Key, Item), Key End Sub 

得到

err东西是为对象,因为你会传递对象使用set和variables没有。 我想你可以检查一下是否是一个对象,但是我被时间所压。

 Private Function cGet(ByRef Col As Collection, Key As String) As Variant If Not cHas(Col, Key) Then Exit Function On Error Resume Next err.Clear Set cGet = Col(Key)(1) If err.Number = 13 Then err.Clear cGet = Col(Key)(1) End If On Error GoTo 0 If err.Number <> 0 Then Call err.raise(err.Number, err.Source, err.Description, err.HelpFile, err.HelpContext) End Function 

具有

这个post的原因…

 Public Function cHas(Col As Collection, Key As String) As Boolean cHas = True On Error Resume Next err.Clear Col (Key) If err.Number <> 0 Then cHas = False err.Clear End If On Error GoTo 0 End Function 

去掉

如果不存在,则不抛出。 只要确保它被删除。

 Private Sub cRemove(ByRef Col As Collection, Key As String) If cHas(Col, Key) Then Col.Remove Key End Sub 

按键

获取一组密钥。

 Private Function cKeys(ByRef Col As Collection) As String() Dim Initialized As Boolean Dim Keys() As String For Each Item In Col If Not Initialized Then ReDim Preserve Keys(0) Keys(UBound(Keys)) = Item(0) Initialized = True Else ReDim Preserve Keys(UBound(Keys) + 1) Keys(UBound(Keys)) = Item(0) End If Next Item cKeys = Keys End Function 

脚本运行时字典似乎有一个错误,可以在高级阶段破坏你的devise。

如果字典值是一个数组,则不能通过对字典的引用来更新数组中包含的元素的值。

是。 对于VB6 ,VBA(Excel)和VB.NET

如果由于任何原因,您不能将附加function安装到您的Excel或不想,也可以使用数组,至less对于简单的问题。 作为WhatIsCapital你把国家的名字和函数返回给你的资本。

 Sub arrays() Dim WhatIsCapital As String, Country As Array, Capital As Array, Answer As String WhatIsCapital = "Sweden" Country = Array("UK", "Sweden", "Germany", "France") Capital = Array("London", "Stockholm", "Berlin", "Paris") For i = 0 To 10 If WhatIsCapital = Country(i) Then Answer = Capital(i) Next i Debug.Print Answer End Sub 

所有其他人已经提到了使用Dictionary类的scripting.runtime版本。 如果你不能使用这个DLL,你也可以使用这个版本,只需将它添加到你的代码。

https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls

它与微软的版本相同。