【簡単エクセル/Excel VBA マクロ】重複データを検出する方法|Dictionaryオブジェクト|ワンポイントテクニック #006



いつもありがとうございます。
ノンプログラマー向け「Excelマクロ・VBAワンポイントテクニック解説シリーズ」へようこそ!
本稿では「重複データを検出する方法」を解説します!
Excelで大量のデータを扱っていると、名前や商品名などが重複して記録されていることがあります。たとえば名簿管理や売上管理で、同じ人が二重登録されていたり、同じ商品の売上が重複して入力されてしまうケースです。こうした重複は、集計や分析の結果を歪めてしまう原因になります。
そこで今回は、VBAを使って重複データを検出する手法を紹介いたします。複数の方法がありますが、それぞれの方法のメリット、デメリット、適したデータの規模を解説します。なかでもおすすめは Dictionaryオブジェクト を使った方法です!小規模データから大規模データまで幅広く対応でき、コードも簡潔で高速に動作します。
結論
ほとんどの場合、Dictionary を使っておけば、問題ない。
今回紹介するテクニックを使い、スマートに重複検出処理を実装すれば、あなたのマクロの合理性・可読性が一段と上がり、でプロフェッショナルな仕上がりになります!
VBAを活用して、自分やコミュニティに合ったアプリを作成し、仕事量は半分に、成果は2倍にしていきましょう! 初心者の方にも分かりやすく丁寧に解説していきますので、ぜひ最後までご覧ください!
VBAで重複データを検出する6つの方法

VBAで重複データを検出する方法は複数ありますが、主な方法は6つです。それぞれの特徴を下表にまとめました。
特別な事情がなければ、Dictionaryを使った方法で実装しておけば間違いありません。小規模データから大規模データまで幅広く対応でき、コードも簡潔で高速に動作します。
方法 | 概要 | メリット | デメリット | 適したデータ規模 |
WorksheetFunction.CountIfを使う | WorksheetFunction.CountIf を使用して、範囲内での値の出現回数をカウントし、2以上のデータを検出します。 |
|
|
小規模 (~数百行以下) |
繰り返し処理を使う | データを1つずつ順番に確認し、それぞれの値が他の値と同じかどうかを比較します。 |
|
|
小規模 (~数百行以下) |
Collectionを使う | Collection にデータを格納し、エラー処理で重複を検出します。 |
|
|
中規模 (~数千行以下) |
Dictionaryを使う | Dictionary を用いて一意性を判定しながら重複を検出します。 |
|
|
小規模~大規模 (~数万行) |
SQLクエリを使う | ADOを使い仮想テーブルを作成し、SQL文で重複データを検索します。 |
|
|
大規模 (数万行以上) |
Dictionary オブジェクトを使い重複データを検出する方法

シナリオ
次のようなフォルダ・ファイル構成です。Dictionaryで重複を検出する.xlsm
にコード記述します。このファイルが、重複を含むデータ.xlsx
を見に行き、重複しているデータを検出します。
your_folder/
├── Dictionaryで重複を検出する.xlsm
└── 重複を含むデータ.xlsx

なお、重複を含むデータ.xlsx
には次のようなデータが記録されています。

コードの実装

