Google Apps Script:利用表单响应值删除重复行的代码问题排查
问题修复:表单提交后删除表格重复姓名行(基于现有代码逻辑)
需求:表单提交姓名后,对比表格第4列的已有姓名,删除存在重复姓名的行,避免数据重复。以下是原代码及修复方案:
原代码
var formResponses = form.getResponses(); for (var i = 0; i < formResponses.length; i++) { var formResponse = formResponses[i]; var itemResponses = formResponse.getItemResponses(); for (var j = 0; j < itemResponses.length; j++) { var itemResponse = itemResponses[1]; var finalitemResponse = itemResponse.getResponse(); nameofclient_runningbalance.setValue(finalitemResponse); Logger.log(finalitemResponse); var values = hospitalSheet.getRange(2, 4, hospitalSheet.getLastRow(), 1).getValues(); Logger.log(values); var { v, cells } = values.reduce((o, r, i) => { if (r[4] == finalitemResponse) { hospitalSheet.getRangeList(cells).deleteRows(cells.length, cells[0].length); o.cells.push(`R${i + 2}`); } return o; }, { v: [], cells: [] }); if (v.length == 0) return; } }
代码问题分析
- 无意义的内层循环:
j循环遍历所有表单项,但始终只取itemResponses[1],循环完全多余,还会重复执行核心逻辑。 - 范围取值错误:
getRange(2, 4, hospitalSheet.getLastRow(), 1)会从第2行开始取getLastRow()行,超出表格实际行数,应该取getLastRow() - 1行(因为从第2行开始,总行数是最后一行减1)。 - 数组索引错误:
values是单列数组,每个元素r是长度为1的数组,判断重复时应该用r[0]而非r[4]。 - 提前执行删除操作:在
reduce循环里直接调用deleteRows,此时还没收集完所有重复行,而且删除行后后续行号会偏移,导致漏删或删错。 - 无效变量与终止逻辑:
v变量未使用,if (v.length == 0) return;会直接终止整个函数,导致后续表单响应无法处理。 - 删除方法调用错误:
getRangeList(cells).deleteRows用法错误,且删除行时未考虑行号顺序,应该从大到小删除,避免行号偏移。
修复后的代码
var formResponses = form.getResponses(); for (var i = 0; i < formResponses.length; i++) { var formResponse = formResponses[i]; var itemResponses = formResponse.getItemResponses(); // 直接取第2个表单项(索引1),去掉无意义的j循环 var itemResponse = itemResponses[1]; var finalitemResponse = itemResponse.getResponse(); nameofclient_runningbalance.setValue(finalitemResponse); Logger.log("当前提交姓名:" + finalitemResponse); // 正确获取第4列(D列)从第2行开始的数据范围 var lastRow = hospitalSheet.getLastRow(); if (lastRow < 2) { Logger.log("表格无数据,无需删除"); continue; } var values = hospitalSheet.getRange(2, 4, lastRow - 1, 1).getValues(); Logger.log("现有姓名列表:" + values); // 收集所有重复姓名的行号(从大到小排序,避免删除后行号偏移) var duplicateRows = values.reduce((rows, r, idx) => { if (r[0] == finalitemResponse) { // 行号是索引+2(因为从第2行开始) rows.push(idx + 2); } return rows; }, []).sort((a, b) => b - a); Logger.log("要删除的行号:" + duplicateRows); // 批量删除重复行 duplicateRows.forEach(row => { hospitalSheet.deleteRows(row, 1); }); }
关键修改说明
- 移除了无意义的
j循环,直接获取目标表单项。 - 修正了数据范围的取值逻辑,确保只取表格中已有的数据行。
- 修复了数组索引错误,用
r[0]获取单列数组的内容。 - 先收集所有重复行号,按从大到小排序后再批量删除,避免删除行导致后续行号偏移。
- 移除了无效的
v变量和错误的终止逻辑,确保所有表单响应都能被处理。 - 添加了表格无数据时的判断,避免报错。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

