Google Apps Script报错:无法获取表单数据,请求协助排查
问题分析与修复方案
核心错误原因
你遇到的Exception: Failed to retrieve form data. Please wait and try again.错误,根源在于全局变量的初始化时机错误:
- 你将表单响应、表格实例等变量定义在函数
numprotocolo()外部,这些全局变量会在脚本启动时(而非函数执行时)被初始化。当表单提交触发脚本时,新的响应可能还未完全同步到Google Form的响应列表中,导致formResponses获取不到最新提交的数据,进而respostas[0]可能为undefined,调用getResponse()时触发报错。 - 另外,
Math.max.apply(null, guia.getRange("L2:L").getValues())存在逻辑缺陷:getValues()返回的是二维数组,Math.max无法直接处理,若L列存在空值,会返回NaN,导致协议编号生成失败。
修复后的完整代码
function numprotocolo() { // 1. 在函数执行时才获取最新表单响应 var formResponses = FormApp.getActiveForm().getResponses(); if (formResponses.length === 0) { throw new Error("无表单响应数据"); } var formResponse = formResponses[formResponses.length - 1]; var respostas = formResponse.getItemResponses(); if (respostas.length === 0 || !respostas[0]) { throw new Error("无法获取提交者邮箱数据"); } var emailSolicitante = respostas[0]; // 2. 表格操作移至内部,避免全局实例过期 var planilha = SpreadsheetApp.openById('151F6ry81nER7UjPhlnQor2XFI4beV9avwwSD-nTjoIY'); var sheet = planilha.getActiveSheet(); var guia = planilha.getSheetByName("sheet0"); if (!guia) { throw new Error("未找到名为sheet0的工作表"); } // 3. 修复协议编号生成逻辑:处理二维数组与空值 var ultimaLinha = guia.getLastRow(); var idColunaValores = guia.getRange("L2:L" + ultimaLinha).getValues() .flat() // 将二维数组转为一维 .filter(val => !isNaN(val) && val !== ""); // 过滤空值与非数字 var maiorID = idColunaValores.length > 0 ? Math.max(...idColunaValores) : 0; var id = maiorID + 1; guia.getRange(ultimaLinha, 12).setValue(id); // 4. 优化邮件内容获取:一次性读取行数据,减少API调用 var row = sheet.getLastRow(); var rowData = sheet.getRange(row, 1, 1, 12).getValues()[0]; // 读取整行数据 var protocoloNum = rowData[11]; // L列是第12列,索引为11 var assunto = rowData[5]; // F列索引5 var cpfCnpj = rowData[3]; // D列索引3 // 5. 邮件发送逻辑 var logo = DriveApp.getFileById('1T2VLuChpMN23gC3uCDses3Evq-DIWfbC'); var inlineImages = {}; inlineImages[logo.getId()] = logo.getBlob(); var body = `<b>*** E-mail automático *** </b><br />Seu requerimento foi protocolado (<b>Protocol Nº ${protocoloNum}</b>)<br />ASSUNTO: ${assunto}.<br />CPF/CNPJ n° ${cpfCnpj}<br /><br /><b>Prazo de resposta - 72 horas</b><br /><br />`; // 6. 检查邮箱有效性后发送 var destinatario = emailSolicitante.getResponse(); if (!destinatario || destinatario.trim() === "") { throw new Error("提交者邮箱为空"); } MailApp.sendEmail({ to: destinatario, subject: "Protocol", body: "", htmlBody: body, inlineImages: inlineImages }); }
关键修改点说明
- 全局变量移至函数内部:确保每次函数执行时都获取最新的表单响应和表格实例,避免因数据未同步导致的读取失败。
- 增加数据校验:在获取响应、工作表、邮箱等关键数据前增加判断,提前抛出明确错误,便于排查问题。
- 修复协议编号生成:将二维数组扁平化,过滤无效值,避免
Math.max返回NaN,同时处理无历史数据的初始情况(默认从0开始递增)。 - 优化表格操作:一次性读取整行数据,减少
getRange的调用次数,提升脚本执行效率,降低Google服务的调用限制风险。 - 移除不必要的
Utilities.sleep(3000):通过逻辑优化替代强制等待,避免无意义的延迟。
额外建议
- 确保表单的第一个问题是邮箱输入项,且设置为必填,避免
respostas[0]不是邮箱数据。 - 建议将脚本的触发方式设置为表单提交触发(而非手动执行),并在Google Apps Script编辑器的「编辑」→「当前项目的触发器」中配置,确保触发时机正确。
内容的提问来源于stack exchange,提问作者Gabriel Passos
相关产品推荐
相关产品推荐

