The Master Guide to onEdit(e): Automating Google Sheets Instantly
If you want your Google Sheets to feel like powerful software rather than static grids, you need to learn onEdit(e). This function is the "magic wand" of Google Apps Script.
It allows your spreadsheet to react instantly to user actions. You check a box, and a row moves. You select a status from a dropdown, and a timestamp appears. No buttons to click, no menus to open—it just happens.
This guide covers everything from the basic mechanics to advanced performance optimization for the onEdit simple trigger.
onEdit(e) is known as a "Simple Trigger." This means it runs automatically whenever a user manually edits a cell. It requires no setup in the "Triggers" menu, but it has specific security limitations.
1. What is onEdit(e)?
onEdit is a reserved function name. If you write a function with this exact name in your script project, Google Sheets will attempt to run it every time a cell's value is modified by a human user.
The "e" Parameter
Just like doGet(e), the power lies in the e (Event) object. When an edit happens, Google captures the context—which cell changed, what the old value was, and what the new value is—and passes it to your function.
Using e is significantly faster than asking the spreadsheet for data, because the data is already pre-loaded in memory.
2. Technical Deep Dive
To write professional-grade triggers, you must understand the constraints.
Execution Context & Limitations
- User Permissions: A simple
onEditruns as the user who is at the keyboard. If "Bob" edits the cell, the script runs with Bob's permission. - Restricted Services: Because it runs automatically without explicit authorization, simple triggers cannot access personal data like Gmail, Calendar, or Identity. They also cannot use
UrlFetchAppto call external APIs. - 30-Second Limit: The script must finish execution within 30 seconds, or it will be terminated.
onEdit only triggers on user actions. It will NOT run if a cell changes due to a formula recalculation or if another script modifies the sheet.
3. Real-World Use Cases
Developers use this function to build interactive spreadsheet applications:
- Auto-Timestamping: Recording exactly when a task was marked "Complete."
- Input Validation: Preventing users from entering invalid data patterns (e.g., forcing uppercase).
- ToDo Lists: Moving rows from "Active" to "Archive" sheets automatically when checked off.
- Dynamic Dropdowns: Changing the options in Column B based on what was selected in Column A.
4. Code Examples
Level 1: The Basic Logger
This snippet helps you understand what is happening. It simply shows a "Toast" (a small popup notification) whenever you edit a cell.
function onEdit(e) {
// 1. Get the range that was edited from the event object
var range = e.range;
// 2. Get the new value entered
var value = e.value;
// 3. Show a toast message in the bottom right corner
SpreadsheetApp.getActiveSpreadsheet().toast(
"You typed: " + value,
"Edit Detected",
3
);
}
Level 2: The Classic Auto-Timestamp
The most requested script feature: "Put a date in Column B when I edit Column A."
function onEdit(e) {
// 1. Performance Guard: Check strict conditions immediately
// Only run if the edited column is Column 1 (A)
if (e.range.columnStart !== 1) return;
// Only run if the sheet name matches 'Tasks'
if (e.source.getSheetName() !== 'Tasks') return;
// 2. Define the timestamp cell
// It should be on the same row, but in Column 2 (B)
// offset(rowOffset, columnOffset)
var timestampCell = e.range.offset(0, 1);
// 3. Set the date
// new Date() creates the current date and time
timestampCell.setValue(new Date());
}
Code Explanation:
if (e.range.columnStart !== 1) return;: This is critical optimization. If the user edits Column C, the script stops instantly.offset(0, 1): This targets the cell 1 column to the right of the active cell.
Level 3: Checkbox Logic (Moving Rows)
This advanced example moves a row to an "Archive" sheet when a checkbox in Column 5 is ticked.
function onEdit(e) {
// 1. Define configuration variables
var watchSheet = "Active Projects";
var destSheetName = "Archive";
var triggerCol = 5; // Column E (Checkbox)
// 2. FAST checks to exit early if not relevant
if (e.range.columnStart !== triggerCol) return;
if (e.range.rowStart < 2) return; // Ignore headers
if (e.source.getSheetName() !== watchSheet) return;
// 3. Only proceed if the value is TRUE (Checked)
// Note: e.value is always a string. Checkbox TRUE is "TRUE"
if (e.value !== "TRUE") return;
var sheet = e.source.getActiveSheet();
var destSheet = e.source.getSheetByName(destSheetName);
var row = e.range.rowStart;
// 4. Get the full row data
// getRange(row, column, numRows, numColumns)
var rowRange = sheet.getRange(row, 1, 1, sheet.getLastColumn());
var rowValues = rowRange.getValues();
// 5. Move Data: Append to destination, then delete original
destSheet.appendRow(rowValues[0]);
sheet.deleteRow(row);
}
e.value (the string representation of the input) because it is instant. Calling e.range.getValue() requires a slow call back to the spreadsheet App.
5. Optimization & Performance
Since onEdit runs on every single cell change, a poorly written script can slow down your spreadsheet significantly.
- Use "Guard Clauses": Start every function with
ifstatements that return immediately if the edit isn't in the correct column or sheet. - Avoid
getActiveSpreadsheet(): Usee.sourceinstead. It refers to the spreadsheet that triggered the event and is already in memory. - Avoid
getActiveCell(): Usee.range. It is more accurate, especially if the user is editing quickly.
6. Common Mistakes
- Renaming the Function: If you rename it to
myEditTrigger(e), it will stop working unless you manually set up an installable trigger. - Testing with "Run": You cannot click "Run" in the script editor to test this function. It will fail because the
evariable will be undefined. You must test by actually editing a cell in the sheet. - Sending Email: Beginners often try `MailApp.sendEmail` inside
onEdit. It will fail silently due to permission restrictions. Use an "Installable Trigger" for emails.
7. FAQ: Developer Questions
It actually does trigger! However, if you paste multiple values, e.value will be undefined (because there isn't just one value). You must verify if (!e.value) and then use e.range.getValues() to handle bulk edits.
No. You can only have one function named onEdit per project. If you have multiple tasks (e.g., timestamping AND moving rows), you must put logic for both inside the single onEdit function.
If you used an "Installable Trigger" (for emails/APIs), the trigger is bound to your account. If you just used simple `onEdit`, ensure your colleagues have "Editor" access to the sheet, otherwise the script cannot run for them.
Conclusion
Mastering onEdit(e) is the turning point where you stop using Google Sheets as a data bucket and start using it as an application platform. By following the optimization rules—checking columns early and using the event object—you can create snappy, responsive tools that automate tedious workflows for your entire team.
Next Steps: Implement the "Level 2" timestamp script in a blank sheet. Once it works, try modifying it to only timestamp if the status is changed to specific words like "Done" or "Approved."