是否可以通过 google 应用程序脚本中的 onFormSubmit 调用 SpreadsheetApp.getUi()?

Is it possible to invoke SpreadsheetApp.getUi() via onFormSubmit in google app script?

使用我的电子表格绑定脚本,此代码在从 onOpen 调用时工作正常。从 onFormSubmit 调用时出现此错误:"Cannot call SpreadsheetApp.getUi() from this context."

        function showSidebar(issue,row) {
        var html = HtmlService
            .createTemplateFromFile('MySidebar');
        html.issue = issue;
        html.row = row;        
        SpreadsheetApp.getUi()
            .showSidebar(html.evaluate().setTitle('Alert'));
}

它不会起作用,因为从技术上讲,电子表格不是“用户界面”的“当前实例”。

Google Documentation - Custom Sidebars

即使您的脚本已绑定到电子表格,并且 getUi 可以与它​​绑定到的任何文件一起使用,但它是从另一个文件调用的。

您甚至可以 运行 从脚本编辑器“手动”编写该代码,它会添加一个自定义对话框,但如果您从提交的表单中调用它,它将不起作用。

您不能通过 SpreadsheetApp 从像 onFormSubmit() 这样的触发器直接访问价差 sheet,因为在调用 onFormSubmit() 时,价差sheet 脱离上下文 - onFormSubmit() 超出了它所针对的形式和脚本链接到的传播 sheet(如果有)。不幸的是,没有真正简单的解决方法。

此外,如果调用 getUi() 的函数不是从传播 sheet 本身的用户界面执行的,则不能调用 getUi() - 因为触发 运行 在后台,不一定会有 UI 可以这么说。

在尝试以下解决方案之前,请考虑以下事项:如果您使用的是您自己制作的表单,而不是您编写代码创建的表单,请考虑使用 高级设置[下的数据验证选项] =57=] 在表单编辑器中。例如,对于文本问题,您可以要求回答是一个范围内的整数,或者您可以要求回答与正则表达式相匹配。如果这不起作用,请尝试以下操作:

首先,我们需要打开传播sheet(以编程方式),然后才能使用它。我发现最简单的方法是将 spreadsheet ID 或 URL 存储在 spreadsheet 及其服务器端函数可以访问的某个地方。有多种方法可以做到这一点。例如,您可以使用属性服务(通过另一个服务器端函数,因为此时 onFormSubmit() 仍然没有 "know" 任何传播 sheets)。我发现访问 spreadsheet 的其他服务器端函数即使从像 onFormSubmit 这样由触发器调用的函数调用时也能正常工作。

您可以在 onInstall 函数中保存传播 sheet ID 或 URL 以确保它被保存。 (这适用于未来的用户,但如果您此时通过触发器测试调用 onFormSubmit(),它将不起作用,因为 ID 尚未保存在任何地方。要解决此问题,请添加与您相同的代码用于将onInstall函数中的ID或URL保存到onOpen函数中,然后refresh/open你的spreadsheet。然后你可以删除ID-或 URL - 从 onOpen 函数中保存代码(但将其保留在 onInstall 函数中!)。然后,在 Code.gs 文件(或任何文件)中使用不同的函数有你的服务器端功能)来检索那个传播sheet ID或URL并调用SpreadsheetApp.openByID(id)SpreadsheetApp.openByUrl(url)打开传播sheet.

之后,如果需要,您应该可以使用 getActiveSheet 或类似的。

不幸的是,我们仍然不能从这个上下文中调用 getUi()。当您考虑它时,这是有道理的,因为没有办法知道用户是否打开了 spreadsheet,并且您不希望您的触发代码达到执行时间限制,因为没有响应 alert/prompt.

我会做的是:

  • 当您收到新的表单提交时,您的 onFormSubmit(或等效)函数将被调用。
  • 从那里,您可以检查表单回复的有效性。但是,与其向用户显示警报,不如向他们发送电子邮件(只要确保您发送的邮件不要太多)。这样,用户可以收到问题通知并自行处理,如果他们没有打开 spreadsheet,他们就不会错过无效的提交。您还可以包含一个 URL,让用户可以使用下一个要点中的说明编辑他们的回复。
  • 您可以获得 URL 来编辑回复
    1. 通过 ID 或 URL 使用类似于我上面描述的方法获取表单(例如 FormApp.openByUrl(url))[onFormSubmit 不在表单的文档中,因此您必须 "open"表格]
    2. 获取表单中调用 getResponses() 的所有响应的数组
    3. 要么按时间戳查找最新响应,要么仅通过获取响应数组的最后一个元素来获取最新响应。第二种方法有一个警告,例如,当您正在处理一个提交时,在提交和代码完成提交处理之间的时间内,收到另一个提交,数组中的最后一个响应来自 getResponses 变化。我不能说这对你来说是否是个问题,因为我不知道你期望回复的频率有多高,但这是需要考虑的事情。如果您正在查看时间戳(第一种方法),可以想象在极少数情况下两个响应可能具有相同的时间戳。 (或者,与其只关注 onFormSubmit 中的最新响应,您还可以检查表单响应 sheet 中没有添加特定值的行(在处理一行之后),然后处理所有不具有该值的行(因此尚未处理)。但是您不需要这样做,除非非常接近连续的响应是一个问题。)