La VBA a-t-elle une structure de dictionnaire?

Ne VBA ont dictionnaire de la structure? Comme le tableau de valeurs de la touche?

230
demandé sur DaveInCaz 2009-05-27 16:00:03

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".

References Window

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 
297
répondu Mitch Wheat 2018-07-27 10:53:30

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.

158
répondu Caleb Hattingh 2016-08-12 20:04:46

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
37
répondu Jarmo 2009-05-27 12:19:03

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
27
répondu John M 2012-11-26 13:04:35

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
9
répondu Evan Kennedy 2017-05-23 12:10:44

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.

6
répondu Kalidas 2011-11-02 18:36:53

Oui. Pour VB6 , VBA (Excel), et VB.NET

6
répondu Matthew Flaschen 2012-07-26 12:13:23

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
4
répondu user2604899 2013-08-22 12:29:55

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.

2
répondu Michiel van der Blonk 2015-11-23 01:27:04