VBA ha una struttura di dizionario? Ti piace la chiave <> array di valori?
VBA ha una struttura di dizionario? Ti piace la chiave <> array di valori?
Risposte:
Sì.
Impostare un riferimento al runtime di MS Scripting ("Microsoft Scripting Runtime"). Come da commento di @ regjo, vai su Strumenti-> Riferimenti e seleziona la casella "Microsoft Scripting Runtime".
Crea un'istanza di dizionario usando il codice seguente:
Set dict = CreateObject("Scripting.Dictionary")
o
Dim dict As New Scripting.Dictionary
Esempio di utilizzo:
If Not dict.Exists(key) Then
dict.Add key, value
End If
Non dimenticare di impostare il dizionario su Nothing
quando hai finito di usarlo.
Set dict = Nothing
keyed
.
Dim dict As New Scripting.Dictionary
senza il riferimento. Senza il riferimento, è necessario utilizzare il CreateObject
metodo di associazione tardiva per creare un'istanza di questo oggetto.
VBA ha l'oggetto di raccolta:
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
oggetto esegue ricerche basate su chiave utilizzando un hash, quindi è veloce.
È possibile utilizzare una Contains()
funzione per verificare se una determinata raccolta contiene una chiave:
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
Modifica 24 giugno 2015 : Contains()
abbreviato grazie a @TWiStErRob.
Modifica il 25 settembre 2015 : aggiunto Err.Clear()
grazie a @scipilot.
ContainsKey
; qualcuno che legge solo l'invocazione può confonderlo per verificare che contenga un valore particolare.
VBA non ha un'implementazione interna di un dizionario, ma da VBA è ancora possibile utilizzare l'oggetto dizionario da 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 esempio di dizionario aggiuntivo utile per contenere la frequenza di occorrenza.
Al di fuori del ciclo:
Dim dict As New Scripting.dictionary
Dim MyVar as String
All'interno di un ciclo:
'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
Per verificare la frequenza:
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
Costruendo la risposta di cjrh , possiamo creare una funzione Contains che non richiede etichette (non mi piace usare le etichette).
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
Per un mio progetto, ho scritto una serie di funzioni di supporto per rendere un Collection
comportamento più simile a un Dictionary
. Permette ancora raccolte ricorsive. Noterai che Key viene sempre per primo perché era obbligatorio e aveva più senso nella mia implementazione. Ho anche usato solo le String
chiavi. Puoi cambiarlo se vuoi.
Ho rinominato questo per impostare perché sovrascriverà i vecchi valori.
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
La err
roba è per gli oggetti poiché passeresti usando oggetti set
e senza variabili. Penso che puoi solo verificare se si tratta di un oggetto, ma mi è stato premuto per tempo.
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
Il motivo di questo 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
Non getta se non esiste. Assicurati solo che sia stato rimosso.
Private Sub cRemove(ByRef Col As Collection, Key As String)
If cHas(Col, Key) Then Col.Remove Key
End Sub
Ottieni una serie di chiavi.
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
Se per qualsiasi motivo, non è possibile installare funzionalità aggiuntive in Excel o non si desidera, è possibile utilizzare anche array, almeno per problemi semplici. Come WhatIsCapital inserisci il nome del paese e la funzione ti restituisce la sua capitale.
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
parola chiave Country
e Capital
deve essere dichiarata come Varianti a causa dell'uso di Array()
, i
deve essere dichiarata (e deve essere se Option Explicit
è impostata), e il contatore del ciclo genererà un errore fuori limite - più sicuro per utilizzare UBound(Country)
per il To
valore. Inoltre, forse vale la pena notare che mentre la Array()
funzione è un collegamento utile, non è il modo standard per dichiarare le matrici in VBA.
Tutti gli altri hanno già menzionato l'uso della versione scripting.runtime della classe Dictionary. Se non si è in grado di utilizzare questa DLL, è possibile utilizzare anche questa versione, semplicemente aggiungerla al codice.
https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls
È identico alla versione di Microsoft.