Чи має структура VBA словник? Як ключ <> масив значень?
Чи має структура VBA словник? Як ключ <> масив значень?
Відповіді:
Так.
Встановіть посилання на час виконання сценарію MS Scripting ("Microsoft Scripting Runtime"). Відповідно до коментаря @ regjo, перейдіть до Інструменти-> Список літератури та поставте прапорець у розділі "Виконання сценарію Microsoft".
Створіть екземпляр словника за допомогою наведеного нижче коду:
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
keyed
.
Dim dict As New Scripting.Dictionary
файл без посилання. Без посилання вам доведеться використовувати CreateObject
метод пізнього прив’язки для інстанції цього об'єкта.
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
Редагувати 24 червня 2015 року : Коротше Contains()
завдяки @TWiStErRob.
Редагувати 25 вересня 2015 року : додано Err.Clear()
завдяки @scipilot.
ContainsKey
; хтось, читаючи лише виклик, може переплутати його, перевіривши, чи містить воно певне значення.
Додатковий приклад словника, який корисний для вмісту частоти виникнення.
Поза петлі:
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 в , ми можемо побудувати Містить функції , які не потребують міток (мені не подобається з допомогою ярликів).
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
клавіші. Ви можете змінити його назад, якщо хочете.
Я перейменував це на встановлення, оскільки воно буде перезаписати старі значення.
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
та змінних без. Я думаю, ви можете просто перевірити, чи це об’єкт, але мене натискали на час.
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
Dim
ключового слова, Country
і вона Capital
повинна бути оголошена як Варіанти через використання Array()
, i
повинна бути оголошена (і повинна бути, якщо Option Explicit
встановлено), і лічильник циклу збирається викинути зв'язану помилку - безпечніше використання UBound(Country)
для To
значення. Також, можливо, варто зауважити, що, хоча Array()
функція є корисним ярликом, це не стандартний спосіб оголошення масивів у VBA.
Усі інші вже згадували про використання версії scripting.runtime класу Словник. Якщо ви не можете використовувати цю DLL, ви також можете використовувати цю версію, просто додайте її до свого коду.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
Він ідентичний версії Microsoft.