Dictionary オブジェクトを使い重複データを検出するコードと、その実行結果を示します。
コードは次の通りです。
Option Explicit
Sub DetectDuplicates()
' 変数宣言
Dim src_fp As String ' データファイルのパス
Dim this_wb As Workbook ' 現在のワークブック
Dim data_wb As Workbook ' データが格納されているワークブック
Dim data_ws1 As Worksheet ' データが格納されているワークシート
' 配列関連
Dim data_array() As Variant ' データを格納する配列
Dim dup_data_array() As Variant ' 重複データを格納する配列
Dim array_row_idx As Long ' 配列内の現在の行インデックス
Dim dup_array_row_idx As Long ' 重複データ配列の現在の行インデックス
' 辞書関連
Dim dict As Dictionary ' 重複検出に使用する辞書オブジェクト
Dim key As Variant ' Dictionaryのキーとして使用
' シート操作関連
Dim write_row_idx As Long ' 結果を書き込む行インデックス
' データファイルのパスを取得
src_fp = ThisWorkbook.Path & "\重複を含むデータ.xlsx"
' ワークブックとワークシートを取得
Set this_wb = ThisWorkbook
Set data_wb = Workbooks.Open(src_fp)
Set data_ws1 = data_wb.Worksheets(1)
' 重複検出用のDictionaryオブジェクトを作成
Set dict = New Dictionary
' A列のデータを配列形式で取得
data_array = data_ws1.Range("A1:A20").Value
' データの重複を検出してDictionaryに格納
For array_row_idx = 1 To UBound(data_array, 1)
' 辞書にすでにフルーツ名が存在する場合、その行番号をリストに追加
If dict.exists(data_array(array_row_idx, 1)) Then
dict(data_array(array_row_idx, 1)) = _
dict(data_array(array_row_idx, 1)) & "," & array_row_idx
' フルーツ名が辞書に存在しない場合、新しいデータとして追加
Else
dict.Add data_array(array_row_idx, 1), CStr(array_row_idx)
End If
Next array_row_idx
' 重複データを格納する配列のサイズを調整
' 1列目にフルーツ名、2列目に行番号
ReDim dup_data_array(1 To dict.Count, 1 To 2)
' 重複データとその行番号を配列に格納
dup_array_row_idx = 1
For Each key In dict.Keys
If InStr(dict(key), ",") > 0 Then ' カンマが含まれる(重複の)場合
dup_data_array(dup_array_row_idx, 1) = key ' フルーツ名
dup_data_array(dup_array_row_idx, 2) = dict(key) ' 行番号
dup_array_row_idx = dup_array_row_idx + 1
End If
Next key
' 重複データをC列とD列に出力
If dup_array_row_idx > 1 Then ' 重複データが存在する場合
data_ws1.Range("C1:D" & _
dup_array_row_idx - 1).Value = dup_data_array
End If
End Sub
コードの実行結果は次の通りです。C列には重複しているデータの名前が、D列にはそのデータが存在する行番号が表示されます。



