Excel

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

k.w
\お買い物マラソン開催中/
スポンサーリンク

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を足すと、実装が安定します。

ABOUT ME
スポンサーリンク
記事URLをコピーしました