VBAで配列から重複している要素を削除する

VBA
この記事は約2分で読めます。

VBAで配列から重複している要素を削除するには
Dictionaryオブジェクトを使用します。

Dictionaryオブジェクトを使用するためには
Microsoft Scripting Runtimeに参照設定を行う必要があります。
参照設定の方法についてはこちらをご覧ください。

VBAで参照設定を行う
VBAに標準で含まれていない機能があるときは 外部のライブラリを参照して、外部ライブラリ内の機能を利用します。 この外部ライブラリの機能を利用する設定を、参照設定と言います。

 

配列から重複を削除するコードは以下になります。

 

配列の要素をDictionaryオブジェクトに格納します。
Existsメソッドを使用し、格納されてない配列要素だけを
Dictionaryに格納します。

 

dic.keysで重複した要素を排除した配列を返します

 

TestDeleteDuplicateItemでDeleteDuplicateItemのテストをしてみます。
配列aryの”テスト1″という項目が重複しています。

 

コードを動かすと配列の重複要素を削除した内容をメッセージボックスに表示します。

コメント

  1. 吉川 真一 より:

    「deleteDuplicateItem」関数ですが無駄が多いと思います。多分以下のコードで問題ないと思いますがいかがでしょうか?

    Function deleteDuplicateItem(ary() As Variant) As Variant()
    ‘#####################################################################
    ‘配列から重複している要素を削除する
    ‘Dictionaryを使用するので、Microsoft Scripting Runtimeの参照設定が必要
    ‘———————————————————————
    ‘引数 :ary 重複を削除したい配列
    ‘#####################################################################

     Dim Dic As Dictionary
     Set Dic = New Dictionary
     
     Dim i As Long
     
     For i = 0 To UBound(ary)
      If Dic.Exists(ary(i)) = False Then
       Dic.Add ary(i), ary(i)
      End If
     Next i
      
     deleteDuplicateItem = Dic.Keys()
     
     Set Dic = Nothing
     
    End Function

    • 吉川 真一さん

      コメントありがとうございます。
      ご指摘のとおり、dictionaryのkeysで配列をそのまま返したほうが、すっきりしますね。
      参考にさせていただきます。

  2. 高橋徹哉 より:

    初めまして、このソースを引用させていただき、こちらのメインルーチンの中でary() As Variantのところに間違えなくバリアントと宣言した変数を代入して使おうとすると、なぜか型が合わないとエラーを返してくるのです。
    これについて、頭抱えております。
    ご教示いただければ幸いです

    • コメントありがとうございます。
      掲載しているサンプルのコードだと、様々な型で利用できるようにVariant型で配列aryを宣言して引数に渡しています。

      関数に引き渡す配列のデータ型が決まっている場合は
      型をVariantではなく、例えばStringなどのように宣言します。
      Dim ary(3) As String
      ary(0) = “テスト1”
      ary(1) = “テスト2”
      ary(2) = “テスト1”
      ary(3) = “テスト3”

      それからDeleteDuplicateItemの引数ary()を利用側の型と合わせてもらうと、型エラーはでなくなるかなと思います。
      Function DeleteDuplicateItem(ary() As String) As Variant()

      End Function

  3. 吉川 真一 より:

    メインルーチンのコードが見えないので何とも言えないのですが、もしかしたらですが配列変数ではなく、単純な変数(後ろに「()」がつかない変数)とかではないですよね?

  4. 高橋徹哉 より:

    コメントありがとうございます。
    吉川さん。。。。ご名答でございました。
    バリアントのカッコなしに統一するとさらっと動きました。
    バリアントの理解がない私が悪かったです。。。
    けど不思議です
    バリアントであれば、配列でぶち込めば配列になりますよね。
    証拠に。。。。
    dim buf as variant
          buf = Split(dkey, “,”)
    For i = 0 To 7
    .Cells(r, i + 1).Value = buf(i)
    Next i
    は成立するんですよね
    責任転嫁できるならこれに騙されたかなあと悪態をついております。。。。

    けどありがとうございました。