解説をしていきます。
Option Explicit
ここでは、Option Explicit
を有効にしています。この設定を使うと、変数を使用する前に必ず宣言が必要になります。これにより、変数のタイプミスや未定義変数によるエラーを防ぎ、コードの安全性と信頼性を高めることができます。
' 変数宣言
Dim src_fp As String ' データファイルのパス
Dim this_wb As Workbook ' 現在のワークブック
Dim data_wb As Workbook ' データが格納されているワークブック
Dim data_ws1 As Worksheet ' データが格納されているワークシート
' 配列関連
Dim data_array() As Variant ' データを格納する配列
Dim dup_data_array() As Variant ' 重複データを格納する配列
Dim array_row_idx As Long ' 配列内の現在の行インデックス
Dim dup_array_row_idx As Long ' 重複データ配列の現在の行インデックス
' 辞書関連
Dim dict As Dictionary ' 重複検出に使用する辞書オブジェクト
Dim key As Variant ' Dictionaryのキーとして使用
' シート操作関連
Dim write_row_idx As Long ' 結果を書き込む行インデックス
ここでは、コード内で使用する変数が宣言されています。変数は Dim 変数名 As データ型
の構文で宣言します。これにより、各変数は As
以降で指定したデータ型のデータを格納できるようになります。
ここでは、具体的には、データファイルのパスや現在のワークブックを表す変数、配列、辞書オブジェクト(Dictionary
)など、重複データ検出に必要な変数を宣言しています。可読性を高めるため、カテゴリごとに整理して記述しています。
なお、各データ型の意味は下表の通りです。
データ型 | 種類 | 意味 |
---|---|---|
Workbook |
オブジェクト型 | 現在のワークブックやデータが格納されているワークブック(操作対象のファイル)を表すオブジェクト型です。 |
Worksheet |
オブジェクト型 | データが格納されているワークシートを表すオブジェクト型のデータ型です。 |
Dictionary |
オブジェクト型 | 重複データ検出に使用するキーと値のペアを管理する辞書オブジェクト型のデータ型です。 |
String |
文字列型 | ファイルパスや名前などのテキスト情報を格納する文字列型のデータ型です。 |
Long |
数値型 | -2,147,483,648 から 2,147,483,647 までの範囲の整数を格納できる数値型のデータ型です。 |
Variant |
汎用型 | 任意のデータ型を格納できる柔軟なデータ型です。ここでは配列や辞書のキーなど多用途に使用されています。 |
' データファイルのパスを取得
src_fp = ThisWorkbook.Path & "\重複を含むデータ.xlsx"
ここでは、変数src_fp
に、操作対象であるデータファイルのパスを設定しています。ThisWorkbook.Path
は、このコードを実行しているExcelファイル(自分自身)の保存場所を意味します。これに、ファイル名をつなげることで、ファイルの完全なパスを作成しています。
' ワークブックとワークシートを取得
Set this_wb = ThisWorkbook
Set data_wb = Workbooks.Open(src_fp)
Set data_ws1 = data_wb.Worksheets(1)
ここでは、各ワークブックを開くと同時にオブジェクト変数に割り当てています。また、必要なシートも取得し、対応するオブジェクト変数に割り当てています。これにより、以降の操作は、これらのオブジェクト変数を通じて実行できます。
なお、Set
キーワードは、オブジェクト型の変数に値を代入する際に使用します。文字列や数値など、オブジェクト以外の値を代入する場合には Set
は不要です。このコードでは、this_wb
、data_wb
、data_ws1
がオブジェクト型の変数であるため、Set
を用いて代入しています。
' 重複検出用のDictionaryオブジェクトを作成
Set dict = New Dictionary
ここでは、重複データを検出するための辞書オブジェクトを作成しています。Dictionary
はキーと値のペアを管理できるデータ構造であり、効率的に重複を検出するのに適しています。
' A列のデータを配列形式で取得
data_array = data_ws1.Range("A1:A20").Value
ここでは、ワークシートのA列からデータを取得し、data_array
配列に格納しています。配列に格納することで、データをメモリ上で処理できるため、Excelアプリケーション(セル)を逐次操作する場合と比べてオーバーヘッドが削減され、高速な処理が可能になります。
' データの重複を検出してDictionaryに格納
For array_row_idx = 1 To UBound(data_array, 1)
' 辞書にすでにフルーツ名が存在する場合、その行番号をリストに追加
If dict.exists(data_array(array_row_idx, 1)) Then
dict(data_array(array_row_idx, 1)) = _
dict(data_array(array_row_idx, 1)) & "," & array_row_idx
' フルーツ名が辞書に存在しない場合、新しいデータとして追加
Else
dict.Add data_array(array_row_idx, 1), CStr(array_row_idx)
End If
Next array_row_idx
ここでは、A列のデータを1行ずつ確認し、重複しているかを辞書オブジェクトで管理しています。既に存在するキーには行番号を追加し、新しいデータの場合は辞書に登録しています。

