编辑器插件的触发器

每当指定的事件发生时,Apps 脚本触发器就会执行指定的脚本函数(触发器函数)。只有某些事件会导致触发器触发,并且每个 Google Workspace 应用都支持一组不同的事件。

当触发器触发时,系统会创建一个事件对象。该 JSON 结构包含已发生事件的详细信息。事件对象结构中的信息会根据触发器类型以不同的方式组织。

创建事件对象后,Apps 脚本会将其作为参数传递给触发器函数。触发器函数是一个您必须自行实现的回调函数,用于采取任何合适的操作来响应事件。例如,在编辑器插件中,触发器用于在文档打开时创建插件菜单项。在这种情况下,您可以实现 onOpen(e) 触发器函数来创建插件所需的菜单项,并可能会使用事件对象中的数据。

本页面介绍了如何在编辑器插件项目中使用触发器。

编辑器插件触发器类型

您可以在编辑器插件中使用适用于 Apps 脚本项目的大多数通用触发器类型,包括简单触发器和大多数可安装的触发器。确切可用的触发器类型取决于要扩展的应用。

下表显示了编辑器插件可以使用的简单触发器和可安装的触发器类型,并提供了指向相应事件对象的链接:

事件 事件对象 简单的触发器 可安装的触发器
打开
系统打开一个编辑器文件。
Google 文档 onOpen 事件对象
Google 表单 onOpen 事件对象
Google 表格 onOpen 事件对象
Google 幻灯片 onOpen 事件对象
文档
表单*
表格
幻灯片

function onOpen(e)

文档
表单
表格
安装
已安装插件。
onInstall 事件对象 文档
表单
表格
幻灯片

function onInstall(e)

修改
电子表格单元格内容已更改。
Google 表格 onEdit 事件对象 表格

function onEdit(e)

表格
更改
工作表中的内容经过编辑或设置了格式。
Google 表格 onChange 事件对象 表格
表单提交
已提交 Google 表单。
表单提交事件对象
表单提交事件对象
表单
表格
时间驱动(时钟)
触发器按指定的时间或时间间隔触发。
时间驱动的事件对象 文档
表单
表格
幻灯片

* Google 表单的打开事件不会出现在用户打开要回复的表单时,而是由编辑器打开表单进行修改。

插件中的简单触发器

简单触发器使用设置的函数预留名称,无法使用需要授权的服务,并且会自动启用以供使用。在某些情况下,简单的触发器事件可以由可安装的触发器处理。

只需使用以下任何预留名称实现一个函数,即可向插件添加简单的触发器:

  • onOpen(e) 会在用户打开文档、电子表格或演示文稿时执行。在编辑器中打开表单时,还可以执行 onOpen(e)(而不是在响应表单时执行)。仅当用户有权修改相关文件时,系统才会执行该命令,并且最常用于创建菜单项
  • onInstall(e) 会在用户安装插件时执行。通常,onInstall(e) 仅用于调用 onOpen(e);这样可确保插件菜单在安装后立即显示,而无需用户刷新页面。
  • 当用户更改电子表格中的单元格值时,系统会执行 onEdit(e)。此触发器不会响应单元格移动、格式更改或其他不会更改单元格值的更改。

限制

插件中的简单触发器受到与其他类型的 Apps 脚本项目的简单触发器相同的限制。在设计插件时,请注意以下限制:

  • 如果文件在只读(查看或评论)模式下打开,系统不会运行简单触发器。此行为会阻止系统填充您的插件菜单。
  • 在某些情况下,编辑器插件会在无授权模式下运行其 onOpen(e)onEdit(e) 简单触发器。此模式会显示一些额外的复杂功能(如插件授权模型中所述)。
  • 简单触发器不能使用服务或采取需要授权的其他操作,插件授权模型中所述的情况除外。
  • 简单的触发器的运行时长不能超过 30 秒。请注意,尽可能降低在简单触发器函数中完成的处理量。
  • 简单的触发器受 Apps 脚本触发器配额限制的约束。

插件中的可安装触发器

插件可以通过 Apps 脚本 Script 服务以编程方式创建和修改可安装触发器。插件无法手动创建。与简单的触发器不同,可安装的触发器可以使用需要授权的服务。

当插件出现错误时,插件中的可安装触发器不会向用户发送错误电子邮件,因为在大多数情况下,用户无法解决问题。因此,您应该将插件设计为尽可能代表用户妥善处理错误。

插件可以使用以下可安装触发器:

  • 当用户打开文档、电子表格或编辑器中打开表单时(而不是回复表单时),执行可安装的触发器。
  • 当用户更改电子表格中的单元格值时,系统会执行修改可安装的触发器。此触发器不会响应格式更改或其他不会更改单元格值的更改。
  • 当用户在电子表格中执行任何更改时,系统都会执行更改可安装触发器,包括格式修改和对电子表格本身的修改(例如添加行)。
  • 表单提交可安装触发器在提交 Google 表单响应时执行。

  • 时间驱动型触发器(也称为时钟触发器)在特定时间触发,或按固定时间间隔重复触发。

