【问题标题】:onSubmit Trigger Executed Without Form SubmissiononSubmit 触发器在没有提交表单的情况下执行
【发布时间】:2019-09-19 13:37:27
【问题描述】:

我创建了一个 Google 表单,链接到一个工作表以捕获响应,并添加了一个在每次提交表单时运行的 Apps 脚本。通过一系列测试,一切正常 - 表单响应通过,onSubmit 功能运行良好。不过,昨晚我们收到了一些脚本的执行,即使表单没有提交。

查看表单本身的响应页面,当我收到通知时没有提交。此外,这不是我组织中的公共表格,除了我自己之外,只有其他人拥有该链接。他确认他在处决时没有提交表格。

Google 表格中有两张表格:1> 表单回复和 2> 数据。数据表使用一些QUERY 函数从响应表中提取数据,并对其进行不同的格式化(例如,将连字符放在电话号码中,将某些字段呈现为大写等)。此外,数据表标题的标记与表格问题不同(例如,“homeAdd1”而不是“家庭地址行 1”)。这是因为脚本创建了一个 PDF,使用表单响应替换模板 Google Doc 上的占位符 ('%homeAdd1%')。然后脚本获取生成的 PDF 并将其通过电子邮件发送给提交者。

在昨天的测试之前,一切都很好。当时我并没有意识到,但是当我的同事输入随机值来测试表格时,对于家庭地址行 2,他只输入了一个 5 位数的邮政编码。它生成了一个 PDF 罚款,并将其通过电子邮件发送给他,但这导致 QUERY 函数呈现 #VALUE 错误。函数如下所示:

=QUERY(Responses!L2:S,"SELECT UPPER(L) UPPER(M)...

因此,当 Sheets 看到一个只有 5 位数字的单元格时,它会自动将其呈现为数字,而 UPPER 不适用于数字值。我(愚蠢地)没想到将所有两张纸都预先格式化为纯文本,所以发生了这种情况。

链接到表单和 Apps 脚本的 Google 表格上的 #VALUE 错误是否会导致 onSubmit 函数失灵?这是我能看到的唯一可能导致它的事情,但它没有意义。我已经修复了格式问题,但我不知道错误执行是否意味着其他问题。

随着额外的提交,脚本只是一次又一次地发送最新的 PDF。在 20 秒内,它触发了 5 次,每次都发送通过电子邮件生成的最后一个 PDF。查看 Stackdriver 日志,与我们昨天早些时候测试它时没有什么不同。 console.logconsole.info 命令工作正常,它们都被列为由 onSubmit 函数触发。

这是脚本:

提交函数:

function onSubmit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
  var list = ss.getRange("A1:A").getValues();
  var row = list.filter(String).length;
  var email = ss.getRange(row,2).getValue();
  var newResponse = ss.getRange(row,3).getValue();
  if (newResponse == 'Generate New') {
    newOne(ss,row,email);
  } else if (newResponse == 'Upload Completed') {
    completed(ss,row,email);
  } else {
  }
}

执行的函数:

function newOne(ss,row,email) {
  var name = ss.getRange(row,4).getValue();
  console.log('Function Start - ' + name);
  var newType = ss.getRange(row,6).getValue();
  var copyFile = DriveApp.getFileById('[file id]').makeCopy();
  var copyDoc = DocumentApp.openById(copyFile.getId());
  var copyBody = copyDoc.getActiveSection();
  // Replacing variables with values on spreadsheet
  console.log('Create file start - ' + name);
  var newInfo = ss.getRange(row, 1, 1, 29).getDisplayValues();
  var header = ss.getRange(1, 1, 1, 29).getDisplayValues();
  for (var i = 1; i <= 5; i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  var x;
  if (newType == 'Office 1') {
    x = 6;
  } else if (newType == 'Office 2') {
    x = 15;
  } else {
  }
  for (var i = x; i <= (x + 8); i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  copyBody.replaceText('%' + header[0][26] + '%', newInfo[0][26].toString());
  // Create the PDF file, rename it, and delete the doc copy
  copyDoc.saveAndClose();
  var newFile = DriveApp.createFile(copyFile.getAs('application/pdf'));
  newFile.setName('New - ' + name + '.pdf');
  copyFile.setTrashed(true);
  console.log('Create file finished - ' + name);
  //Mails PDF to submitter
  console.info('Pre-email log for ' + name);
  MailApp.sendEmail(email,'Email Subject','', {
                    noReply: true,
                    htmlBody: "<body>Hello, and thank you.</body>",
                    attachments: [newFile]
                    });
  console.info('Email sent for ' + name);
  appFile.setTrashed(true);
}

任何见解/帮助将不胜感激;谢谢!

乔什

【问题讨论】:

  • 我之前曾多次触发一次提交(解决方案是脚本锁定,等待几秒钟后返回),但从未见过完全空的 onsubmit。我无法想象结果页面上的任何内容都可能导致这种行为。
  • @J.G.好吧,很高兴知道结果页面上的错误不太可能导致随机提交。是的,不知道半夜的空提交是关于什么的。

标签: google-apps-script google-sheets google-forms


【解决方案1】:

虚假的不需要的事件触发器

我遇到了来自 onFormSubmit 事件触发器的虚假触发器的问题。就我而言,它们总是在表单提交发生真正触发之后立即发生。我发现我可以识别它们,因为我要求的问题都没有得到回答。我讨论它here

您可能值得花时间捕获 e.values 数组,看看您是否可以找到一种一致的方法来防止它们导致您的处理功能失灵。

【讨论】:

  • 不知道为什么我在搜索时没有遇到您的问题,但感谢您的帮助!我将把 if(e.values &amp;&amp; !e.values[1]){return;} 逻辑放入顶部函数中以捕获任何不需要的提交(所有响应都是必需的)。希望这将解决问题!这些通常在一夜之间发生,所以我今晚将在那里再次测试。
  • 实际上,这是一个适用于我的问题集的示例。基本上,我所看到的是在 e.values 数组中空白的虚假触发器中需要问题。所以我决定利用这个事实来消除这些不需要的触发器来运行我的函数。所以你会想看看你的样子。所以我建议记录时间和 e.values 数组,看看它们长什么样。
  • 明白了;是的,我确实添加了一个console.log 条目以在每次执行该顶级函数时(在if(e.values... 行之前)捕获e.values,并且当我再次测试时它们会很好地出现。我会密切关注这些日志以查看这些值是否为空,我猜如果它们为空,if 语句将防止这种情况再次发生。如果它们不是空的,我将不得不看看还有什么可能导致不需要的提交。
  • 好吧,这看起来已经解决了!在 Apps 脚本仪表板中,我可以看到额外的提交,但函数执行只持续了几分之一秒,因为它被 if(e.values &amp;&amp; !e.values[1]){return;} 行捕获。 e.values[1] 我的表单是必填字段,只是一个文本字段。我注意到有时在这些额外的提交中确实会出现值,它们通常是日期或只是数字值。我们没有启用选项让人们在事后编辑他们的答案,所以我不确定发生了什么。不管怎样,现在看起来不错!谢谢!
【解决方案2】:

据我所知,onSubmit(e) 无法按您预期的方式工作。

我认为您正在寻找的是一个 onFormSubmit 触发器,请尝试使用 Class SpreadsheetTriggerBuilder documentation 中的以下内容创建一个脚本触发器,该触发器在每次有人向您的链接表单提交响应时执行:

var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("function name")
  .forSpreadsheet(sheet)
  .onFormSubmit()
  .create();

【讨论】:

  • 我使用的是installable trigger,它允许我选择在提交表单时运行哪个函数(从应用程序脚本仪表板)。每次创建一个新触发器会不会有使用可安装触发器没有的好处?我对 Apps 脚本比较陌生(大约 1 年),所以我以前没有听说过 Trigger Builder。以及如何触发该构建器?不确定我是否关注。
  • 使用触发器生成器而不是您提到的方式创建触发器实际上并没有太大的不同。运行触发器构建器脚本后,它会添加一个触发器,您通常会在其中找到它们。
【解决方案3】:

我安装了一个电子表格和相应的表单,我在表单提交事件中经常出现重复,莫名其妙。它不会发生在其他安装中。如果这是你的情况,你不能只检查事件是否为空,因为要测试它是否为空,你必须有一些东西要测试。如果它是未定义的,你会得到一个错误。所以首先测试它是否未定义。试试这个代码:

`function formSubmitted(e) {
  // Deal with the unusual case that this is a bogus event
  if ((typeof e === "undefined") || (e == null) || (e.length == 0))  { 
    Logger.log("formSubmitted() received a bogus or empty event");
    return;
  }
  ...`

【讨论】:

    猜你喜欢
    • 2017-07-13
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 2021-06-30
    • 2011-12-04
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    相关资源
    最近更新 更多