ここがポイントなので、もう少し詳しく解説します。
このコードでは、A列のデータを辞書オブジェクトに格納し、重複データを管理しています。辞書オブジェクトは、キーと値のペアでデータを扱うため、A列の値をキーとして登録し、値として行番号を記録します。
データがすでに登録されているかどうかは、dict.exists
メソッドで確認しています。このメソッドは、指定したキーが辞書に存在するかを判定するものです。ここでは、キーが辞書に存在する場合は、そのキーに関連付けられた値を更新しています。つまり、行番号をカンマ区切りで追加しています。一方、キーが存在しない場合は、dict.Add
を使って新しいデータとして登録しています。
これにより、同じデータに関連する複数の行番号を効率的に管理できるほか、配列とは異なり、辞書オブジェクトはキーが一意であるため、データの重複を簡単に検出できる仕組みになっています。
' 重複データを格納する配列のサイズを調整
' 1列目にフルーツ名、2列目に行番号
ReDim dup_data_array(1 To dict.Count, 1 To 2)
ここでは、重複データを格納する配列 dup_data_array
のサイズを設定しています。ReDim
を使い、辞書オブジェクト dict
のキーの数(重複データの種類)を行数として設定し、1列目にデータ名、2列目に行番号を格納できる2列の構造にしています。
この操作は必ず行う必要があります。これをしないと、配列のサイズが定義されていないため、配列dup_data_array
にデータを格納する際にエラーが発生します。
' 重複データとその行番号を配列に格納
dup_array_row_idx = 1
For Each key In dict.Keys
If InStr(dict(key), ",") > 0 Then ' カンマが含まれる(重複の)場合
dup_data_array(dup_array_row_idx, 1) = key ' フルーツ名
dup_data_array(dup_array_row_idx, 2) = dict(key) ' 行番号
dup_array_row_idx = dup_array_row_idx + 1
End If
Next key
ここでは、辞書に登録されたデータから重複しているデータのみを抽出し、配列 dup_data_array
に格納しています。この配列は後のワークシートへの出力処理に使用されます。
なお、「dup」は「duplicate(重複)」の略です。重複データを格納するための配列であることを示しています。
' 重複データをC列とD列に出力
If dup_array_row_idx > 1 Then ' 重複データが存在する場合
data_ws1.Range("C1:D" & _
dup_array_row_idx - 1).Value = dup_data_array
End If
ここでは、抽出した重複データをワークシートのC列とD列に出力しています。C列にはデータ名、D列には行番号が出力されます。配列の内容を一度にワークシートに書き戻すため、逐次的にセルを操作するよりも処理速度が上がります。

以上で解説は終了です
なお、配列に関してはこちらの記事で詳しく解説しております。もしよろしければ、合わせて活用ください。
おわりに


ご覧いただきありがとうございました。
今回の記事では、「重複データを検出する方法」を解説いたしました。
お問い合わせやご要望等ございましたら、「お問い合わせ/ご要望」またはコメントにて、ご連絡いただければ幸いでございます。
皆様の人生がより一層素晴らしいものになるよう、少しでもお役に立てれば幸いでございます。
なお、当サイトでは様々な情報を発信しております。もしよろしければ、トップページもご覧いただけると幸いでございます。
関連記事
本稿と関連の深い記事です。もしよろしければ、合わせてご活用ください。
- 【簡単エクセル/Excel VBA マクロ】Excel VBA マクロの全体像 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】通常使用編目次 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】ワンポイントテクニック編目次 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】アプリ事例編目次 | みんなの実用学 (jitsuyogaku.com)
VBAプログラミングスキルアップのための参考情報
ここでは参考図書を紹介いたしますが、これらに限らず自分に合うものを選ぶことが重要だと考えております。皆様の、より一層のご成功を心よりお祈りしております。
VBAプログラミングのスキルアップ
学習用としてもハンドブックとしても役立つ便利な書籍がこちらです。価格はやや高めですが、その内容は非常に充実しています。相応のスキルを身に付けるためには、こうしたしっかりとした書籍を一冊持っておくと良いでしょう。
入門書に関しては、どの書籍も大きな違いはありません。あまり迷うことに時間をかけるよりは、手頃なものを一冊選んでみると良いでしょう。VBAの入門書は数多く出版されていますので、興味がある方はぜひチェックしてみてください。
甲乙つけがたい場合、私はインプレス社の「いちばんやさしい」シリーズを選ぶことが多いです。
\チェックしてみよう/
\チェックしてみよう/
\チェックしてみよう/
VBAのプログラミング能力を客観的に証明したい場合には「VBAエキスパート試験」があります。この試験はVBAの知識を公式に認定するものです。VBAの総合的な能力獲得を目指す方に適しています。以下の公式テキストが販売されております。
プログラミングの一般教養
「独学プログラマー」というプログラミングの魅力を解説した書籍があります。これはVBAではなくPythonを題材としていますが、プログラミングの基本的な知識や思考法、仕事の進め方まで幅広く学べます。
こちらの記事でも紹介しております。もしよろしければご覧ください。
