
スプシユーザー
スプレッドシートでデータテーブル作っててさ、データの中に重複があるかどうか確認するのってめちゃくちゃ面倒じゃない?入れた記憶ないのに実は被ってて無駄に行増えてさ。どうにか簡単に見つけて重複を避けることができないかなっていつも思うんだけど…。

(ZACK IT編集)
スプレッドシートに限らずExcelでも誰もがぶつかる壁だよな。でも安心してくれ。実はスプレッドシートには、重複をサクッと見つけて、なんなら自動でハイライト表示したりする方法がいくつかあるんだ。ほかでは紹介されていないGAS(スクリプト)のコード付き解説もしてみよう。
スプレッドシートで表から重複をなくす対策
スプレッドシートでデータを扱う際、重複するデータの存在は集計や分析を歪める要因となる。特に大規模なデータセットでは、手作業での重複チェックは非現実的であり、効率的な方法が求められる。ここでは、スプレッドシートにおける重複データへの対策として、具体的な関数や機能、さらにはGAS(スクリプト)を用いた方法を詳しく解説する。これらの方法を習得することで、データ入力の誤りやインポート時の重複といった問題を未然に防ぎ、あるいは迅速に修正することが可能となる。データの正確性を保ち、より信頼性の高い分析結果を得るために、これらの対策は必須であると言える。
UNIQUE関数
UNIQUE関数は、スプレッドシート内で重複する値を除外し、一意のリストを生成する関数である。この関数は、元のデータ範囲から重複しない値のみを抽出し、新しいセル範囲に出力する。例えば、特定の列(B4:B25)に商品型番が多数入力されており、その中から重複を除いた商品リストを作成したい場合に非常に有効である。使用方法は非常にシンプルで、=UNIQUE(範囲)
と入力するだけでよい。
=UNIQUE(B4:B25)
指定した範囲内のデータから重複が取り除かれ、ユニークなデータが縦一列に表示される。元のデータを変更しても、UNIQUE関数の結果は自動的に更新されるため、常に最新の一意のリストを維持できる点も大きな利点である。ただし、この関数はあくまで重複を除いたリストを「作成」するものであり、元のデータから重複を「削除」するわけではないことに注意が必要である。別シートなどで1列分取得し、残りのデータはXLOOKUP関数などで引っ張ってくるのがおすすめ。つまり重複したデータを作らないための解決策にはならない。

そのためFILLするのに必要な行数がないとエラーになる。
下の行に別の値が入っていないか確認しよう。
UNIQUE関数はMicrosoft Excelにも搭載されているが、古いバージョンでは使用できないためGoogleスプレッドシートであればだれでも使用できる点非常に優秀。
COUNTIF関数
COUNTIF関数は、指定した範囲内で特定の条件を満たすセルの数を数える関数である。この関数を応用することで、スプレッドシート内で重複するデータを効果的に特定できる。具体的には、あるセル範囲内で各データが何回出現するかをCOUNTIF関数で計算し、その結果が1より大きい場合に重複であると判断する。例えば、B列に商品型番が並んでいるとして、D4セルに下記のように数式を入力し、下の行までコピー&ペーストする。
=COUNTIF($B$4:$B$25,B4)
絶対参照($マーク付き)にすることを忘れないようにしてから下の行にコピペしよう。でなければ下の行にずれれば範囲を1行ずつずれていってしまうからだ。デメリットは1列分無駄に関数で使用することだ。無駄な情報を入れたくないデータベース的な使い方には不向き。ちなみに条件付き書式の「カスタム数式」で応用することでシート状のセルに数式を入れずに済む方法もあるので次の章で解説。

条件付き書式
スプレッドシートの条件付き書式は、特定の条件を満たすセルに自動的に書式を適用する機能である。この機能とCOUNTIF関数を組み合わせることで、重複するデータを視覚的に強調表示できる。具体的な設定方法としては、まず重複を探したい範囲を今回もB4:B25とするならば、重複をチェックしたい範囲(B4:B25)を選択し、「表示形式」メニューから「条件付き書式」を選択する。次に、「カスタム数式」を選び、数式欄に下記のように入力する。
=COUNTIF(B:B,B4)>1
B:BはB列全体を選択したい場合に有効。この数式でカウントされた回数が1より大きい、つまり2以上で重複している場合のセルにハイライトする方法。

