Excel VBA Dictionaryの使い方

ExcelVBA-基礎編

今回はDictionary(連想配列)の使い方をご説明します。

Dictionaryは字のごとく、辞書の様に扱います。

Key(キー)とItem(データ)をセットで格納して、リストなどを作成するときに使用します。

Dictionaryは処理が非常に高速ですが、記述方法によってはとても遅くなります。

その方法と比較をまとめましたので、使い方と併せて知りたい方は「Dictionaryを確実に高速処理する方法と比較」をご覧下さい。

また、Dictionaryを活用したVlookup関数や、Countif関数の高速化についても掲載していますので、下記記事をご覧ください。

1.Dictionary(連想配列)の使い方

DictionaryはKeyとItemとをセットで格納します。

ただし、重複したKeyを格納する事は出来ません

Dictionaryの特徴は格納されているデータを指定する時に、Keyで指定してItemを取得出来ます

Dictionaryの宣言方法

Dictionaryの宣言はObject(オブジェクト)型で宣言します。

宣言しただけでは使用出来ず、「CreateObject関数」を使用して、変数に代入します。

Sub Sample1()

Dim myDic   As Object

Set myDic = CreateObject("Scripting.Dictionary")

End Sub

Dictionaryのデータ格納方法

Dictionaryへのデータ格納方法は「Add Key, Item」で、KeyとItemをそれぞれセットで格納します。

配列のインデックス番号は0から始まります。

格納されているデータの指定方法は、キー(Key)もしくはインデックス番号を使用して指定します。

キー(Key)を指定する事でセットになっているデータ(Item)を抽出する事が出来ます。

簡単なコードですが、宣言したDictionaryへKeyとItemを格納するサンプルコードです。

Sub Sample2()

    Dim myDic As Object
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
   
End Sub

Dictionaryのデータを参照する方法

Dictionaryへ格納されたデータを参照する方法はいくつかありますので、それぞれご説明します。

Dictionaryを直接Keyで参照する

Dictionaryに格納されているKeyとItemを直接参照する方法です。

変数名(Key)でセットになっているItemを取得出来ます

Sub Sample3()

    Dim myDic As Object
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
    
    MsgBox myDic("商品C") 'Keyを指定すると格納されているItemを抽出できます。

End Sub

Dictionaryを直接インデックスで参照する

Keyではなくインデックスでも指定可能です。

KeyもItemもインデックスは0から始まります。

変数名.Keys()(インデックス)、変数名.Items()(インデックス)と指定します。

ここで注意ですがKeys()(インデックス)のインデックスの前にも()が必要です。

Sub Sample4()

    Dim myDic   As Object
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
    
    MsgBox myDic.Keys()(0) & myDic.Items()(0) '格納した変数のインデックスでそれぞれ指定できます。
    
End Sub

KeyとItemを変数に代入して参照する

KeyとItemをそれぞれ変数に代入して、インデックスで指定します。

もちろん、変数に代入したKeyを使用して直接参照も可能です。

Sub Sample5()

    Dim myDic   As Object
    Dim myKey   As Variant
    Dim myItem  As Variant
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
    
    myKey = myDic.keys 'Keyを変数に代入
    myItem = myDic.Items 'Itemを変数に代入
    
    MsgBox myKey(0) & myItem(0) '格納した変数のインデックスでそれぞれ指定できます。
    
End Sub

変数に代入したKeyを使用して参照する場合は代入した変数のインデックスで指定します。

Sub Sample6()

    Dim myDic   As Object
    Dim myKey   As Variant
    Dim myItem  As Variant
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
    
    myKey = myDic.Keys 'Keyを変数に代入
    
    MsgBox myDic(myKey(0)) 'Keyを指定すると格納されているItemを抽出できます。
    
End Sub

DictionaryのデータをRemoveで削除する

格納されたデータを削除する場合は「Remove」で削除することが出来ます。

変数名.Remove Key」と記載します。

