VBAのDictionaryの使い方(全メソッドとプロパティ網羅)

Dictionaryオブジェクトとは

大量のデータを使う場合にはDictionaryはとても高速に動作するため有用な手段の1つになります。

Dictionaryオブジェクトはキーと値で1セットとなるデータ形式を持ちます。

他の言語であれば連想配列やハッシュマップなどの言い方をされます。

キーは値を検索するために使う「しおり」の役割を持ちます。

同じDictionaryオブジェクトの中でキーと値のセットは複数持つことも可能ですが、同一キーの重複は出来ません。

以下のようなデータ構造になります。

キー
1 111
2 222
3 333
“1” “111”
“2” “222”
“a” “aaaaa”
“b” “bbbb”
“c” “ccc”

事前準備

Dictionaryオブジェクトを利用するには2通りの方法があります。

1つはCreateObject関数を使う方法で、もう1つは参照設定を行う方法です。

どちらでも動作は変わりませんが、参照設定を行うと多少高速なこととメソッドやプロパティが入力候補で表示されます。

個人的には参照設定で利用することをお勧めします。

CreateObject関数を使う方法

書き方は以下のようになります。

参照設定を行う方法

VBA画面のツールメニュー→参照設定を選び、参照設定ダイアログで「Microsoft Scripting Runtime」にチェックを付けます。

コードの書き方は以下のようになります。

なお、1行で書いても構いません。

厳密には1行で書かない方がいいのですが、普通に利用する分では問題は発生しませんので1行でも構いません。

私自身も1行で書くことが多いです。

このことについての詳細は「VBAでクラス変数の宣言とNewを1行で書いてよいか」をご参照ください。

メソッドとプロパティ

Dictionaryオブジェクトには以下のメソッドとプロパティがあります。

それぞれの引数の「key」はキー、「Item」は値を指します。

メソッド

Sub Add(Key, Item) 新しいキーと値のセットを追加します。

既に追加されているキーの上書きはエラーになります。

Function Exists(Key) As Boolean 指定したキーが含まれているか確認します。

含まれていればTrue、そうでなければFalseを返します。

Function Items() Dictionaryオブジェクトに含まれる全ての値を配列で返します。

配列内で値が重複していることが

Function Keys() Dictionaryオブジェクトに含まれる全てのキーを配列で返します。
Sub Remove(Key) 指定したキーの要素を削除します。
Sub RemoveAll() Dictionaryオブジェクトに含まれる全ての要素を削除します。

プロパティ

Property CompareMode As CompareMethod キーのあいまい検索を許可するかどうかをCompareMethod列挙型の定数で指定します。

Itemプロパティなどで使うキーがDictionaryオブジェクトに格納されているキーと厳密に同じでなければならない場合はBinaryCompareを指定し、大文字・小文字、ひらがな・カタカナ、全角・半角の区別せずに行う場合はTextCompareを指定します。

あくまでも検索する際のキーの条件のため、テキスト比較を設定してもキーの重複が許されるわけではありません。

Dictionaryオブジェクトにデータがセットされている状態ではエラーになります。

CompareMethod列挙型

定数 内容
BinaryCompare 0 バイナリ比較(大文字・小文字、ひらがな・カタカナ、全角・半角を区別します)
TextCompare 1 テキスト比較(大文字・小文字、ひらがな・カタカナ、全角・半角を区別しません)
Property Count As Long キーと値のセットの数を返します。
Property Item(Key) 指定したキーに対応する値の設定および取得を行います。
Property Key(Key) キーを別のキーに変更します。

たとえばキー”1″を”2″に変更したい場合は「Dictionary.Key(“1”) = “2”」のように記述します。

一般的な使い方のサンプル

Dictionaryクラスの全てのメソッドとプロパティを使ったサンプルです。

Dictionaryクラスの各メソッドやプロパティには書き方が分かりにくいものもありますので、不明なものはコードをご参考ください。

配列よりDictionaryクラスを使う利点

Dictionaryクラスとよく比較対象とされるのが配列です。

Dictionaryと配列との違いは、キーがあるかないかですが、それによりデータの格納方式にも違いがあります。

配列は先頭から順にデータが並んだ状態でデータを格納しますが、Dictionaryにはデータの並び順は持っておらず、あくまでもキーが基準になります。

そのため、並び順が重要な意味を持つ場合には後述するキーのソートを行うか、もしくは、Dictionaryクラスよりも配列を利用した方がよい場合があります。