上記の数式だと25行目以降に票が追加された場合は条件付き書式が反映されないため、選択範囲を「B4:B」と入力することで、一番下の行まで選択範囲を広げることも可能。
データクリーンアップ (新機能)
Googleスプレッドシートには、データを整理し、重複を検出・削除するための「データクリーンアップ」という機能が搭載されている。これは比較的新しい機能であり、手作業での操作を減らし、データ整理の効率を高めることを目的としている。具体的な手順は下記の通り。
この機能の大きな利点は、関数を記述する必要がなく、直感的な操作で重複を削除できる点にある。特に、スプレッドシートの操作に不慣れなユーザーでも簡単に重複データを整理できるため、非常にユーザーフレンドリーであると言える。ただ、当サイトで検証してみたところ、重複があるにもかかわらず候補が表示されない場面も。候補の提案はうまく動作している感じがしなかったので使えない場面もあるかもしれない点には留意したい。

「重複を削除」を選択すると、重複を検出する対象の列を選択するダイアログが表示され、指定した列に基づいて重複行を削除できる。注意点としては、重複を削除したい列だけ選択してしまうと、表がずれて悲惨なことになるので注意。個人的には自動で重複削除する機能はトラブルがあった際に後戻りできないのでお勧めしない。あくまで重複を検知してくれるだけの機能のほうがありがたい場面は多いだろう。

