Time-driven triggers
A time-driven trigger runs a function on a schedule without anyone opening the sheet. Create it in the editor under Triggers (clock icon), Add Trigger, event source Time-driven, or in code: ScriptApp.newTrigger("dailyReport").timeBased().atHour(7).everyDays(1).create(). The function then uses getSheetByName or openById, never getActiveSheet.
Syntax
ScriptApp.newTrigger(functionName).timeBased().everyHours(n) | .atHour(h).everyDays(1) | .onWeekDay(ScriptApp.WeekDay.MONDAY) .create()| Part | What it is |
|---|---|
everyMinutes(n) | 1, 5, 10, 15 or 30 |
everyHours(n) / everyDays(n) / everyWeeks(n) | Repeat interval |
atHour(h) | Hour of day (0 to 23) in the script time zone; the exact minute is random within that hour |
onWeekDay(day) | ScriptApp.WeekDay.MONDAY etc., combine with atHour |
at(date) | One-off run at a specific Date |
Examples
function createDailyTrigger() {
ScriptApp.newTrigger("dailyReport").timeBased().atHour(7).everyDays(1).create();
}Result: dailyReport runs every day between 7:00 and 8:00 in the script time zone
ScriptApp.newTrigger("syncOrders").timeBased().everyHours(1).create();Result: syncOrders runs about once per hour
ScriptApp.newTrigger("weeklyDigest").timeBased().onWeekDay(ScriptApp.WeekDay.MONDAY).atHour(9).create();Result: weeklyDigest runs every Monday morning
function deleteTriggersFor(name) {
ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === name)
.forEach(t => ScriptApp.deleteTrigger(t));
}Result: Removes every trigger pointing at that function; run before creating a new one to avoid duplicates
Common mistakes
- The scheduled function fails with Cannot read properties of null: it uses getActiveSheet or getUi; triggers have no active sheet or UI, so use getSheetByName and skip dialogs.
- The script runs twice a day: the trigger creation function was run twice; delete existing triggers for that handler first.
- Runs at the wrong hour: atHour uses the project time zone (Project Settings), not your browser's; set it to your zone.
- This trigger has been disabled for too many failures: fix the error shown in Executions, then recreate the trigger.
Practice Time-driven triggers
These drills check your answer on live data, free, no account needed.
- Sleep with a PromiseReturn a Promise that resolves (with `undefined`) after `ms` milliseconds, so callers can write `await sleep(500)`. It must always return a Promise, even for `sleep(0)`. Tests run on a fake clock: `setTimeout`, `clearTimeout` and `Date.now` are simulated, so waits are instant and exact.
- Retry a failing callCall `fn()` until it succeeds, at most `attempts` times, and resolve with its result. `fn` may return a Promise or a plain value, and it may throw or reject. If every attempt fails, reject with the error from the last attempt.
- Run tasks in sequence`tasks` is an array of functions; each returns a Promise or a plain value. Run them one at a time, in order, starting each only after the previous one has finished, and resolve with the array of their results. If a task fails, reject and do not start the remaining tasks. Tests run on a fake clock: `setTimeout`, `clearTimeout` and `Date.now` are simulated, so waits are instant and exact.
Questions
Can I run a script every minute?
Yes with everyMinutes(1), but each run counts against daily trigger runtime quota (90 minutes per day on free accounts), so prefer 5 or 15 minutes unless you really need it.
Who runs a time-driven trigger?
The account that created it. The script can only access what that account can, and emails are sent from that account.
Related
- Installable triggersInstallable triggers in Google Apps Script: how they differ from simple triggers, creating them from the UI or ScriptApp.newTrigger, onChange, onFormSubmit.
- onEdit triggerUse the onEdit trigger in Google Apps Script: the event object with range, value and oldValue, limiting it to one sheet or column, timestamps, installable.
- PropertiesServiceStore settings and secrets in Google Apps Script with PropertiesService: script, user and document properties, setProperty and getProperty, JSON values, keys.
- Send email from a sheetSend email from Google Sheets with Apps Script: MailApp.sendEmail and GmailApp.sendEmail with HTML body, cc and attachments, loop a list of recipients, quota.