VBA Dictionaryで重複のないデータを作成 マクロ講座ー練習用ファイルがダウンロードできます。

マクロ講座VBA Dictionary 連想配列の使い方

VBA Dictionary 連想配列の使い方
VBA Dictionary 連想配列の使い方

マクロ 95回

Dictionary を使って重複したデータの中から重複しないリストを作成する

Dictionaryは vba を高速化したい 場合にかなり威力を発揮します。
そして具体的なメリットとしては辞書の 検索と存在の確認が高速にできるということです。
その結果 vba 全体が高速に動くというわけです。

この記事では、以下の内容について解説しています。

  • VBAのDictionaryオブジェクトについての説明
  • 重複したデータから重複しないリストを作成する方法の解説
  • Dictionaryを使った操作方法(キーと値の追加、存在確認など)
  • 配列と組み合わせたDictionaryの利用方法


(練習ファイルがダウンロードできます。 練習ファイルの配布)マクロコードは記述されていません。

連想配列を使って重複のないリストを作成する

  1. 前回はdictionary を使うために2つの方法があることを説明しました。 一つは CreateObject関数を使う方法と、もう一つは参照設定で Microsoft scripting runtimeを参照するようにチェックを 入れる方法です。
    Create Objectを使う場合は特に に何の準備もせずに Dictionaryを使うことができます。
    だったらこれが一番いいんじゃないかと思うかもしれませんが 一つ欠点があります。 というのはIntellisenseが働かないこと です。
    とくにまだDictioanryに慣れていない方は、ぜひMicrosoft の scripting runtime を参照設定してください。

    VBA Dictionaryの使い方、タイトル01
  2. シートの A1:B7までの範囲にわざと重複を作成しています。 これをその下に重複のないデータとして書き出すというコードを考えていきましょう。

    VBA Dictionaryの使い方、タイトル02
  3. 前回のコードは重複がない前提で、コードを書いて for 文で回していました。重複がある場合はfor 文の部分を変更していきます。

    VBA Dictionaryの使い方、タイトル03
  4. どのように変更したかと言うと 、for 文の中で if 文を使ってExistsメソッドで存在確認をしたわけです。

            If dic.Exists(data(i, 1)) = False Then
               dic.Add data(i, 1), data(i, 2) 'Dictionaryに登録
            End If
    
    VBA Dictionaryの使い方、タイトル04
  5. If dic.Exists(data(i, 1)) = False Then  のコードの部分ではdic.Exists(data(i, 1))でディクショナリに存在するか、=Falseでで存在しないならばという意味になります。
    false ならば辞書に追加する
    dic.Add data(i, 1), data(i, 2)

    VBA Dictionaryの使い方、タイトル05
    For i = 1 To UBound(data, 1)
        '登録されていない場合
        If dic.Exists(data(i, 1)) = False Then
           dic.Add data(i, 1), data(i, 2) 'Dictionaryに登録
        End If
    Next

重複データを削除するコードはどう書くか

  1. コードを実行した結果、辞書に重複しないデータを登録できました。そしてその結果を指定したセル範囲に書き出すことができました。

    VBA Dictionaryの使い方、タイトル06
    Sub dict02_a()
        Dim dic As New Scripting.Dictionary
        Dim data, i As Long
        data = Range("A2:B7")
    
        For i = 1 To UBound(data, 1)
            '登録されていない場合
            If dic.Exists(data(i, 1)) = False Then
               dic.Add data(i, 1), data(i, 2) 'Dictionaryに登録
            End If
        Next
        Range("A11").Resize(dic.Count) = _
        WorksheetFunction.Transpose(dic.Keys)
        Range("B11").Resize(dic.Count) = _
        WorksheetFunction.Transpose(dic.Items)
    End Sub
  2. Dictionary オブジェクトのメソッド

  3. Excel VBA の Dictionary オブジェクトには、以下のような主なメソッドがあります。

    Add
    キーと値のペアを辞書に追加します。
    Remove
    指定したキーを持つ要素を辞書から削除します。
    Exists
    指定したキーを持つ要素が辞書に存在するかどうかを調べます。
    Item
    指定したキーを持つ要素の値を取得します。
    Items
    辞書内のすべての値を配列で返します。
    Keys
    辞書内のすべてのキーを配列で返します。
    Count
    辞書内の要素の数を取得します。
    CompareMode
    辞書内のキーの比較方法を設定します。
  4. 今度は、 キーとアイテムだけでは比較できないケースを考えます。
    たとえば、キーにしたい列が2つあるような場合です。そのようなときはどのような工夫が必要でしょうか?

    例えば、下記の表のように、列を追加してくだものにA品B品があるとします。個数をキーとしたいのですが、重複を削除できるのでしょうか?

    VBA Dictionaryの使い方、タイトル08
  5. 重複しないリストを高速で作るのが目的ですから、辞書にこだわる必要はありません。Keyひとつ、Itemひとつの組み合わせですが、そこを工夫しましょう。
    配列で受けとったデータを受け取るリストという空の配列を用意します。

    そして重複確認するのは、data(i, 1) & "-" & data(i, 2)というMelonとAをつなげた値です。
    dic.に追加するのは、data(i, 1) & "-" & data(i, 2)という連結したデータが無かった時だけです。

    VBA Dictionaryの使い方、タイトル07
  6. わざわざ辞書に追加していますが、その辞書が目的ではないのです。
    目的は、そのあとに追加しているリストなのです。

    辞書dicは重複を見つけるためにだけ利用しています。
    data(i, 1) & "-" & data(i, 2)という形で書き出すのでは、また仕事が増えてしまいますから、
    ReDim list(1 To UBound(data, 1), 1 To 3)と、
    リストlistを作成したわけです。

    VBA Dictionaryの使い方、タイトル09
  7. 重要なコードは以下の部分です。

            If dic.Exists(data(i, 1) & "-" & data(i, 2)) = False Then
                dic.Add data(i, 1) & "-" & data(i, 2), data(i, 3) '辞書に登録
                k = k + 1
                list(k, 1) = data(i, 1) 'Key前
                list(k, 2) = data(i, 2) 'Key後ろ
                list(k, 3) = data(i, 3) 'Item
            End If
    
    VBA Dictionaryの使い方、タイトル01

Listは重複を削除した配列になる

  1. listは、辞書を間に挟むことで元のdataから重複を削除した配列になっています。

    dic.Exists(data(i, 1) & "-" & data(i, 2))
    の部分がdic.になければそれをdic.のKeyに追加して、 data(i, 3)はItemに入れます。
    さらにlistにも追加する。

                list(k, 1) = data(i, 1) 'Key前
                list(k, 2) = data(i, 2) 'Key後ろ
                list(k, 3) = data(i, 3) 'Item

  2. 重複を探す時に、辞書はキーを下図のような形でチェックしています。

    VBA Dictionaryの使い方、タイトル03
  3. シートに書き出すコードは、範囲をしっかり指定してやる必要があります。 このコードではRange("A12)セルを、.Resize(dic.count, 3) でリストのサイズを取得しています。

    VBA Dictionaryの使い方、タイトル04
  4. コードを実行すると、重複が削除されて、listという配列が取得できました。さらにその中身を確認するために、シートRange("A12)から書き出しています。

    VBA Dictionaryの使い方、タイトル05

Dictionaryと配列を組み合わせるとさらに便利になる

  1. 連想配列Dictionary はキーが一つ、アイテムが一つの、 一対一の組み合わせだから、便利そうだけど意外と使い道がないと思われている方も多いと思います。 ですが実際には配列と組み合わせることで、このように便利に使うことができます。