Sub Sample7()

    Dim myDic   As Object
    Dim myKey   As Variant
    Dim myItem  As Variant
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000
    
    myDic.Remove "商品B"
    
End Sub

Existsで格納されているか判定する

Dictionaryのデータを操作する際に、追加や削除をする場合、重複したKeyを格納しようとしたり、格納されていないKeyを削除しようとした場合 エラーになります。

そこで、処理をする前に「Exists」で格納されているか判定します。

「If 変数名.Exists(Key) then」で格納されているか判定できます。

変数名の前に「Not」を付ける事で格納されていないか判定可能です。

ここは、慣れるまでNotの有無などで混乱しがちになります。

次のコードは格納されていなければ格納というコードです。

Sub Sample8()

    Dim myDic   As Object
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    
    If Not myDic.exists("商品E") Then '商品Eが格納されているか判定
    
        myDic.Add "商品E", 5000 '未登録の場合追加
    
    End If
    
End Sub

次のコードは格納されていれば削除のコードです。

Sub Sample9()

    Dim myDic   As Object
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    'Key、ItemとAddで追加します。
    myDic.Add "商品A", 1000 'DictionaryのKeyに商品名、Itemに価格を格納
    myDic.Add "商品B", 2000
    myDic.Add "商品C", 3000
    myDic.Add "商品D", 4000
    myDic.Add "商品E", 5000

    If myDic.exists("商品E") Then '商品Eが格納されているか判定
    
        myDic.Remove "商品E" '登録済みの場合削除
    
    End If

2.Dictionaryをループで操作する

実際にDictionaryを扱う場合、ループやIF文で処理する事がほとんどです。

Dictionaryのループ方法もいくつか方法あるので、それぞれご説明します。

Dictionary の要素数は「変数名.Count-1」で指定するか、別の変数にKeyを代入した場合は「UBound(代入した変数名)」で指定します。

DictionaryをFor~Nextで操作する

For~Nextでデータを追加し、条件に合うデータを出力するコードです。

今回は「変数名.Keys()(インデックス)、変数名.Items()(インデックス)」の記述方法で、直接参照していますが、もちろんKeyとItemの指定方法は上記で説明した方法すべてで対応可能です。

Sub Sample10()

    Dim myDic   As Object
    Dim i       As Long
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    For i = 1 To 10
    
        If Not myDic.exists("商品" & i) Then 'ループで格納されているか判定
    
            myDic.Add "商品" & i, i '未登録の場合追加
        
        End If
    
    Next i
    
    For i = 0 To myDic.Count - 1
    
        If myDic.Keys()(i) = "商品5" Then '商品5の場合
        
            MsgBox myDic.Keys()(i) & myDic.items()(i) 'KeyとItemを表示
            Exit For
            
        End If
    
    Next i
    
End Sub

DictionaryをFor Each In Nextで操作する

「For Each In Next」で操作する場合は、格納されているKeyを取得することが出来ます。

Sub Sample11()

    Dim myDic   As Object
    Dim Dic     As Variant
    Dim i       As Long
    
    Set myDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    For i = 1 To 10
    
        If Not myDic.exists("商品" & i) Then 'ループで格納されているか判定
    
            myDic.Add "商品" & i, i '未登録の場合追加
        
        End If
    
    Next i
    
    For Each Dic In myDic 'Keyが格納される
    
        If Dic = "商品5" Then 'Keyが商品5の場合
        
            MsgBox Dic & myDic(Dic) 'KeyとItemを表示
            Exit For
            
        End If
    
    Next
    
End Sub

3.まとめ

DictionaryはKeyとItemをセットで格納でき、ループでの操作も比較的簡単です。

さらに直接Keyを指定する事でItemを取得できるため、工夫する事で大抵のことに対応できます。

また、直接KeyでItemを取得できるので、記述次第ではループで検索するなどの処理を、省略する事も出来ますので非常に便利だと思います。

タイトルとURLをコピーしました