データの重複削除(ユニーク化)をする場合にDictionaryオブジェクトを使う基本的な方法を簡潔に紹介します。
Dictionaryオブジェクト(連想配列)とは
Dictionaryオブジェクトとはキー(Key)とデータ(item)をセットで格納して、重複のないデータを管理できるもので,、重複が許されないキー(Key)にデータ(item)を紐づけていきます。
Dictionaryオブジェクトの使い方
Dictionaryオブジェクトを使う場合は、Dictionaryオブジェクトを生成する必要があります。生成方法は2種類あります。
CreateObject関数
Dim 変数名 As Object
Set 変数名 = CreateObject("Scripting.Dictionary")
参照設定
「ツール」→「参照設定」→「Microsoft Scripting Runtime」にチェックを入れます。
※参照設定の場合は、ブックごとに行う必要がありますのでご注意ください。
「Dictionary」サンプル1
それでは実際にDictionaryオブジェクトの動きを確認したいと思います。
A列にコード、B列に商品があります。コードをKey、商品をitemにして重複削除を行います。(※赤字はキーの重複です)重複削除した一覧はイミディエイトウィンドウに出力します。
Sub ex1()
Dim Dic As Object
Set Dic = CreateObject("Scripting.Dictionary")
Dim rng As Range
Dim max As Long
Dim r As Long
max = Cells(Rows.count, 1).End(xlUp).Row
For r = 2 To max
Dic(Cells(r, 1).Value) = Cells(r, 2).Value
Next
Dim itm As Variant
For Each itm In Dic
Debug.Print itm & vbTab & Dic(itm)
Next
End Sub
ディクショナリ名(キー名)=アイテム名(データ)
Dic(Cells(r, 1).Value) = Cells(r, 2).Value
このコードでDictionaryに要素を追加していきます。つまりキーとアイテムを紐づけます。
※必ずValueプロパティを省略しないように注意してください。
①B列のくだものが格納されています。
②A列のコードがKeyとなります。重複があった場合は、上書きされます。
③itm変数にItemを格納して出力します。(次項目解説)
アイテムの取り出し
For Each itm In Dic.Items
Debug.Print itm
Next
Dictionaryのデータの取り出しに、For Each文を使っています。
For Each文はコレクションの中からコレクションの各要素を取り出す場合に使用します。今回はitemsコレクションから各itemを取り出しています。
Dic.Itemsは生成したオブジェクト変数のItemsコレクションという意味です。
結果:赤字部分は重複データなので除外されます。それ以外が出力されます。
キーとアイテムの取り出し
因みにキーとアイテムを取り出す場合は以下のようになります。
For Each itm In Dic
Debug.Print itm & vbTab & Dic(itm)
Next
For Each文にDictionaryオブジェクトを表すDic(オブジェクト変数)を入れます。
Dictionaryオブジェクトを入れると各キーが取り出されてるので、Dic(itm)とキーを指定することでitem(データ)を取り出すことができます。
BA100本ノック題材
VBA100本ノック17本目を題材にして、もう1つDictionaryオブジェクトを見ていきます。
「社員」シートの社員一覧表から部・課マスタを作成します。
「部コード」フィールドと「課コード」フィールド(※赤枠部分)を基準(Key)にして重複削除します。そして下の画像のように「部・課マスタ」シートに出力します。
Sub VBA100_17_Dic()
Dim Dic As Dictionary
Set Dic = New Dictionary
Dim Wd As String
Dim max As Long, r As Long
Dim inws As Worksheet: Set inws = Sheets("社員")
Dim outws As Worksheet: Set outws = Sheets("部・課マスタ")
max = inws.Cells(inws.Rows.count, 1).End(xlUp).Row
For r = 2 To max
Wd = inws.Cells(r, 3).Value & vbTab & inws.Cells(r, 4).Value
If Not Dic.Exists(Wd) Then
Dic.Add Wd, inws.Cells(r, 3).Resize(, 4).Value
End If
Next
r = 2
outws.Cells.ClearContents
Dim v As Variant
outws.Range(Cells(1, 1), Cells(1, 4)).Value = Array("部コード", "課コード", "部名称", "課名称")
For Each v In Dic.Items
outws.Range(Cells(r, 1), Cells(r, 4)) = v
r = r + 1
Next
outws.Range("A1").CurrentRegion.Sort outws.Range("A1"), xlAscending, outws.Range("B1"), , xlAscending, , , xlYes
Set Dic = Nothing
End Sub
Addメソッド
ディクショナリ名.Add キー名、アイテム名(データ)
Dic.Add Wd, inws.Cells(r, 3).Resize(, 4).Value
先ほどサンプルでディクショナリに要素を追加していくやり方がありました。
Dic(Cells(r, 1).Value) = Cells(r, 2).Value
こちらはキーの重複があった場合に上書きされて登録されます。
Addメソッドは同じようにDictionaryに要素を追加しますが、キーに重複があった場合にエラーとなります。
Existsメソッド
ディクショナリ名.Exists キー名
If Not Dic.Exists(Wd) Then
Dic.Add Wd, inws.Cells(r, 3).Resize(, 4).Value
End If
Existsメソッドはキーの重複があればTUREを、重複がなければFALSEを返します。
よって、Not演算子とif文の条件分岐を使って、重複がなければ、要素を追加するようにしています。
Set Dic = Nothing
Set Dic = Nothingでオブジェクトへの参照を解除します。必須ではないですが、基本的には記述します。
キー(Key)に複数のデータ(item)を紐づけたい場合は、こちらの記事をご覧ください↓
まとめ
Dictionaryとそのメソッド、Dictionaryで管理しているKeyとitemを出力する方法を簡潔に紹介しました。是非参考にしてみてください。
コメント