VBA技術解説|Dictionary(ディクショナリー)による連想配列の使い方ガイド

Dictionaryの基本と連想配列の考え方
Dictionaryは、キーと値の組み合わせを入れる入れ物です。
配列は番号で取り出します。Dictionaryはキーで取り出します。
キーは文字列でも数値でも使えます。値はどんな型でも入ります。
同じキーは1つだけ持てます。キーが重なるとエラーになります。
Collectionも似ていますが、Dictionaryは検索が速い場面が多いです。
Dictionaryの得意分野は、重複の判定、件数の集計、参照置換です。
キーがあるので、VLOOKUPのような参照表の代わりにもなります。
小さなデータから中規模のデータ処理まで広く使えます。
DictionaryとCollectionはどう違う?
Collectionはキー検索の専用機能が弱いです。存在確認が苦手です。
DictionaryはExistsでキーの有無をすぐ調べられます。
また、KeysとItemsで配列を一気に取り出せます。
準備:参照設定と遅延バインディング
DictionaryはScripting.Dictionaryという部品を使います。
参照設定を行う方法と、参照なしで使う方法があります。
環境の制約や配布方法に合わせて選びます。
参照設定の手順は次の通りです。
- 1. VBAエディタで「ツール」→「参照設定」を開きます。
- 2. 一覧から「Microsoft Scripting Runtime」にチェックを付けます。
- 3. OKを押します。Scripting.Dictionaryが型指定で使えます。
参照設定ありの例です。
“`vba
Option Explicit
Sub NewDictionary_Early()
Dim dict As Scripting.Dictionary ‘型が使える
Set dict = New Scripting.Dictionary
dict.Add “A”, 1
Debug.Print dict(“A”)
End Sub
“`
参照設定なしでも使えます。CreateObjectを使います。
この方法は配布先で参照設定をしなくてよい利点があります。
“`vba
Option Explicit
Sub NewDictionary_Late()
Dim dict As Object ‘遅延バインディング
Set dict = CreateObject(“Scripting.Dictionary”)
dict.Add “A”, 1
Debug.Print dict(“A”)
End Sub
“`
参照設定なしの欠点は?
コード補完が弱くなります。メソッドの一覧が出ません。
定数や型のチェックも効きにくいです。記述ミスに注意が必要です。
基本操作:作成・追加・取得・更新・削除
Dictionaryのよく使う操作をまとめます。動く最小コードです。
“`vba
Option Explicit
Sub Dictionary_Basics()
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
‘追加 Add key, item
dict.Add “tokyo”, 13
dict.Add “osaka”, 8
‘取得 Item(key)
Debug.Print dict(“tokyo”) ’13
‘存在確認 Exists(key)
If dict.Exists(“nagoya”) Then
Debug.Print dict(“nagoya”)
Else
Debug.Print “not found”
End If
‘更新は代入でOK
dict(“tokyo”) = 14
‘削除 Remove / すべて削除 RemoveAll
dict.Remove “osaka”
‘個数 Count
Debug.Print dict.Count
‘キー一覧と値一覧 Keys / Items は配列
Dim ks As Variant, vs As Variant
ks = dict.Keys
vs = dict.Items
Dim i As Long
For i = LBound(ks) To UBound(ks)
Debug.Print ks(i), vs(i)
Next i
End Sub
“`
エラーを避けるには、Addの前にExistsで確認するのが安全です。
キーが重複するとAddでエラーになります。上書きは代入で行います。
キーが重複したらどうなる?
Addは重複キーでエラーになります。上書きしたいときは
`dict(key) = 新しい値` の形で代入します。存在しないと新規追加になります。
重複除去(ユニーク抽出)の基本レシピ
シートのリストから重複を除き、別列にユニークを出す例です。
A列のデータを読み、Dictionaryで重複を弾きます。
“`vba
Option Explicit
Sub UniqueWithDictionary()
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
Dim ws As Worksheet
Set ws = ActiveSheet
Dim last As Long, r As Long
last = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim v As Variant
For r = 1 To last
v = ws.Cells(r, 1).Value
If Not dict.Exists(v) Then dict.Add v, True
Next r
Dim arr As Variant
arr = dict.Keys ‘ユニーク値の配列
ws.Range(“B1”).Resize(UBound(arr) – LBound(arr) + 1, 1).Value = _
WorksheetFunction.Transpose(arr)
End Sub
“`
Keysを配列で受け取り、Transposeで縦に出力します。
大量データでは、Variant配列に一度に書き込むと速くなります。
大文字小文字は区別される?
既定では区別されません。`CompareMode`を`TextCompare`にすると
大文字小文字を無視します。`BinaryCompare`で区別します。
使い方パターン①:出現回数のカウント
同じ値がいくつあるかを数える処理です。カテゴリ別件数などに使えます。
“`vba
Option Explicit
Sub CountByKey()
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
Dim ws As Worksheet
Set ws = ActiveSheet
Dim last As Long, r As Long
last = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim k As Variant
For r = 1 To last
k = ws.Cells(r, 1).Value
If dict.Exists(k) Then
dict(k) = dict(k) + 1
Else
dict.Add k, 1
End If
Next r
‘結果を二列で出力(キー, 件数)
Dim ks As Variant, i As Long
ks = dict.Keys
For i = LBound(ks) To UBound(ks)
ws.Cells(i + 1, 2).Value = ks(i)
ws.Cells(i + 1, 3).Value = dict(ks(i))
Next i
End Sub
“`
件数は整数で持ちます。キーが空白やNullの行は先に除くと安定します。
数値キーと文字列キーが混ざるときは?
キーの型が混ざると別物になります。”1″と1は違います。
処理前にCStrやCLngでそろえると混乱を防げます。
使い方パターン②:参照テーブル化と結合
マスタ表をDictionaryにして、VLOOKUPの代わりに使います。
左表のキーを右表の値に置き換える処理が簡単に書けます。
“`vba
Option Explicit
Sub LookupByDictionary()
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
Dim ws As Worksheet
Set ws = ActiveSheet
‘A列:キー, B列:参照値 をマスタとして読み込み
Dim lastM As Long, r As Long
lastM = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
For r = 2 To lastM
If Not dict.Exists(ws.Cells(r, 1).Value) Then
dict.Add ws.Cells(r, 1).Value, ws.Cells(r, 2).Value
End If
Next r
‘D列のキーに対応する値をE列へ出力
Dim lastT As Long
lastT = ws.Cells(ws.Rows.Count, 4).End(xlUp).Row
For r = 2 To lastT
Dim k As Variant
k = ws.Cells(r, 4).Value
If dict.Exists(k) Then
ws.Cells(r, 5).Value = dict(k)
Else
ws.Cells(r, 5).Value = “(なし)”
End If
Next r
End Sub
“`
二つの表を結合したいときも同じ考え方で書けます。
値にレコードの配列や小さな型を入れると拡張できます。
キーが見つからない場合は?
Existsで確認し、見つからないときの扱いを決めます。
空文字を入れる、既定値を入れる、スキップする、などです。
注意点:速度・メモリ・型とエラー処理
大量データでは、画面更新や計算を止めると体感が大きく変わります。
また、シートと行き来する回数を減らし、配列でまとめて処理します。
“`vba
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
‘処理
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
“`
キーの型はそろえます。比較モードも目的に合わせて設定します。
“`vba
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
dict.CompareMode = vbTextCompare ‘大文字小文字無視
“`
エラー処理は最小限でも入れます。追加時はExistsで守ります。
Remove前にもExistsで確認します。無駄なエラーを避けられます。
遅いと感じたらどこを見直す?
シートとの読み書き回数、配列化の有無、画面更新と計算モード、
ループ内の無駄な参照を見直します。Keys/Itemsの取得回数も減らします。
サンプル集と早見表
短い断片コードをまとめます。必要なところを貼って使えます。
**雛形:新規作成**
“`vba
Dim dict As Object
Set dict = CreateObject(“Scripting.Dictionary”)
“`
**雛形:上書き(存在すれば更新、なければ追加)**
“`vba
If dict.Exists(k) Then
dict(k) = v
Else
dict.Add k, v
End If
“`
**キーの並べ替え(簡易)**
“`vba
Dim ks As Variant: ks = dict.Keys
Call QuickSortVariant ks, LBound(ks), UBound(ks) ‘任意のソート関数
‘並べ替え後にキー順で参照
“`
**Keys/Itemsの同時走査**
“`vba
Dim ks As Variant, it As Variant
ks = dict.Keys: it = dict.Items
Dim i As Long
For i = LBound(ks) To UBound(ks)
Debug.Print ks(i), it(i)
Next i
“`
早見表:主なメソッド/プロパティ
名前 | 用途 | 返り値/説明 |
---|---|---|
Add(key, item) | 追加 | キーが重複ならエラー |
Item(key) / dict(key) | 取得 | 値を返す。代入で更新 |
Exists(key) | 存在確認 | True/False |
Remove(key) | 削除 | 指定キーを削除 |
RemoveAll() | 全削除 | すべて消す |
Count | 件数 | 要素数 |
Keys() | キー配列 | Variant配列 |
Items() | 値配列 | Variant配列 |
CompareMode | 比較方法 | Text/Binary 比較 |
最小の雛形は?
最小はCreateObjectで作ってAddして使う形です。用途に応じて
ExistsやCompareModeを足すと、実装が安定します。