VBA a-t-il une structure de dictionnaire? Comme le tableau de valeurs de la clé <>?
VBA a-t-il une structure de dictionnaire? Comme le tableau de valeurs de la clé <>?
Réponses:
Oui.
Définissez une référence au runtime MS Scripting («Microsoft Scripting Runtime»). Selon le commentaire de @ regjo, allez dans Outils-> Références et cochez la case «Microsoft Scripting Runtime».
Créez 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 définir le dictionnaire Nothing
lorsque vous avez fini de l'utiliser.
Set dict = Nothing
keyed
.
Dim dict As New Scripting.Dictionary
sans la référence. Sans la référence, vous devez utiliser la CreateObject
méthode de liaison tardive pour instancier cet objet.
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' Collection
objet effectue des recherches basées sur des clés à l'aide d'un hachage, donc c'est rapide.
Vous pouvez utiliser une Contains()
fonction 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 courtContains()
merci à @TWiStErRob.
Edit 25 septembre 2015 : Ajouté Err.Clear()
grâce à @scipilot.
ContainsKey
; une personne qui ne lit que l'invocation peut la confondre pour vérifier qu'elle contient une valeur particulière.
VBA n'a pas d'implémentation interne d'un dictionnaire, mais à partir de VBA, vous pouvez toujours utiliser l'objet dictionnaire 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'occurrence.
En dehors 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
À partir de la réponse de cjrh , nous pouvons créer une fonction Contains ne nécessitant aucune étiquette (je n'aime pas utiliser d'é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 rendre un Collection
comportement plus semblable à un Dictionary
. Il permet toujours des collections récursives. Vous remarquerez que Key vient toujours en premier car il était obligatoire et plus logique dans ma mise en œuvre. J'ai aussi utilisé seulementString
clés. Vous pouvez le modifier si vous le souhaitez.
J'ai renommé cela pour définir car il écrasera 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
Le err
truc est pour les objets puisque vous passeriez des objets en utilisant set
et des variables sans. Je pense que vous pouvez simplement 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
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
Ne jette pas s'il n'existe pas. S'assure juste qu'il est supprimé.
Private Sub cRemove(ByRef Col As Collection, Key As String)
If cHas(Col, Key) Then Col.Remove Key
End Sub
Obtenez 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
Si, pour une raison quelconque, vous ne pouvez pas installer de fonctionnalités supplémentaires sur votre Excel ou si vous ne le souhaitez pas, vous pouvez également utiliser des tableaux, au moins pour des problèmes simples. Comme WhatIsCapital vous mettez le 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
Dim
mot-clé, Country
et Capital
doit être déclarée comme Variante en raison de l'utilisation de Array()
, i
doit être déclarée (et doit être si Option Explicit
est définie), et le compteur de boucles va générer une erreur hors limite - plus sûr pour utiliser UBound(Country)
pour la To
valeur. Il convient également de noter que bien que la Array()
fonction soit un raccourci utile, ce n'est pas la manière standard de déclarer des tableaux dans VBA.
Tous les autres ont déjà mentionné l'utilisation de la version scripting.runtime de la classe Dictionary. Si vous ne pouvez pas utiliser cette DLL, vous pouvez également utiliser cette version, ajoutez-la simplement à votre code.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
Elle est identique à la version de Microsoft.