VBAの動的配列でReDim Preserveを繰り返して可読性が落ちたり、処理速度が落ちて困ったことがありました。 そこで私は大量のデータを名寄せする際、配列のループ処理に限界を感じてDictionaryオブジェクトに乗り換えました。 結果、コードが劇的にスッキリし、保守性も上がりました。そこでよく使っている実装方法を紹介します。

Dictionaryオブジェクトについて

VBAで使える連想配列のオブジェクトです。キーと値をセットとして要素の追加、削除、存在チェックなど基本的なメソッドが使えます。

変数宣言と設定方法

Dictionaryには2種類の設定方法があります。

1. 実行時バインディング(推奨)

実務では、自分一人が使うツールなら「参照設定」で良いのですが、社内の他部署に配布する場合は、参照設定のズレで動かなくなるトラブルが多発します。 そのため、私は配布用ツールでは必ず「実行時バインディング(CreateObject)」を使うようにしています。

Dim dictionary As Object: Set dictionary = CreateObject("Scripting.Dictionary")

2. 参照設定(Early Binding)

VBEのメニューから [ツール] > [参照設定] > [Microsoft Scripting Runtime] にチェックを入れます。入力候補が表示されるようになり、開発効率が上がります。

Dim dictionary As New Scripting.Dictionary

注意点:Mac環境での利用について Scripting.Dictionary はWindows専用のライブラリ(scrrun.dll)を使用しているため、Mac版のExcelでは動作しません。 Mac環境を含むマルチプラットフォームで開発する場合は、VBA標準の Collection オブジェクトや、自作のクラスで代替する必要があります。

使い方例

要素の追加

Call dictionary.Add("1", "value")
dictionary("2") = "value2"
Debug.Print dictionary("1")

キーは必須で数値型でも指定できます。(Collection型は文字列のみ)

要素の存在確認

If dictionary.Exists("1") Then
    Debug.Print "存在します"
End If

配列のループ

Dim key As Variant
For Each key In dictionary
    Debug.Print key & ":" & dictionary(key)
Next

要素の削除

Call dictionary.Remove("1")
Call dictionary.RemoveAll()

擬似的にプロパティを連想配列に定義

Dim user As Object: Set user = CreateObject("Scripting.Dictionary")
user("ID") = 101
user("Name") = "田中"
user("Role") = "Admin"

Dim k As Variant
For Each k In user
    Debug.Print k & "は" & user(k)
Next

リストから重複を除いたユニークなIDだけを抽出する

Dim cell As Range
For Each cell In Range("A2:A100")
    If Not dictionary.Exists(cell.Value) Then
        dictionary.Add cell.Value, True
    End If
Next

配列との比較

機能配列Dictionary
検索ループが必要Existsで一瞬
サイズ変更ReDimが必要自動で拡張
要素の削除困難Removeで容易
Mac環境利用可能利用不可

Dictionaryオブジェクトを推奨してきましたが、要素数が固定のときは単純な配列を使ったほうが使いやすいこともあります。

参考サイト



関連記事