为可安装的触发器授权

通常,如果开发者更新某个插件以使用需要额外授权的新服务,那么系统会在用户下次使用该插件时提示用户重新授权。

不过,使用触发器的插件会遇到特殊的授权挑战。假设某个插件使用触发器监控表单提交:表单创建者可能会在第一次使用该插件时对其进行授权,然后让其持续运行数月或数年,而无需重新打开表单。如果插件开发者更新该插件以使用需要额外授权的新服务,表单创建者将永远不会看到重新授权对话框,因为他们从未重新打开该表单,并且插件将停止运行。

与常规 Apps 脚本项目中的触发器不同,插件中的触发器仍会继续触发,即使它们需要重新授权也是如此。不过,如果脚本到达需要授权行没有授权的代码行,它仍然会失败。为避免这种情况,开发者可以使用 ScriptApp.getAuthorizationInfo() 方法限制对插件的已发布版本之间发生更改的代码访问。

下面列出了推荐在触发器函数中使用的结构,以避免授权问题。示例触发器函数在 Google 表格插件中响应表单提交事件,如果需要重新授权,则使用模板化 HTML 向该插件的用户发送提醒电子邮件。

Code.gs

触发器/表单/代码.gs
/**
 * Responds to a form when submitted.
 * @param {event} e The Form submit event.
 */
function respondToFormSubmit(e) {
  const addonTitle = 'My Add-on Title';
  const props = PropertiesService.getDocumentProperties();
  const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL);

  // Check if the actions of the trigger requires authorization that has not
  // been granted yet; if so, warn the user via email. This check is required
  // when using triggers with add-ons to maintain functional triggers.
  if (authInfo.getAuthorizationStatus() ===
    ScriptApp.AuthorizationStatus.REQUIRED) {
    // Re-authorization is required. In this case, the user needs to be alerted
    // that they need to re-authorize; the normal trigger action is not
    // conducted, since it requires authorization first. Send at most one
    // "Authorization Required" email per day to avoid spamming users.
    const lastAuthEmailDate = props.getProperty('lastAuthEmailDate');
    const today = new Date().toDateString();
    if (lastAuthEmailDate !== today) {
      if (MailApp.getRemainingDailyQuota() > 0) {
        const html = HtmlService.createTemplateFromFile('AuthorizationEmail');
        html.url = authInfo.getAuthorizationUrl();
        html.addonTitle = addonTitle;
        const message = html.evaluate();
        MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
            'Authorization Required',
            message.getContent(), {
              name: addonTitle,
              htmlBody: message.getContent()
            }
        );
      }
      props.setProperty('lastAuthEmailDate', today);
    }
  } else {
    // Authorization has been granted, so continue to respond to the trigger.
    // Main trigger logic here.
  }
}

Authorizationemail.html

trigger/form/AuthorizationEmail.html
<p>The Google Sheets add-on <i><?= addonTitle ?></i> is set to run automatically
    whenever a form is submitted. The add-on was recently updated and it needs you
    to re-authorize it to run on your behalf.</p>

<p>The add-on's automatic functions are temporarily disabled until you
    re-authorize it. To do so, open Google Sheets and run the add-on from the
    Add-ons menu. Alternatively, you can click this link to authorize it:</p>

<p><a href="<?= url ?>">Re-authorize the add-on.</a></p>

<p>This notification email will be sent to you at most once per day until the
    add-on is re-authorized.</p>

限制

插件中的可安装触发器受到与其他类型的 Apps 脚本项目中的可安装触发器相同的限制

除了这些限制之外,一些额外的限制专门适用于插件中的可安装触发器:

  • 在每个插件中,每位用户、每个插件在每个类型中只能有一个触发器。 例如,在给定电子表格中,给定用户只能有一个修改触发器,但用户可能在同一电子表格中还有表单提交触发器或时间驱动触发器。有权访问同一电子表格的其他用户可能拥有自己的一组触发器。
  • 插件只能为使用该插件的文件创建触发器。 也就是说,Google 文档 A 中使用的插件不能创建触发器来监控 Google 文档 B 的打开时间。
  • 时间驱动型触发器的运行频率不得超过每小时一次。
  • 当可安装触发器运行的代码抛出异常时,插件不会自动向用户发送电子邮件。开发者应自行检查并妥善处理失败情况。
  • 在以下任一情况下,插件触发器都会停止触发:
    • 如果用户已卸载该插件,
    • 如果文档中的插件已停用(如果重新启用),触发器会再次变为可运行状态,或者
    • 如果开发者取消发布插件或向插件商店提交损坏的版本,
  • 插件触发器函数会执行,直到到达使用未经授权的服务的代码为止。此时,这些代码会停止。仅当插件已发布时,才会出现这种情况;如果脚本的任何部分需要授权,那么常规 Apps 脚本项目中的同一触发器或未发布的插件根本不会执行。
  • 可安装触发器受到 Apps 脚本触发器配额限制的约束。