上の画像のように、変に削除された結果、表(テーブル)がずれて使い物にならなくなった…なんてことはないようにしたい。必ず表の全範囲を指定したい。というか怖いので自動で削除されたくない人は使わないことをおすすめする。
GASで自動ハイライト
※スクリプト実行によるトラブルやデータの損失は当サイトで責任は負わない。必ずバックアップを取ってからテストをしてほしい。
仕事でスプレッドシートを活用する場面で表の重複を探したい場合、必ずしも条件は1つのセルだけではないだろう。例えば同じ商品型番でも仕入れ先が違ったらデータとして必ずしも重複をするわけではないこともある。そう言ったときには重複判定をせずに、表の1行すべてが同じ値なら重複判定にしたい、そんな希望を叶えるならGASでスクリプトを組むのがおすすめ。なお下記のコードはテストシートとして作成したB4:F26までの範囲で表を作成した場合を想定したコード。表の下に行が追加される分には重複を検知できるコードとなっているが、そのままコピペしても使えないケースもあるで必ずGASの知識を持ったユーザーがこのコードを参考に調整をしてほしい。
/**
* セル編集時に行全体の重複チェックとハイライトを行う機能
* onEditイベントを使用して自動実行
*/
function onEdit(e) {
try {
// イベントオブジェクトが存在しない場合は、アクティブなシートを取得
if (!e || !e.source) {
const sheet = SpreadsheetApp.getActiveSheet();
updateAllHighlights(sheet);
return;
}
const sheet = e.source.getActiveSheet();
const range = e.range;
const editedRow = range.getRow();
const editedCol = range.getColumn();
// 表の範囲内かチェック(B列以降、5行目以降)
if (editedCol >= 2 && editedRow >= 5) {
// 全体の重複チェックとハイライト更新
updateAllHighlights(sheet);
}
} catch (error) {
console.log('onEdit エラー:', error);
// エラー時でも処理を続行
try {
const sheet = SpreadsheetApp.getActiveSheet();
updateAllHighlights(sheet);
} catch (fallbackError) {
console.log('フォールバック処理エラー:', fallbackError);
}
}
}
/**
* セル変更時(削除含む)に重複チェックとハイライトを行う機能
*/
function onChange(e) {
try {
// イベントオブジェクトが存在しない場合は、アクティブなシートを取得
if (!e || !e.source) {
const sheet = SpreadsheetApp.getActiveSheet();
updateAllHighlights(sheet);
return;
}
const sheet = e.source.getActiveSheet();
// 変更タイプを確認
if (e.changeType === 'REMOVE_ROW' || e.changeType === 'REMOVE_COLUMN' ||
e.changeType === 'INSERT_ROW' || e.changeType === 'INSERT_COLUMN' ||
e.changeType === 'OTHER') {
// 少し遅延を入れて処理を実行(削除処理完了後に実行)
Utilities.sleep(100);
updateAllHighlights(sheet);
}
} catch (error) {
console.log('onChange エラー:', error);
// エラー時でも処理を続行
try {
const sheet = SpreadsheetApp.getActiveSheet();
updateAllHighlights(sheet);
} catch (fallbackError) {
console.log('フォールバック処理エラー:', fallbackError);
}
}
}
/**
* 行全体で重複チェックを行い、ハイライトを更新する関数
* @param {Sheet} sheet - 対象のシート
*/
function updateAllHighlights(sheet) {
try {
// 既存のハイライトをクリア
clearHighlights(sheet);
// 表の範囲を取得
const lastRow = sheet.getLastRow();
const lastCol = sheet.getLastColumn();
if (lastRow < 5 || lastCol < 1) return;
// データの開始行(5行目から)
const startRow = 5;
// 行全体の重複チェック
highlightDuplicateRows(sheet, startRow, lastRow, lastCol);
console.log('行全体の重複ハイライトを更新しました');
} catch (error) {
console.log('updateAllHighlights エラー:', error);
}
}
/**
* 行全体で重複する行をハイライトする関数
* @param {Sheet} sheet - 対象のシート
* @param {number} startRow - 開始行
* @param {number} lastRow - 終了行
* @param {number} lastCol - 最終列
*/
function highlightDuplicateRows(sheet, startRow, lastRow, lastCol) {
try {
// 全データを取得
const allData = sheet.getRange(startRow, 1, lastRow - startRow + 1, lastCol).getValues();
// 行データをハッシュ化して重複をチェック
const rowHashes = {};
const duplicateRows = [];
for (let i = 0; i < allData.length; i++) {
const row = allData[i];
// 空行は除外(全てのセルが空の場合)
const isEmptyRow = row.every(cell =>
cell === '' || cell === null || cell === undefined || String(cell).trim() === ''
);
if (!isEmptyRow) {
// 行全体を文字列に変換してハッシュ化
const rowString = row.map(cell => String(cell).trim()).join('|||');
const rowIndex = i + startRow;
if (rowHashes[rowString]) {
// 既に同じ行が存在する場合
rowHashes[rowString].push(rowIndex);
} else {
// 新しい行パターン
rowHashes[rowString] = [rowIndex];
}
}
}
// 重複する行をハイライト
Object.values(rowHashes).forEach(rowIndices => {
if (rowIndices.length > 1) {
// 2行以上同じ内容の行がある場合
rowIndices.forEach(rowIndex => {
// B列からF列までをハイライト(A列は除外)
const range = sheet.getRange(rowIndex, 2, 1, lastCol - 1);
range.setBackground('#FFFF00'); // 黄色でハイライト
});
}
});
} catch (error) {
console.log('highlightDuplicateRows エラー:', error);
}
}
/**
* シート内のすべてのハイライトをクリアする関数
* @param {Sheet} sheet - 対象のシート
*/
function clearHighlights(sheet) {
try {
// 表の最終行を取得
const lastRow = sheet.getLastRow();
const lastCol = sheet.getLastColumn();
// データの開始行(5行目から)
const startRow = 5;
// B列以降の5行目以降の範囲で背景色をクリア(A列は除外)
if (lastCol >= 2 && lastRow >= startRow) {
const clearRange = sheet.getRange(startRow, 2, lastRow - startRow + 1, lastCol - 1);
clearRange.setBackground(null);
}
} catch (error) {
console.log('clearHighlights エラー:', error);
}
}
/**
* スプレッドシートが開かれた時の初期設定
*/
function onOpen() {
try {
const sheet = SpreadsheetApp.getActiveSheet();
// 初期状態で全ての重複をハイライト
updateAllHighlights(sheet);
console.log('行重複ハイライト機能が初期化されました');
} catch (error) {
console.log('onOpen エラー:', error);
}
}
このコードをスプレッドシート上部のメニューにある「拡張機能」>「Apps Script」に入り、「コード.gs」に貼り付ける。貼り付けただけでは動かないため、保存をした後「OnOpen」をいったん実行。

初回のスクリプト実行の場合、Apps Scriptの制限でGoogleアカウントの承認画面になるため承認して続行をすればOK。

さらに、トリガーに「OnChange」を割り当て、「イベントの種類を選択」で「変更時」を選択する必要がある。設定を適用するには右下の「保存」ボタンを押して、シートに戻り正常に動くか確認して操作すれば問題ない。


このコードは、シート名を取得する機能を搭載していないので、スプシのファイルに複数のシートを作成する場合はコードを変更しないと、すべてのシートで重複探しを自動実行されてしまうので注意が必要。
まとめ
スプレッドシートにおける重複データの確認と削除は、データ整理の基本でありながら、その方法を知らなければ煩雑な作業となり得る。本記事では、その対策として、UNIQUE
関数、COUNTIF
関数、条件付き書式といった基本的な機能の活用方法から、Googleスプレッドシートに搭載された「データクリーンアップ」機能、そして最も実用的な解決策としてGAS
(Google Apps Script)を用いた自動ハイライトの方法まで、多角的に解説した。この情報を参考にデータの重複が解決できれば幸いだ。当サイトではITやテクノりじー情報に加えて、スプレッドシートやExcelの自動化や効率化に関する情報も多数発信している。