Google Sheet脚本报错:如何将一行数据复制至多个工作表?
问题背景
我正在开发Google Sheet脚本,用于将「Order Sheet」中的一行数据移至同一电子表格内的两个不同工作表,追踪同时为两个办公室订购的库存收货状态。电子表格包含12列:A列为位置下拉选择器(可选值:Location 1、Location 2、Both),K列为收货状态勾选框。
当前脚本在A列值为Location 1或Location 2且K列勾选收货时,可正常将数据移至对应「Location 1 Received」或「Location 2 Received」工作表并删除原行,但当A列值为Both时,复制数据到两个目标工作表出现报错:
Exception: The coordinates of the target range are outside the dimensions of the sheet. at moveToReceived(moveToReceived:26:65)
现有代码如下:
function moveToReceived(e) { const src = e.source.getActiveSheet(); const r = e.range; const valueToWatch1 = "Location 1"; const valueToWatch2 = "Location 2"; const valueToWatch3 = "Both"; const dest1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Location 1 Received"); const dest2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Location 2 Received"); if (src.getName()!= "Order Sheet" || r.columnStart!= 11 || r.rowStart == 1) return; if (r.offset(0, -10).getValue() == valueToWatch1) { src.getRange(r.rowStart,1,1,12).moveTo(dest1.getRange(dest1.getLastRow()+1,1,1,12)); src.deleteRow(r.rowStart); } else if (r.offset(0, -10).getValue() == valueToWatch2) { src.getRange(r.rowStart,1,1,12).moveTo(dest2.getRange(dest2.getLastRow()+1,1,1,12)); src.deleteRow(r.rowStart); } else if (r.offset(0, -10).getValue() == valueToWatch3) { src.getRange(r.rowStart,1,1,12).copyTo(dest1.getRange(dest1.getLastRow()+1,1,1,12)) src.getRange(r.rowStart,1,1,12).copyTo(dest2.getRange(dest2.getLastRow()+1,1,1,12)) src.deleteRow(r.rowStart); } };
错误原因
报错的核心原因是:当目标工作表为空时,getLastRow()返回0,此时dest.getRange(0+1,1,1,12)会尝试选中第1行的12列,但如果目标工作表的列数不足12列,就会触发「坐标超出表格维度」的异常。另外直接使用copyTo时,若目标范围维度与源范围不匹配,也会触发同类错误。
修复方案
改用appendRow方法替代copyTo,该方法会自动将数据追加到工作表的最后一行,且自动扩展表格列数以匹配数据长度,彻底规避维度不匹配的问题。同时提前将源行数据转为一维数组,提升执行效率。
修复后的代码:
function moveToReceived(e) { const src = e.source.getActiveSheet(); const r = e.range; const valueLocation1 = "Location 1"; const valueLocation2 = "Location 2"; const valueBoth = "Both"; const dest1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Location 1 Received"); const dest2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Location 2 Received"); // 仅处理Order Sheet的K列(第11列)且非表头行的操作 if (src.getName()!== "Order Sheet" || r.columnStart!== 11 || r.rowStart === 1) return; const locationValue = r.offset(0, -10).getValue(); const sourceRowData = src.getRange(r.rowStart, 1, 1, 12).getValues()[0]; // 将行数据转为一维数组 if (locationValue === valueLocation1) { src.getRange(r.rowStart, 1, 1, 12).moveTo(dest1.getRange(dest1.getLastRow() + 1, 1, 1, 12)); src.deleteRow(r.rowStart); } else if (locationValue === valueLocation2) { src.getRange(r.rowStart, 1, 1, 12).moveTo(dest2.getRange(dest2.getLastRow() + 1, 1, 1, 12)); src.deleteRow(r.rowStart); } else if (locationValue === valueBoth) { // 使用appendRow自动处理空表、列数不足等场景 dest1.appendRow(sourceRowData); dest2.appendRow(sourceRowData); src.deleteRow(r.rowStart); } };
额外优化说明
- 变量名改为语义化命名,提升代码可读性
- 提前获取位置值和源行数据,避免重复调用API,提升执行效率
- 使用严格相等运算符
===替代==,避免隐式类型转换的潜在问题
内容的提问来源于stack exchange,提问作者Alexander Van-Nugent

