在处理Google表格时,我们经常遇到这样的需求:把当前选中的几行数据原样搬到另一个工作表或者同一表的其他位置。如果靠手工剪切粘贴,既费时又容易选错区域。Google Apps Script提供了SpreadsheetApp服务,能够用代码精确控制选区与写入过程,确保数据和格式都不丢失。

获取用户选定的行范围
要复制选定行,第一步是拿到用户当前的高亮区域。在Apps Script里,通过SpreadsheetApp.getActiveSpreadsheet()拿到活动表格,再用getActiveRange()获取选区。这个方法返回的是一个Range对象,里面包含了起始行、结束行、列数等信息。我们需要先判断选区是不是包含了整行,或者至少是跨行的区域,否则只复制单个单元格没有意义。
通常可以用getRow()和getLastRow()算出选了几行,用getColumn()与getLastColumn()确认列覆盖情况。如果希望严格限定为整行,可以比对工作表的最大列数。下面这段代码演示了如何安全地读取选区并打印出行号区间,方便后续扩展为复制逻辑。
function logSelectedRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveRange();
var startRow = range.getRow();
var endRow = range.getLastRow();
var startCol = range.getColumn();
var endCol = range.getLastColumn();
var lastCol = sheet.getLastColumn();
// 检查是否近似整行选择
if (startCol === 1 && endCol === lastCol) {
Logger.log("选中了整行,从" + startRow + "到" + endRow);
} else {
Logger.log("仅选中部分区域,从" + startRow + "行" + startCol + "列到" + endRow + "行" + endCol + "列");
}
}
上面的脚本没有真正复制数据,只是把选区信息输出到日志,这有利于我们在写复杂脚本前先验证交互逻辑。实际项目中,你可以把这段判断封装成一个函数,在菜单点击时调用,避免用户选了错误区域导致脚本报错。
使用copyTo实现格式与公式的精确搬迁
Google Apps Script的Range对象自带copyTo方法,它可以把源区域的值、公式、格式一次性写到目标位置。和getValue、setValue手动搬运相比,copyTo不会破坏原有公式引用,也不会丢掉单元格背景色或数据验证规则。我们只需指定目标Range,就能完成整行复制。
假设用户选中了第二行到第五行,想复制到名为“备份”的工作表开头,可以这样写:先拿到源sheet的对应行Range,再在目标sheet里用getRange算出接收位置,调用copyTo。注意目标范围的行数要和源一致,列宽最好也匹配。以下示例展示了跨表复制的完整过程。
function copySelectedRowsToBackup() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getActiveSheet();
var range = sourceSheet.getActiveRange();
var startRow = range.getRow();
var numRows = range.getLastRow() - startRow + 1;
var lastCol = sourceSheet.getLastColumn();
// 源区域:选中的整块
var sourceRange = sourceSheet.getRange(startRow, 1, numRows, lastCol);
var targetSheet = ss.getSheetByName("备份");
if (!targetSheet) {
targetSheet = ss.insertSheet("备份");
}
var targetRange = targetSheet.getRange(1, 1, numRows, lastCol);
sourceRange.copyTo(targetRange);
SpreadsheetApp.getUi().alert("已复制" + numRows + "行到备份表");
}
这个脚本在目标表首行写入数据。如果备份表已有内容,就会被覆盖。若要追加而不是覆盖,可以先取targetSheet.getLastRow()再加一作为起始行。copyTo还有可选参数,比如{contentsOnly:true}只复制值不复制格式,按需选用即可。
避免数据覆盖与常见错误处理
精确复制行数据的最大风险是无意间盖掉目标表里的重要信息。在企业报表中,这种错误很难察觉。因此在粘贴前,脚本应当主动检查目标区域是否为空,或者采用追加模式。另一个常见问题是用户没选区域就运行脚本,这时getActiveRange可能指向A1,复制空行会造成困惑。
我们可以在方法开头加保护:如果numRows小于1或者源区域完全空白,就提示用户重新选择。同时,当目标表不存在时自动创建虽然方便,但在严格权限环境下可能失败,所以最好用try-catch包裹建表逻辑。下面代码给出了带校验和异常捕获的稳健版本。
function safeCopyRows() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var src = ss.getActiveSheet();
var sel = src.getActiveRange();
var rows = sel.getLastRow() - sel.getRow() + 1;
if (rows < 1) {
SpreadsheetApp.getUi().alert("请先选中至少一行再执行");
return;
}
var cols = src.getLastColumn();
var from = src.getRange(sel.getRow(), 1, rows, cols);
var dest = ss.getSheetByName("归档");
if (!dest) {
dest = ss.insertSheet("归档");
}
var nextRow = dest.getLastRow() + 1;
var to = dest.getRange(nextRow, 1, rows, cols);
from.copyTo(to);
SpreadsheetApp.getUi().alert("安全追加" + rows + "行到归档表");
} catch (e) {
SpreadsheetApp.getUi().alert("出错:" + e.message);
}
}
通过上述写法,我们既保证了复制的准确性,也降低了误操作概率。结合自定义菜单,普通同事点一下就能把选定行搬走去统计,不必理解底层API。长期看,这类小脚本能省下大量重复劳动,也让表格维护更规范。
Google_Apps_ScriptSpreadsheetApprange_copyTo修改时间:2026-08-15 11:27:26