【VBA】Dictionary(辞書型)の便利な使い方(データ位置の特定)
VBAでDictionaryオブジェクトを使ったことはありますか?
存在は知っていても使ったことは無い、という人も多いかと思います。
私もその内の一人だったのですが、先日マクロの開発をしていた時に非常に便利な使い方があることに気付きました。
連想配列を使ったことないよって人は一度試してみてください。
変化のあるデータを扱う時には重宝します。
連想配列(Dictionary)でデータ位置を特定する方法
データを扱う時、大抵1番上のセルに見出しが入っていますよね。
そして、データを取得するためにはA列のどこか、B列のどこか、といった具合にデータ位置を特定すると思います。
しかし、このやり方だとデータの位置がずれた場合に対応することができません。
if文を駆使してデータ位置を特定することもできますが、この時に連想配列(Dictionary)を使えば可読性が良く、汎用性のある対策を取ることができます。
サンプルコード
連想配列(Dictionary)を使った解決策はこれです。
Sub HeaderDic()
'見出しの右端を取得
Dim headerRight As Integer: headerRight = Cells(1, Columns.Count).End(xlToLeft).Column
'見出しの連想配列を作成
Dim objDic As Object: Set objDic = CreateObject("scripting.dictionary")
Dim oneCell As Variant
For Each oneCell In Cells(1, 1).Resize(1, headerRight)
objDic(oneCell.Value) = oneCell.Column
Next
'各項目にデータの入力
Cells(2, objDic("項目①")).Value = "xxx"
Cells(2, objDic("項目②")).Value = "yyy"
Cells(2, objDic("項目③")).Value = "zzz"
End Sub
ポイントとなるのは次の4行です。
Dim oneCell As Variant
For Each oneCell In Cells(1, 1).Resize(1, headerRight)
objDic(oneCell.Value) = oneCell.Column
Next
Cells(1, 1).Resize(1, headerRight)の部分で、見出し部分のRangeオブジェクトを取得しています。
そして、For Each文によって、このRangeオブジェクトから1つずつセルをoneCellに取り出しています。
objDic(oneCell.Value) = oneCell.Column
そして、見出しの項目名とその位置(列)を連想配列へ格納しています。
- キー:見出しの項目名(oneCell.Value)
- 中身:見出しの位置(oneCell.Column)※Columnプロパティ:セルの列数を取得
これで、見出しの内容と位置が紐づけされたため、objDic(“項目名")と書くとその項目の位置を取得することができます。
サンプルコードの最後に一例としてデータ入力するコードを入れています。
※具体的にはobjDic(“項目①")は1を返しています。
'各項目にデータの入力
Cells(2, objDic("項目①")).Value = "xxx"
Cells(2, objDic("項目②")).Value = "yyy"
Cells(2, objDic("項目③")).Value = "zzz"
連想配列とするメリット
見出し部分を連想配列とするメリットは2つあります。
1つはデータの項目位置がずれても問題ないことです。
上の画像のように項目の位置がずれても、入力項目は自動的に追従します。
もう1つは可読性です。
セルの位置を数字にしていると、コードを書いている時に「この部分って何のデータだっけ?」と首をかしげることが意外とあります。
この連想配列ならば、項目名がすぐそばにあるためこのような混乱に繋がることがありません。