When automating Google Sheets with Apps Script, two triggers are often confused: onEdit and onChange. They behave differently, and this short guide summarizes what actually triggers each one.
What triggers each event
| Action in the spreadsheet | onEdit | onChange |
|---|---|---|
| Edit a cell value | ✔️ | ✔️ |
| Insert a row or column | ❌ | ✔️ |
| Delete a row or column | ❌ | ✔️ |
| Change background color or font | ❌ | ✔️ |
| Create or delete a sheet | ❌ | ✔️ |
| Move a column or row with data | ✔️ | ✔️ |
| Move a column or row without data | ❌ | ✔️ |
Key idea
onEditreacts to data edits inside cells.onChangereacts to structural changes in the spreadsheet.
This means that formatting changes, sheet structure modifications, or column insertions will not trigger onEdit, but will trigger onChange.
Comparing the event objects
Another major difference is the object passed to the function.
Example: onEdit(e)
onEdit provides detailed information about the edited range.
{
"authMode":"FULL",
"range":{
"columnEnd":14,
"columnStart":14,
"rowEnd":1000,
"rowStart":1
},
"source":{},
"triggerUid":"2212109739582554112",
"user":{
"email":"lidia.calicia@gmail.com",
"nickname":"lidia.calicia"
}
}Important point:
The range property tells you exactly which cells were edited.
Example: onChange(e)
onChange focuses on what type of change happened, not where.
{
"authMode":"FULL",
"changeType":"INSERT_COLUMN",
"source":{},
"triggerUid":"4991534397111926784",
"user":{
"email":"lidia.calicia@gmail.com",
"nickname":"lidia.calicia"
}
}Important point:
Instead of a range, you receive a changeType, such as:
INSERT_ROWINSERT_COLUMNREMOVE_ROWREMOVE_COLUMNFORMATOTHER
Quick rule of thumb
Use:
onEditwhen you need to react to cell value changes.onChangewhen you need to react to spreadsheet structure or formatting changes.
Understanding this distinction avoids many automation bugs in Apps Script projects.