また、配列はデータを格納するための領域をRedim構文やRedim Preserve構文で確保する必要がありますが、Dictionaryにはその必要がありません。

Dictionaryは配列と違ってキーでデータを特定できるため、高速にデータの選別が可能であるという特性があります。

そのため、多数のデータの中から特定のデータを抽出する、という処理を行う場合は配列よりも圧倒的にDictionaryクラスを使った方が高速に処理できます

もし配列でのデータ抽出を繰り返し行うような処理で遅いと感じることがあるのであれば「VBAで配列を連想配列Dictionaryに変換する」をご参照ください。

キーと値に登録できるデータの種類

Dictionaryを使う際に、キーと値にセットするデータは数値や文字列が多いと思いますが、オブジェクトなどを格納することも可能です。

キーにはオブジェクトを指定することができます。

値にはオブジェクト(例:Range(“A1”))や配列や戻り値を返す関数(例:Timer)なども指定できます。

キーに配列をセットすることは出来ません。

以下のように、キーにRangeオブジェクト、値にワークシートをセットしたり、値に配列をセットしたりすることが出来ます。

また、キーに使う数値と文字列は別物として扱われます。

以下のコードにもありますが、1と”1″は重複せずにどちらもキーとして設定されます。

未登録のキーだけを追加したい場合

Dictionaryオブジェクトに未登録のキーだけを追加したい場合は、事前にExistsメソッドで対象のキーが追加済みかどうかを判定した上で、未追加であれば追加するようにします。

以下のような感じになります。

キーの上書きをしたい場合

追加済みのキーに対してAddメソッドを実行するとエラーになります。

他の言語のハッシュマップなどではAddメソッドのような追加メソッドで直接上書きが出来るものもありますが、VBAのDictionaryクラスではそれは出来ません。

そこでVBAでは疑似的に別の方法で上書きを行うことになります。

上書きの方法には2通りあります。

Itemプロパティを使って値の書き換えを行う方法と、Removeメソッドで削除してからAddメソッドで追加する方法です。

どちらの方法でも構いませんがItemプロパティでの書き換えの方が手間が少ない分、処理速度も速いです。

以下のコード内でそれぞれの方法を紹介します。

関数の引数でDictionaryクラスを使う場合

Dictionaryオブジェクトを関数の引数としてやり取りを行う場合に、渡した関数側での処理が呼び出し元にも反映されます。

Integer等の数値型やStringの文字列型の場合は関数の引数にByRef指定をしないと呼び出し元にも引き継がれませんが、DictionaryはByRefを付けなくても渡した関数での編集内容が呼び出し元にも反映されます。

以下のサンプルは呼び出し元で1と2を追加し、関数を呼び出してその関数内部で3を追加し、呼び出し元でDictionaryの全てのキーに対応する値を出力しています。

出力すると呼び出し先の関数で追加された3も一緒に出力され、ByRef指定をしなくても関数間で引き継がれていることが分かります。

全キーをソートする方法

Dictionaryクラスのキーはソートの仕組みがありません。

ただ、場合によってはキーがソートされていた方が都合がいい場合があります。

そのままではソートはできませんので、Keysプロパティで全てのキーを配列として取得して、その全キー配列をソートする方法を行います。

ソートの方法にはいくつかあります。

よく紹介されるソート方法はワークシートの指定セル範囲を並べるSortメソッドを使う方法だと思いますが、個人的にはこの方法は避けた方がよいと思っています。

理由は、ソートのためにワークシートやセルを用意しなければならず、使ったあとに削除も必要になりますし、セルへの値の設定や操作は処理が遅いため、せっかくのDictionaryクラスを使っている高速性の利点が犠牲になってしまうためです。

そこで、高速にソートを行うためには2通りの方法があります。

1つはソート処理を実装する方法で、もう1つは.NETのArrayListクラスのSortメソッドを利用する方法です。

どちらを使ってもいいのですが、.NETの利用はあまりメジャーな方法ではないため、ここではクイックソートを実装する方法を紹介します。

ここでは利用しませんがArrayListクラスのSortメソッドについては「VBAの配列を.NETのArrayListのSortで並べ替え」をご参照ください。

クイックソートについての詳細は「VBAの配列をクイックソートで並べ替え」ご参照ください。

コードはリンク先のをそのまま使っています。

実行すると、クイックソート後は”8″ “9” “10”の順になります。

関連記事

サブコンテンツ

このページの先頭へ