Hat VBA eine Wörterbuchstruktur? Wie Schlüssel <> Wert Array?
Hat VBA eine Wörterbuchstruktur? Wie Schlüssel <> Wert Array?
Antworten:
Ja.
Legen Sie einen Verweis auf die MS Scripting-Laufzeit fest ('Microsoft Scripting Runtime'). Gehen Sie gemäß dem Kommentar von @ regjo zu Extras-> Referenzen und aktivieren Sie das Kontrollkästchen für "Microsoft Scripting Runtime".
Erstellen Sie eine Wörterbuchinstanz mit dem folgenden Code:
Set dict = CreateObject("Scripting.Dictionary")
oder
Dim dict As New Scripting.Dictionary
Anwendungsbeispiel:
If Not dict.Exists(key) Then
dict.Add key, value
End If
Vergessen Sie nicht, das Wörterbuch auf einzustellen, Nothing
wenn Sie es nicht mehr verwenden.
Set dict = Nothing
keyed
.
Dim dict As New Scripting.Dictionary
ohne die Referenz verwenden. Ohne die Referenz müssen Sie die CreateObject
Methode der späten Bindung zum Instanziieren dieses Objekts verwenden.
VBA hat das Sammlungsobjekt:
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")
Das Collection
Objekt führt schlüsselbasierte Suchvorgänge mit einem Hash durch, damit es schnell geht.
Mit einer Contains()
Funktion können Sie überprüfen, ob eine bestimmte Sammlung einen Schlüssel enthält:
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
Bearbeiten 24. Juni 2015 : Kürzere Contains()
dank @TWiStErRob.
Bearbeiten 25. September 2015 : Err.Clear()
Dank @scipilot hinzugefügt.
ContainsKey
; Jemand, der nur den Aufruf liest, kann ihn verwirren, um zu überprüfen, ob er einen bestimmten Wert enthält.
VBA verfügt nicht über eine interne Implementierung eines Wörterbuchs. In VBA können Sie jedoch weiterhin das Wörterbuchobjekt aus der MS Scripting Runtime Library verwenden.
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
Ein zusätzliches Wörterbuchbeispiel, das nützlich ist, um die Häufigkeit des Auftretens einzudämmen.
Außerhalb der Schleife:
Dim dict As New Scripting.dictionary
Dim MyVar as String
Innerhalb einer Schleife:
'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
So überprüfen Sie die Frequenz:
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
Aufbauend auf der Antwort von cjrh können wir eine Contains-Funktion erstellen, für die keine Beschriftungen erforderlich sind (ich verwende keine Beschriftungen).
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
Für ein Projekt von mir habe ich eine Reihe von Hilfsfunktionen geschrieben, damit sich ein Collection
Verhalten eher wie ein Verhalten verhält Dictionary
. Es erlaubt weiterhin rekursive Sammlungen. Sie werden feststellen, dass der Schlüssel immer an erster Stelle steht, da er obligatorisch war und in meiner Implementierung sinnvoller war. Ich habe auch nur String
Schlüssel verwendet. Sie können es zurück ändern, wenn Sie möchten.
Ich habe dies in set umbenannt, da dadurch alte Werte überschrieben werden.
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
Das err
Zeug ist für Objekte, da Sie Objekte mit set
und Variablen ohne übergeben würden. Ich denke, Sie können einfach überprüfen, ob es sich um ein Objekt handelt, aber ich war unter Zeitdruck.
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
Der Grund für diesen Beitrag ...
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
Wirft nicht, wenn es nicht existiert. Stellt nur sicher, dass es entfernt ist.
Private Sub cRemove(ByRef Col As Collection, Key As String)
If cHas(Col, Key) Then Col.Remove Key
End Sub
Holen Sie sich eine Reihe von Schlüsseln.
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
Wenn Sie aus irgendeinem Grund keine zusätzlichen Funktionen in Ihrem Excel installieren können oder möchten, können Sie auch Arrays verwenden, zumindest für einfache Probleme. Als WhatIsCapital geben Sie den Namen des Landes ein und die Funktion gibt Ihnen das Kapital zurück.
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
Schlüsselwort, Country
und Capital
müssen als Varianten erklärt werden durch die Verwendung von Array()
, i
sollte erklärt werden (und sein muss , wenn Option Explicit
gesetzt), und der Schleifenzähler wird eine aus gebundenen Fehler werfen - sicherer Verwenden Sie UBound(Country)
für den To
Wert. Vielleicht ist es auch erwähnenswert, dass die Array()
Funktion zwar eine nützliche Verknüpfung ist, aber nicht die Standardmethode zum Deklarieren von Arrays in VBA ist.
Alle anderen haben bereits die Verwendung der scripting.runtime-Version der Dictionary-Klasse erwähnt. Wenn Sie diese DLL nicht verwenden können, können Sie diese Version auch verwenden. Fügen Sie sie einfach Ihrem Code hinzu.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
Es ist identisch mit der Microsoft-Version.