Имеет ли VBA структуру словаря?
имеет ли VBA структуру словаря? Как ключ массив значений?
9 ответов:
да.
установите ссылку на MS Scripting runtime ('Microsoft Scripting Runtime'). В соответствии с комментарием @regjo, перейдите в сервис- > ссылки и отметьте поле для "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")
The
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
Редактировать 24 Июня 2015: короче
Contains()
спасибо @TWiStErRob.Редактировать 25 Сентября 2015: добавил
Err.Clear()
спасибо @scipilot.
VBA не имеет внутренней реализации словаря, но из VBA вы все еще можете использовать объект dictionary из библиотеки MS Scripting Runtime.
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
здание с ответ cjrh, мы можем построить функцию Contains, не требующую ярлыков (мне не нравится использовать ярлыки).
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
. Он по-прежнему позволяет рекурсивные коллекции. Вы заметите, что ключ всегда приходит первым, потому что он был обязательным и больше смысла в моей реализации. Я также использовал толькоString
ключи. Вы можете изменить его обратно, если вы как.Set
я переименовал этот набор, потому что он будет перезаписывать старые значения.
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
Get
The
err
материал для объектов, так как вы бы передать объекты с помощьюset
и переменных без. Я думаю, что вы можете просто проверить, если это объект, но у меня было мало времени.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
и
причина этого поста...
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
в словаре времени выполнения сценариев, похоже, есть ошибка, которая может разрушить ваш дизайн на продвинутых этапах.
Если значение словаря является массивом, вы не можете обновить значения элементов, содержащихся в массиве, с помощью ссылки на словарь.
Если по какой-либо причине вы не можете установить дополнительные функции в Excel или не хотите, вы также можете использовать массивы, по крайней мере, для простых задач. В качестве 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
все остальные уже упоминали об использовании сценариев.версия времени выполнения класса словаря. Если вы не можете использовать эту DLL, вы также можете использовать эту версию, просто добавьте его в свой код.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
он идентичен версии Microsoft.