可安装触发器

简单触发器一样,可安装的触发器可让 Apps 脚本在发生特定事件(例如打开文档)时自动运行函数。不过,可安装的触发器比简单的触发器更灵活:它们可以调用需要授权服务,提供多种其他类型的事件(包括基于时间的 [时钟] 触发器),并且可以通过编程方式进行控制。对于简单触发器和可安装触发器,Apps Script 都会向触发的函数传递一个事件对象,其中包含与事件发生情境相关的信息。

限制

虽然可安装的触发器比简单触发器更灵活,但仍存在一些限制:

  • 如果文件以只读(查看或评论)模式打开,则不会运行这些脚本。对于独立脚本,用户至少需要对脚本文件拥有查看权限,才能正常运行触发器。
  • 脚本执行和 API 请求不会导致触发器运行。例如,调用 FormResponse.submit() 提交新的表单回复不会导致表单的提交触发器运行。

  • 可安装的触发器始终在其创建者的账号下运行。例如,如果您创建了可安装的“打开”触发器,那么当您的同事打开文档时(如果您的同事拥有修改权限),该触发器就会运行,但它会以您的账号运行。这意味着,如果您创建了在打开文档时发送电子邮件的触发器,则电子邮件始终会从您的账号发送,而非一定是从打开文档的账号发送。不过,您可以为每个账号创建一个可安装的触发器,这样系统就会从每个账号发送一封电子邮件。

  • 给定账号无法看到通过第二个账号安装的触发器,即使第一个账号仍可激活这些触发器。

  • 可安装的触发器受 Apps 脚本触发器配额限制的约束。

基于时间的触发器

基于时间的触发器(也称为时钟触发器)类似于 Unix 中的 cron 作业。借助基于时间的触发器,您可以让脚本在特定时间或按周期性间隔执行,频率可以高达每分钟一次,也可以低至每月一次。(请注意,插件每小时最多只能使用一次基于时间的触发器。)时间可能会略微随机化 - 例如,如果您创建了上午 9 点的周期性触发器,Google Apps 脚本会选择上午 9 点到 10 点之间的时间,然后每天保持一致的时间,以便在 24 小时后触发器再次触发。

以下示例展示了 Google Chat 应用每分钟向其所在的每个聊天室发送一条消息:

// Example app for Google Chat that demonstrates app-initiated messages
// by spamming the user every minute.
//
// This app makes use of the Apps Script OAuth2 library at:
//     https://github.com/googlesamples/apps-script-oauth2
//
// Follow the instructions there to add the library to your script.

// When added to a space, we store the space's ID in ScriptProperties.
function onAddToSpace(e) {
  PropertiesService.getScriptProperties()
      .setProperty(e.space.name, '');
  return {
    'text': 'Hi! I\'ll post a message here every minute. ' +
            'Please remove me after testing or I\'ll keep spamming you!'
  };
}

// When removed from a space, we remove the space's ID from ScriptProperties.
function onRemoveFromSpace(e) {
  PropertiesService.getScriptProperties()
      .deleteProperty(e.space.name);
}

// Add a trigger that invokes this function every minute in the
// "Edit > Current Project's Triggers" menu. When it runs, it
// posts in each space the app was added to.
function onTrigger() {
  var spaceIds = PropertiesService.getScriptProperties()
      .getKeys();
  var message = { 'text': 'Hi! It\'s now ' + (new Date()) };
  for (var i = 0; i < spaceIds.length; ++i) {
    postMessage(spaceIds[i], message);
  }
}
var SCOPE = 'https://www.googleapis.com/auth/chat.bot';
// The values below are copied from the JSON file downloaded upon
// service account creation.
// For SERVICE_ACCOUNT_PRIVATE_KEY, remember to include the BEGIN and END lines
// of the private key
var SERVICE_ACCOUNT_PRIVATE_KEY = '...';
var SERVICE_ACCOUNT_EMAIL = 'service-account@project-id.iam.gserviceaccount.com';

// Posts a message into the given space ID via the API, using
// service account authentication.
function postMessage(spaceId, message) {
  var service = OAuth2.createService('chat')
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')
      .setPrivateKey(SERVICE_ACCOUNT_PRIVATE_KEY)
      .setClientId(SERVICE_ACCOUNT_EMAIL)
      .setPropertyStore(PropertiesService.getUserProperties())
      .setScope(SCOPE);
  if (!service.hasAccess()) {
    Logger.log('Authentication error: %s', service.getLastError());
    return;
  }
  var url = 'https://chat.googleapis.com/v1/' + spaceId + '/messages';
  UrlFetchApp.fetch(url, {
    method: 'post',
    headers: { 'Authorization': 'Bearer ' + service.getAccessToken() },
    contentType: 'application/json',
    payload: JSON.stringify(message),
  });
}

事件驱动型触发器

可安装的事件驱动型触发器在概念上与 onOpen()简单触发器类似,但它们可以响应其他事件,并且行为不同。

