La VBA a-t-elle une structure de dictionnaire?
Ne VBA ont dictionnaire de la structure? Comme le tableau de valeurs de la touche?
9 réponses
Oui.
définit une référence à MS Scripting runtime ("Microsoft Scripting Runtime"). Conformément au commentaire de @regjo, allez à Outils - > Références et cochez la case "Microsoft Scripting Runtime".
créer une instance de dictionnaire en utilisant le code ci-dessous:
Set dict = CreateObject("Scripting.Dictionary")
ou
Dim dict As New Scripting.Dictionary
exemple d'utilisation:
If Not dict.Exists(key) Then
dict.Add key, value
End If
n'oubliez pas de placer le dictionnaire à Nothing
lorsque vous avez fini de l'utiliser.
Set dict = Nothing
VBA a l'objet de collection:
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")
l'objet Collection
effectue des recherches basées sur des clés en utilisant un hachage pour que ce soit rapide.
vous pouvez utiliser une fonction Contains()
pour vérifier si une collection particulière contient une clé:
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
Edit 24 juin 2015 : plus court Contains()
merci à @TWiStErRob.
Modifier 25 Septembre 2015 : ajouté Err.Clear()
merci à @scipilot.
VBA n'a pas d'implémentation interne d'un dictionnaire, mais de VBA vous pouvez toujours utiliser l'objet dictionary DE 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
un exemple de dictionnaire supplémentaire qui est utile pour contenir la fréquence d'occurence.
à l'Extérieur de la boucle:
Dim dict As New Scripting.dictionary
Dim MyVar as String
dans une boucle:
'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
pour vérifier la fréquence:
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
Construction cjrh la réponse de , nous pouvons construire un Contient la fonction nécessitant pas d'étiquettes (je n'aime pas utiliser des étiquettes).
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
pour un de mes projets, j'ai écrit un ensemble de fonctions d'aide pour faire un Collection
se comporter plus comme un Dictionary
. Il permet encore des collections récursives. Vous remarquerez que Key passe toujours en premier parce que C'était obligatoire et plus logique dans ma mise en œuvre. J'ai aussi utilisé seulement les clés String
. Vous pouvez le modifier si vous le souhaitez.
Set
j'ai renommé ceci pour définir parce qu'il va écraser les anciennes valeurs.
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
le truc err
est pour les objets puisque vous passeriez des objets en utilisant set
et des variables sans. Je pense que vous pouvez juste vérifier si c'est un objet, mais j'étais pressé par le temps.
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
a
La raison de ce 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
Supprimer
ne lance pas s'il n'existe pas. Tout à fait sûr que c'est supprimée.
Private Sub cRemove(ByRef Col As Collection, Key As String)
If cHas(Col, Key) Then Col.Remove Key
End Sub
Clés
Obtenir un tableau de clés.
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
le scripting runtime dictionary semble avoir un bug qui peut ruiner votre conception à des stades avancés.
si la valeur du dictionnaire est un tableau, vous ne pouvez pas mettre à jour les valeurs des éléments contenus dans le tableau par une référence au dictionnaire.
si par n'importe quelle raison, vous ne pouvez pas installer des traits supplémentaires à votre Excel ou ne voulez pas, vous pouvez utiliser des tableaux aussi bien, au moins pour des problèmes simples. Comme le capital que vous mettez nom du pays et la fonction vous rend son capital.
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
tous les autres ont déjà mentionné l'utilisation du script.version runtime de la classe Dictionary. Si vous n'êtes pas en mesure d'utiliser cette DLL, vous pouvez également utiliser cette version, il suffit de l'ajouter à votre code.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
il est identique à la version de Microsoft.