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

时间:2015-02-03 02:23:23

标签: google-apps-script google-sheets

使用我的电子表格绑定脚本,从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'));
}

2 个答案:

答案 0 :(得分:1)

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

Google Documentation - Custom Sidebars

即使您的脚本绑定到电子表格,并且getUi适用于它绑定的任何文件,它也会从另一个文件中调用。

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

答案 1 :(得分:0)

您无法通过SpreadsheetApp从onFormSubmit()等触发器直接访问电子表格,因为在调用onFormSubmit()时,电子表格已脱离上下文 - onFormSubmit()外部它的形式和脚本链接到的电子表格(如果有的话)。不幸的是,这并不是一个简单的解决方法。

此外,如果调用getUi()的函数不是从电子表格本身的用户界面执行此操作,则无法调用getUi() - 因为触发器在后台运行,可以这么说,赢得不一定是一个可以获得的用户界面。

在您尝试以下解决方案之前,请考虑以下事项:如果您使用的是您自己创建的表单,而不是您编写要创建的代码,请考虑使用高级设置下的数据验证选项表单编辑器。例如,对于文本问题,您可以要求响应为范围内的整数,或者您可能需要响应以匹配正则表达式。如果这不起作用,请尝试以下方法:

首先,我们需要先打开电子表格(以编程方式)才能使用它。我发现最简单的方法是将电子表格ID或URL存储在电子表格及其服务器端功能可访问的位置。有多种方法可以做到这一点。例如,您可以使用属性服务(通过另一个服务器端功能,因为此时onFormSubmit()仍然不知道任何电子表格中的#34;)。我发现,即使从触发器调用的onFormSubmit函数调用,访问电子表格的其他服务器端函数也能正常工作。

您可以在onInstall功能中保存电子表格ID或网址,以确保其得到保存。 (这适用于未来的用户,但如果此时通过触发器测试onFormSubmit(),则无法正常工作,因为ID尚未保存在任何地方。要解决此问题,请添加相同内容用于将onInstall函数中的ID或URL保存到onOpen函数的代码,然后刷新/打开电子表格。然后,您可以从{{{{{{{{ 1}} function(但保留在onOpen函数中!)。然后,在Code.gs文件中使用不同的函数(或其中包含服务器端函数的文件)来检索该电子表格ID或网址并致电onInstallSpreadsheetApp.openByID(id)以打开电子表格。

之后,如果需要,您应该可以使用SpreadsheetApp.openByUrl(url)或类似内容。

很遗憾,我们仍然无法从此上下文中调用getActiveSheet。当你考虑它时,这是有道理的,因为没有办法知道用户是否打开了电子表格,你不希望你的触发代码达到执行时间限制,因为没有响应警报/提示。

我要做的是以下内容:

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