Task guide
Add a timestamp when a row changes
When you change a status cell, the script writes the current date and time into the same row. You save the script and nothing else needs to be installed.
1 · Prepare
Put these pieces in place
- Open the spreadsheet you want to stamp and create a tab named Tasks.
- Put a task name in column A, a status in column B, and leave column E free for the timestamp.
- Keep your headers in row 1. The script ignores edits in that row.
Change these values
- Sheet name
TasksThe script reacts only to edits made on the tab with this name.
- Watched column
2Column B is column number 2. Change it to the column you want to watch.
- Timestamp column
5Column E is column number 5. The date and time goes here, in the row you edited.
- Date format
yyyy-MM-dd HH:mmThis is how the stamp is written, for example 2024-03-08 14:05.
2 · Review before running
What the script can access and change
Permissions you approve
- Nothing to approve. A simple trigger does not open the authorization dialog.
- The code reads the cell you edited and writes to the timestamp column in the same spreadsheet. It touches no other file.
Effects of one run
- Writes the current date and time into column E of the row you edited on the Tasks tab.
- Does nothing when more than one cell is edited at once, when the edit is on another tab, or when the edit is in row 1.
- Does not change other rows, other tabs, or other files.
3 · Copy
Paste this into the Apps Script editor
Create or open a script file, replace the example values marked above, then save the project.
const SHEET_NAME = 'Tasks'; // The script reacts only to edits made on the tab with this name.
const WATCHED_COLUMN = 2; // Column B is column number 2. Change it to the column you want to watch.
const TIMESTAMP_COLUMN = 5; // Column E is column number 5. The date and time goes here, in the row you edited.
const DATE_FORMAT = 'yyyy-MM-dd HH:mm'; // This is how the stamp is written, for example 2024-03-08 14:05.
/** @param {Events.SheetsOnEdit} e */
function onEdit(e) {
const range = e.range;
const sheet = range.getSheet();
if (sheet.getName() !== SHEET_NAME) return;
if (range.getNumRows() > 1 || range.getNumColumns() > 1) return;
if (range.getColumn() !== WATCHED_COLUMN) return;
const editedRow = range.getRow();
if (editedRow < 2) return;
const stamp = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), DATE_FORMAT);
sheet.getRange(editedRow, TIMESTAMP_COLUMN).setValue(stamp);
} 4 · Run
Follow these steps in order
Make one small test row
On the Tasks tab, put headers in row 1 and one test task in row 2. Leave column E empty so you can watch it fill in.
Paste the function and save
Choose Extensions, then Apps Script. Replace the starter function with this one and save. A function named onEdit is a simple trigger, so there is nothing else to set up and no need to click Run.
Test it by hand
Go back to the spreadsheet and type a word in cell B2 yourself. Within a second or two, cell E2 shows the current date and time.
Point it at your own columns
Change the tab name, the watched column number, and the timestamp column number to match your sheet. Save, then edit one cell again to confirm the stamp lands in the right place.
5 · Confirm
How to tell it worked
A second or two after you change a cell in column B, column E of that same row shows a stamp such as 2024-03-08 14:05.
If the result is different
Troubleshooting
- Nothing appears in column E after I change a cell.
- Check that the tab name matches Tasks exactly, including capital letters and spaces, and that you edited column B in row 2 or below. A simple trigger runs only for edits a person makes in the browser, so a value written by another script or by an import does not start it.
- Pasting a block of cells adds no timestamps.
- Expect this. The getNumRows and getNumColumns check skips any edit that covers more than one cell. Remove that line only if you also write a stamp for every row in the block.
- The Execution log shows "You do not have permission to call GmailApp.sendEmail".
- Move the email code out of onEdit. A simple trigger cannot use services that need approval, such as Gmail or UrlFetchApp. Put that work in a function with another name and run it yourself, or install it as an On edit trigger from Triggers in the left sidebar.
- The stamp shows as a plain number such as 45359.
- Select column E, then choose Format, Number, and then Date time or Plain text. The cell was formatted as a number.
Technical details
Names used in this script
Open these details when you want to adapt the example or look up an exact service or method name.
Show Apps Script symbols and service pages
Apps Script symbols
Service pages
Keep going
Related tasks, basics, and apps
- Task guide Move finished rows to an Archive tab
Move every row marked Done from a Tasks tab to the bottom of an Archive tab. The script deletes rows from Tasks, so test it on a copy of the file first.
- Task guide Add a custom menu to a Google Sheet
Add a menu named Helpful tools to the menu bar of a Google Sheet. Its one item shows which cell is selected. Save the script, reload the Sheet, and the menu appears.
- Task guide Run an Apps Script function every day
Make a function run on its own once a day. Run the setup function once, and from then on Apps Script calls the reminder function each day around the hour you chose.
- Object reference Sheet
A Sheet is one tab inside a Google spreadsheet. Get it with getSheetByName() or getActiveSheet(). Use getLastRow() to find the last row with content, or getRange() to select cells to read.
- Object reference Range
A Range represents one cell such as A2 or a rectangular block of rows and columns in a Sheet. Use getValue() for one cell and getValues() or setValues() for a 2D array of rows.
- Basics Google Apps Script triggers explained
Google Apps Script triggers run functions automatically when a file opens, a cell changes, a form is submitted, or a scheduled time arrives. Use a simple onEdit or onOpen for work in the bound file. Choose an installable trigger for a schedule, form submission, or work that needs authorization.
- Basics Common Apps Script errors and what they mean
Apps Script error messages say what failed, for example TypeError: Cannot read properties of null (reading 'getRange') or ReferenceError. Find the exact message below for its cause and fix.
- Basics Dates, time zones, and Utilities.formatDate
A Date holds one instant in time. Use Utilities.formatDate(date, timeZone, pattern) and Session.getScriptTimeZone() to format it in the right time zone.
- Google app Google Sheets
SpreadsheetApp lets a Google Sheets script read a Sheet or Range, add a custom menu or formula, and act on each row, such as sending one email per row.
- Google app Triggers
A trigger is a saved schedule or event rule in ScriptApp that runs your function on time, on edit, or on form submit.
- Diagnostic TypeError: e.range is not a function
Why e.range is a Range property rather than a method on the onEdit event object.
- Book chapter Validate, highlight, and react to Sheets edits
Add dropdowns, checkboxes, and conditional formatting to Google Sheets, and stamp edits with a guarded onEdit trigger.