// generated · Sheets

Move a row to a “Done” sheet when column E says Done.

I keep a tracker and want finished rows to leave the active list and pile up on their own tab.

When I mark a row Done in column E, move that row to a separate sheet called Done.

The script

copy · paste · trigger
moveDoneRows.gs
Apps Script
// Made with bulldo.gs · describe an automation, get working Apps Script.
// Fork or fix this one → https://bulldo.gs/g/move-done-rows-to-archive-sheet

// Installable onEdit trigger. When column E of a row reads "Done", copy the
// whole row to a sheet named "Done", then delete it from the source sheet.
function onEdit(e) {
  const range = e.range;
  if (range.getColumn() !== 5) return;          // only column E
  if (range.getValue() !== 'Done') return;      // only the "Done" value

  const sheet = range.getSheet();
  const done = sheet.getParent().getSheetByName('Done');
  const row = sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).getValues()[0];

  done.appendRow(row);
  sheet.deleteRow(range.getRow());
}

Made with bulldo.gs. Fork it to change a field, a trigger, or the edge cases — describe the change and Gnaw rewrites it.

Walkthrough

How it works

The two guards drop edits we do not care about: anything outside column E, and any value other than the exact string "Done". That keeps the trigger cheap on every keystroke.

It reads the full row with getRange(row, 1, 1, getLastColumn()), appends it to the Done sheet, then deletes the source row. appendRow + deleteRow run in order, so the move is atomic from the editor’s point of view.

This must be an installable onEdit trigger (added from the Triggers panel), not the simple one — moving data between sheets needs the broader authorization the installable trigger carries.

Set it up

Create a tab named exactly "Done". Paste the function, then add an installable trigger: Triggers → add → event source: from spreadsheet, event type: on edit. Approve the Sheets scope on the first edit.

Need a different version?

Describe your sheet or inbox and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

3 questions
What if the "Done" sheet does not exist?
getSheetByName returns null and appendRow throws. Create the tab first, or add `if (!done) return;` to fail quietly.
Can I trigger on a checkbox instead of the word "Done"?
Yes. A checked box is the boolean true, so change the value check to `if (range.getValue() !== true) return;`.
Deleting the row shifts everything up — is that a problem?
No, because the handler runs per edit and reads the row position from the event each time. If you mark several rows at once, mark them top-to-bottom or switch to a batched time-trigger version.