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

VBAで参照設定を行う
VBAに標準で含まれていない機能があるときは
外部のライブラリを参照して、外部ライブラリ内の機能を利用します。
この外部ライブラリの機能を利用する設定を、参照設定と言います。
配列から重複を削除するコードは以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Function DeleteDuplicateItem(ary() As Variant) As Variant() '################################################################################### '配列から重複している要素を削除する 'Dictionaryを使用するので、Microsoft Scripting Runtimeの参照設定が必要 '----------------------------------------------------------------------------------- '引数 :ary 重複を削除したい配列 '################################################################################### Dim dic As 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 |
15 16 17 18 19 |
For i = 0 To UBound(ary) If dic.Exists(ary(i)) = False Then dic.Add ary(i), ary(i) End If Next i |
配列の要素をDictionaryオブジェクトに格納します。
Existsメソッドを使用し、格納されてない配列要素だけを
Dictionaryに格納します。
28 |
DeleteDuplicateItem = dic.Keys |
dic.keysで重複した要素を排除した配列を返します
TestDeleteDuplicateItemでDeleteDuplicateItemのテストをしてみます。
配列aryの”テスト1″という項目が重複しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Sub TestDeleteDuplicateItem() Dim ary(3) As Variant ary(0) = "テスト1" ary(1) = "テスト2" ary(2) = "テスト1" ary(3) = "テスト3" Dim ary2() As Variant ary2 = DeleteDuplicateItem(ary) Dim i As Long Dim s As String s = "" For i = 0 To UBound(ary2) s = s & ary2(i) & vbNewLine Next i MsgBox s End Sub |
コードを動かすと配列の重複要素を削除した内容をメッセージボックスに表示します。
コメント
「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で配列をそのまま返したほうが、すっきりしますね。
参考にさせていただきます。
初めまして、このソースを引用させていただき、こちらのメインルーチンの中で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
メインルーチンのコードが見えないので何とも言えないのですが、もしかしたらですが配列変数ではなく、単純な変数(後ろに「()」がつかない変数)とかではないですよね?
コメントありがとうございます。
吉川さん。。。。ご名答でございました。
バリアントのカッコなしに統一するとさらっと動きました。
バリアントの理解がない私が悪かったです。。。
けど不思議です
バリアントであれば、配列でぶち込めば配列になりますよね。
証拠に。。。。
dim buf as variant
buf = Split(dkey, “,”)
For i = 0 To 7
.Cells(r, i + 1).Value = buf(i)
Next i
は成立するんですよね
責任転嫁できるならこれに騙されたかなあと悪態をついております。。。。
けどありがとうございました。