Google表格跨表复制脚本突发length属性未定义报错排查
问题背景
以下Google Apps Script脚本已稳定运行3个月未出现异常,核心逻辑为遍历电子表格,逐行判断是否满足预设归档条件:符合条件的行会被复制到归档工作表,同时删除源工作表中的对应行。近期脚本执行时突然抛出从未出现过的错误,无法定位故障原因。
原脚本代码
function copyIfConditions() { const ss = SpreadsheetApp.getActive(); const ssh = ss.getSheetByName("NUEVOS INGRESOS Y EXPEDIENTES EN TRAMITE"); const ash = ss.getSheetByName("CASOS ARCHIVADOS/FINALIZADOS"); const spA = ["Finalizado_Archivado", "Remitida_a_otro_juzgado_conexidad", "Remitida_UACF", "Remitida_a_otro_juzgado_por_recusacion", "Remitida_a_otro_Juzgado_por_cuestion_de_turno", "Remitida_a_otros_fueros"]; if (ssh.getLastRow() == 1) { SpreadsheetApp.getActive().toast('No data!', 'End of script 🗃️'); return; } const vs = ssh.getRange(2, 1, ssh.getLastRow() - 1, ssh.getLastColumn()).getValues(); const archiveData = []; let d = 0;//delete counter vs.forEach((r, i) => { if (~spA.indexOf(r[35])) { archiveData.push(r); ssh.deleteRow(i + 2 - d++); } }); ash.getRange(ash.getLastRow() + 1, 1, archiveData.length, archiveData[0].length).setValues(archiveData); }
报错信息
TypeError: Cannot read property 'length' of undefined @ CopyIfArchived.gs:19
故障根因
报错指向脚本第19行写入归档表的逻辑:ash.getRange(ash.getLastRow() + 1, 1, archiveData.length, archiveData[0].length).setValues(archiveData);
触发逻辑非常明确:当本次脚本执行时,源表中没有任何一行满足归档条件,archiveData就是空数组,此时访问archiveData[0]会得到undefined,读取undefined的length属性就会抛出该类型错误。
此前3个月运行未触发报错,是因为之前每次执行都至少存在1条待归档数据,刚好没覆盖到这个未做边界判断的逻辑分支。
修复方法
在写入归档表的逻辑前增加空数组判断,仅当存在待归档数据时才执行写入操作即可,修复后完整代码如下:
function copyIfConditions() { const ss = SpreadsheetApp.getActive(); const ssh = ss.getSheetByName("NUEVOS INGRESOS Y EXPEDIENTES EN TRAMITE"); const ash = ss.getSheetByName("CASOS ARCHIVADOS/FINALIZADOS"); const spA = ["Finalizado_Archivado", "Remitida_a_otro_juzgado_conexidad", "Remitida_UACF", "Remitida_a_otro_juzgado_por_recusacion", "Remitida_a_otro_Juzgado_por_cuestion_de_turno", "Remitida_a_otros_fueros"]; if (ssh.getLastRow() == 1) { SpreadsheetApp.getActive().toast('No data!', 'End of script 🗃️'); return; } const vs = ssh.getRange(2, 1, ssh.getLastRow() - 1, ssh.getLastColumn()).getValues(); const archiveData = []; let d = 0;//delete counter vs.forEach((r, i) => { if (~spA.indexOf(r[35])) { archiveData.push(r); ssh.deleteRow(i + 2 - d++); } }); // 新增空数据判断,避免访问空数组首元素报错 if (archiveData.length > 0) { ash.getRange(ash.getLastRow() + 1, 1, archiveData.length, archiveData[0].length).setValues(archiveData); } SpreadsheetApp.getActive().toast(`Archived ${archiveData.length} records`, 'End of script 🗃️'); }
补充优化建议:当前正序遍历+计数器计算删除行号的逻辑存在隐性风险,若后续增加其他行操作逻辑很容易出现行号偏移导致删错行,可改为倒序遍历源表数据,从最后一行往上判断、删除,无需额外计数器计算偏移,逻辑更稳定。
内容的提问来源于stack exchange,提问作者IFritzler
相关产品推荐
相关产品推荐

