Duplicate Email Detection & RemovalGoogle Sheets + Apps Script
Flag the repeat email addresses in a Form response sheet with conditional formatting, then delete the rows with Apps Script.
The setup this assumes: a Google Sheet receiving Google Form responses, with the email address in column C. Adjust the column index in one place — there's a table at the bottom.
Download this guide as Markdown
Conditional formatting
Highlights duplicates as they arrive. It's a visual flag only — no data is changed, and nothing is deleted.
- Apply to range —
C2:Cfor the email cell alone, orA2:Zto light up the whole row - Format rule — Custom formula is
- Formula —
=COUNTIF($C$2:$C, $C2) > 1 - Formatting — red fill
New form responses are checked as they come in, with nothing to re-run.
Removing the duplicates
Finds duplicate rows and deletes them, keeping the first occurrence of each address. This one does change your data.
Go to Extensions → Apps Script, paste the script below, save, and run it.
function removeDuplicates() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var seen = {};
var rowsToDelete = [];
// Start at row 1 to skip the header (row 0)
for (var i = 1; i < data.length; i++) {
var email = data[i][2].toString().toLowerCase().trim()
.replace(/[^\x20-\x7E]/g, '').replace(/\s+/g, '');
if (seen[email]) {
rowsToDelete.push(i + 1);
} else {
seen[email] = true;
}
}
// Delete from bottom to top so row numbers don't shift
for (var j = rowsToDelete.length - 1; j >= 0; j--) {
sheet.deleteRow(rowsToDelete[j]);
}
SpreadsheetApp.getUi().alert(rowsToDelete.length + ' duplicate rows removed.');
}
Why each piece is there
data[i][2]targets column C — the array is zero-indexed, so A=0, B=1, C=2..toLowerCase()collapses case differences, soJohn@gmail.comandjohn@gmail.comcount as one address..replace(/[^\x20-\x7E]/g, '')strips the non-printable characters Google Forms sometimes carries in. Two addresses that look identical on screen aren't equal without this..replace(/\s+/g, '')removes hidden whitespace, including the trailing space a paste often brings.- Rows are deleted bottom-to-top. Deleting top-down shifts every row number below the one you removed, so the second deletion would hit the wrong row.
Targeting a different column
Replace data[i][2] with the index of the column holding the address:
| Column | Index |
|---|---|
| A | 0 |
| B | 1 |
| C | 2 |
| D | 3 |
| E | 4 |
Optional: run it on a schedule
In Apps Script, open Triggers (the clock icon) → Add Trigger, and set
removeDuplicates to run on a time-based schedule — hourly or daily, depending
on how fast responses arrive.