web-dev-qa-db-ja.com

VBAは辞書構造を持っていますか?

VBAは辞書構造を持っていますか?キー<>値の配列が好きですか?

252
fessGUID

はい。

MS Scripting runtime( 'Microsoft Scripting Runtime')への参照を設定します。 @ regjoのコメントに従って、[ツール] - > [参照設定]に移動し、[Microsoft Scripting Runtime]のチェックボックスをオンにします。

References Window

以下のコードを使用して辞書のインスタンスを作成します。

Set dict = CreateObject("Scripting.Dictionary")

または

Dim dict As New Scripting.Dictionary 

使用例

If Not dict.Exists(key) Then 
    dict.Add key, value
End If 

使い終わったら、辞書をNothingに設定することを忘れないでください。

Set dict = Nothing 
326
Mitch Wheat

VBAにはコレクションオブジェクトがあります。

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

Collectionオブジェクトはハッシュを使用してキーベースのルックアップを実行するので、高速です。


Contains()関数を使用して、特定のコレクションにキーが含まれているかどうかを確認できます。

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

2015年6月24日編集:@TWiStErRobのおかげでContains()が短くなりました。

2015年9月25日編集:@scipilotのおかげでErr.Clear()を追加しました。

170
Caleb Hattingh

VBAには辞書の内部実装はありませんが、VBAからは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
42
Jarmo

出現頻度を含めるのに役立つ追加の辞書の例。

ループの外側:

Dim dict As New Scripting.dictionary
Dim MyVar as String

ループ内

'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

頻度を確認するには:

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
29
John M

構築する cjrh's answer 、ラベルを必要としないContains関数を構築することができます(ラベルを使うのは嫌いです)。

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

私のプロジェクトでは、CollectionDictionaryのように動作させるためのヘルパー関数のセットを書きました。それはまだ再帰的なコレクションを可能にします。 Keyは必須であり、私の実装ではより理にかなっているので、Keyが常に最初に来ることに気付くでしょう。私もStringキーだけを使いました。あなたが好きならあなたはそれを元に戻すことができます。

セット

古い値を上書きするため、これをsetに変更しました。

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

errは、setを使用し、変数を使用せずにオブジェクトを渡すため、オブジェクト用です。私はあなたがそれが物であるかどうかただチェックすることができると思います、しかし私は時間をかけて押されました。

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

あり

この投稿の理由...

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

削除する

存在しない場合はスローしません。それが削除されていることを確認してください。

Private Sub cRemove(ByRef Col As Collection, Key As String)
    If cHas(Col, Key) Then Col.Remove Key
End Sub

キー

キーの配列を取得します.

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
Evan Kennedy

はい。 VB6 、VBA(Excel)、および VB.NET の場合

6

スクリプト実行時辞書には、高度な段階でデザインを台無しにする可能性のあるバグがあるようです。

辞書の値が配列の場合、辞書を参照して配列に含まれる要素の値を更新することはできません。

6
Kalidas

何らかの理由でExcelに追加機能をインストールできない場合、またはインストールしたくない場合は、少なくとも簡単な問題で配列を使用することもできます。 WhatIsCapitalとしてあなたは国の名前を入れて、関数はあなたにその首都を返します。

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
user2604899

他のすべての人はすでにscripting.runtimeバージョンのDictionaryクラスの使用について言及しています。このDLLを使用できない場合は、このバージョンも使用できます。単にコードに追加してください。

https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls

マイクロソフトのバージョンと同じです。