仅在必要时拆分Google Form单行响应至独立工作表多行的脚本问题
Google Apps Script 问题:仅当宠物信息非空时生成对应行
背景
某非营利组织使用Google Form作为客户登记表,客户可填写最多4只宠物的信息,每只宠物需单独处理,因此需将每只宠物信息拆分为独立行存入对应工作表。
现有问题
编写的copyTo函数尝试仅当宠物信息非空时,在"Responses"表新增合并主人与对应宠物信息的行,但当前每次都会生成4行——即使部分宠物信息为空,后两行仅含主人信息,宠物信息为空。
原代码
function copyTo(destinationSSId) { // Open source SS at tab named "Data" let dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data"); // Open destination SS at tab named "Responses" let responseSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Responses"); // Get source values let templateValues = dataSheet.getRange(dataSheet.getLastRow(), 1, 1, 14).getValues(); let c1Values = dataSheet.getRange(dataSheet.getLastRow(), 15, 1, 7).getValues(); let c2Values = dataSheet.getRange(dataSheet.getLastRow(), 22, 1, 7).getValues(); let c3Values = dataSheet.getRange(dataSheet.getLastRow(), 29, 1, 7).getValues(); let c4Values = dataSheet.getRange(dataSheet.getLastRow(), 36, 1, 7).getValues(); // Set first row responseSheet.getRange(responseSheet.getLastRow() + 1, 2, 1, 14).setValues(templateValues); responseSheet.getRange(responseSheet.getLastRow(), 16, 1, 7).setValues(c1Values) // Set second row if applicable if (c2Values !==""){ responseSheet.getRange(responseSheet.getLastRow() + 1, 2, 1, 14).setValues(templateValues) responseSheet.getRange(responseSheet.getLastRow(), 16, 1, 7).setValues(c2Values) } // Set third row if applicable if (c3Values !==""){ responseSheet.getRange(responseSheet.getLastRow() + 1, 2, 1, 14).setValues(templateValues) responseSheet.getRange(responseSheet.getLastRow(), 16, 1, 7).setValues(c3Values) } // Set fourth row if applicable if (c4Values !==""){ responseSheet.getRange(responseSheet.getLastRow() + 1, 2, 1, 14).setValues(templateValues) responseSheet.getRange(responseSheet.getLastRow(), 16, 1, 7).setValues(c4Values) } }
错误原因
- 数组与字符串的错误比较:
getValues()返回的是二维数组(比如c2Values是[[null, null, ...]]),直接和空字符串""比较时,由于类型不同,判断结果永远为true,导致空宠物信息的分支也会执行新增行操作。 - 第一行未做判断:原代码直接写入第一行宠物信息,即使
c1Values为空也会生成一行仅含主人信息的记录。
修改方案
1. 新增空值判断辅助函数
编写函数检查宠物信息数组是否包含有效内容(即不全为空/ null):
function hasPetData(petValues) { // 展开二维数组为一维,检查是否有非空/非null的元素 return petValues[0].some(cell => cell !== "" && cell !== null); }
2. 重构代码逻辑
将所有宠物信息存入数组循环处理,避免重复代码,统一判断每一组信息是否有效:
修改后的完整代码:
function copyTo(destinationSSId) { const dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data"); const responseSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Responses"); const lastRow = dataSheet.getLastRow(); // 读取主人信息(转为一维数组,方便后续合并) const templateValues = dataSheet.getRange(lastRow, 1, 1, 14).getValues()[0]; // 读取4组宠物信息,转为一维数组的集合 const petGroups = [ dataSheet.getRange(lastRow, 15, 1, 7).getValues()[0], dataSheet.getRange(lastRow, 22, 1, 7).getValues()[0], dataSheet.getRange(lastRow, 29, 1, 7).getValues()[0], dataSheet.getRange(lastRow, 36, 1, 7).getValues()[0] ]; // 遍历每组宠物信息,仅当有有效数据时写入 petGroups.forEach(petData => { if (hasPetData([petData])) { // 构建完整行数据:第1列留空,填充主人信息到第2-15列,宠物信息到第16-22列 const fullRow = new Array(1).fill(""); fullRow.splice(1, 14, ...templateValues); fullRow.splice(15, 7, ...petData); // 写入一行数据 responseSheet.appendRow(fullRow); } }); } function hasPetData(petValues) { return petValues[0].some(cell => cell !== "" && cell !== null); }
关键改进点
- 使用
appendRow()简化行写入操作,无需手动计算行号,避免行号计算错误 - 将
getValues()返回的二维数组转为一维数组,更方便进行数据合并与空值判断 - 通过
some()方法高效检查宠物信息组中是否存在非空/非null的有效内容 - 用循环遍历4组宠物信息,大幅减少重复代码,提升可维护性
- 统一对所有宠物信息组做非空判断,包括第一组,彻底解决空行问题
内容的提问来源于stack exchange,提问作者Erin
相关产品推荐
相关产品推荐