例如,每当具有修改权限的任何用户打开 Google 表格时,适用于 Google 表格的可安装的打开触发器都会激活,就像简单的 onOpen() 触发器一样。不过,可安装版本可以调用需要授权服务。安装版本在创建触发器的用户授权下运行,即使其他拥有编辑权限的用户打开电子表格也是如此。

Google Workspace 应用有多个可安装的触发器:

  • 当用户打开自己有权修改的电子表格、文档或表单时,系统会运行可安装的打开触发器。
  • 当用户修改电子表格中的值时,系统会运行可安装的修改触发器。
  • 当用户修改电子表格本身的结构(例如,添加新工作表或移除列)时,系统会运行可安装的更改触发器。
  • 当用户回复表单时,系统会运行可安装的表单提交触发器。表单提交触发器有两个版本,一个适用于 Google 表单本身另一个适用于表单提交到电子表格时
  • 当用户的日历活动发生更新(创建、修改或删除)时,可安装的日历活动触发器会运行。

您可以在独立脚本和绑定脚本中使用可安装的触发器。例如,一个独立脚本可以通过调用 TriggerBuilder.forSpreadsheet(key) 并传入电子表格的 ID,以编程方式为任意 Google 表格文件创建可安装的触发器。

手动管理触发器

如需在脚本编辑器中手动创建可安装的触发器,请按以下步骤操作:

  1. 打开您的 Apps 脚本项目。
  2. 点击左侧的触发器图标
  3. 点击右下角的添加触发器
  4. 选择并配置要创建的触发器类型。
  5. 点击保存

以编程方式管理触发器

您还可以使用脚本服务以编程方式创建和删除触发器。首先调用 ScriptApp.newTrigger(functionName),它会返回 TriggerBuilder

以下示例展示了如何创建两个基于时间的触发器:一个触发器每 6 小时触发一次,另一个触发器每周一上午 9 点触发一次(以脚本设置的时区为准)。

triggers/triggers.gs
/**
 * Creates two time-driven triggers.
 * @see https://developers.google.com/apps-script/guides/triggers/installable#time-driven_triggers
 */
function createTimeDrivenTriggers() {
  // Trigger every 6 hours.
  ScriptApp.newTrigger('myFunction')
      .timeBased()
      .everyHours(6)
      .create();
  // Trigger every Monday at 09:00.
  ScriptApp.newTrigger('myFunction')
      .timeBased()
      .onWeekDay(ScriptApp.WeekDay.MONDAY)
      .atHour(9)
      .create();
}

下一个示例展示了如何为电子表格创建可安装的打开触发器。请注意,与简单的 onOpen() 触发器不同,可安装触发器的脚本无需绑定到电子表格。如需通过独立脚本创建此触发器,只需将 SpreadsheetApp.getActive() 替换为对 SpreadsheetApp.openById(id) 的调用即可。

triggers/triggers.gs
/**
 * Creates a trigger for when a spreadsheet opens.
 * @see https://developers.google.com/apps-script/guides/triggers/installable
 */
function createSpreadsheetOpenTrigger() {
  const ss = SpreadsheetApp.getActive();
  ScriptApp.newTrigger('myFunction')
      .forSpreadsheet(ss)
      .onOpen()
      .create();
}

如需程序化地修改现有的可安装触发器,您必须将其删除并创建一个新触发器。如果您之前存储了触发器的 ID,可以将该 ID 作为参数传递给以下函数,以删除该触发器。

triggers/triggers.gs
/**
 * Deletes a trigger.
 * @param {string} triggerId The Trigger ID.
 * @see https://developers.google.com/apps-script/guides/triggers/installable
 */
function deleteTrigger(triggerId) {
  // Loop over all triggers.
  const allTriggers = ScriptApp.getProjectTriggers();
  for (let index = 0; index < allTriggers.length; index++) {
    // If the current trigger is the correct one, delete it.
    if (allTriggers[index].getUniqueId() === triggerId) {
      ScriptApp.deleteTrigger(allTriggers[index]);
      break;
    }
  }
}

触发器中的错误

当可安装的触发器触发,但函数抛出异常或以其他方式未能成功运行时,您不会在屏幕上看到错误消息。毕竟,当基于时间的触发器运行或其他用户启用表单提交触发器时,您可能根本不在计算机旁边。

而是会向您发送如下电子邮件:

From: noreply-apps-scripts-notifications@google.com
Subject: Summary of failures for Google Apps Script
Your script has recently failed to finish successfully.
A summary of the failure(s) is shown below.

该电子邮件中包含用于停用或重新配置触发器的链接。如果脚本绑定到 Google 表格、文档或表单文件,电子邮件中还会包含指向该文件的链接。通过这些链接,您可以停用触发器或修改脚本以修复 bug。

如需查看与您的 Google 账号关联的所有触发器,并停用不再需要的触发器,请按以下步骤操作:

  1. 前往 script.google.com
  2. 点击左侧的我的触发器
  3. 如需删除某个触发器,请依次点击相应触发器右侧的“更多”图标 > 删除触发器

插件中的触发器

除了可安装的触发器之外,您还可以在插件中使用清单触发器。如需了解详情,请参阅 Google Workspace 插件触发器