TriggerShelf

Recipe

Remove duplicate rows from Google Sheets automatically

Trigger: Run from the editor or a time-driven triggerServices: SpreadsheetAppMock-tested: Nov 2026

Keeps the first row for each key and deletes later copies. Choose which columns define a duplicate, and whether case matters.

Set it up

  1. Paste the script and set sheetName and keyCols in RD. keyCols [1] means column A.
  2. Make a copy of your sheet first. The script rewrites the data range.
  3. Run removeDuplicates. Optionally add a daily trigger.

The script

/**
 * Remove duplicate rows from a sheet, keeping the first one.
 * KEY_COLS lists the columns (1-based) that define a duplicate.
 * Run removeDuplicates from the editor or a trigger.
 */
var RD = { sheetName: 'Sheet1', keyCols: [1], headerRows: 1, ignoreCase: true };

function removeDuplicates() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(RD.sheetName);
  var values = sheet.getDataRange().getValues();
  var seen = {};
  var keep = values.slice(0, RD.headerRows);
  for (var i = RD.headerRows; i < values.length; i++) {
    var key = RD.keyCols.map(function (c) {
      var v = String(values[i][c - 1]).trim();
      return RD.ignoreCase ? v.toLowerCase() : v;
    }).join('\u0001');
    if (seen[key]) continue;
    seen[key] = true;
    keep.push(values[i]);
  }
  var removed = values.length - keep.length;
  if (removed === 0) return 0;
  sheet.getRange(1, 1, values.length, values[0].length).clearContent();
  sheet.getRange(1, 1, keep.length, keep[0].length).setValues(keep);
  return removed;
}
Test status. 2 of 2 automated checks pass, run Nov 2026 against simulated Google services. This recipe has not yet been run inside a live Google account. Test it on a copy of your sheet first.

What you should see

EmailPlan
ana@example.comPro
ben@example.comFree
cy@example.comFree

Before: 5 rows. After: 3 rows, order kept. Sample values, not output from a real account.

Common errors and fixes

Formulas turned into values
The script rewrites values. Keep formulas outside the data range, or use the built-in Data > Data cleanup > Remove duplicates for one-off jobs.
Rows that look equal stay
Extra spaces and case are trimmed, but different characters (for example a non-breaking space) are not.
Exceeded maximum execution time
Very large sheets need batching. See the fix page.

Permissions. Running this script asks you to grant Google permissions for the services listed above, to your own script. TriggerShelf never receives your Google data. See the permissions table. Google will show "Google hasn't verified this app"; that is expected for a script you paste yourself.