You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Sheets带保护工作表复制脚本:功能移除与提取需求

Google Apps Script 工作表复制功能拆分与修改

一、移除「跨表复制到首位」功能后的脚本

原脚本移除了跨电子表格复制、以及将新表置于标签栏首位的相关逻辑,仅保留当前电子表格内复制带保护工作表的功能,默认将新表放在标签栏末尾,也可自定义名称和位置。

修改后的代码

/**
* 复制工作表并保留保护设置
* 仅支持在当前电子表格内复制
* 如果指定的新表名已存在,将自动命名为「副本 + 原表名」格式
*
* 使用示例:
  const ss = SpreadsheetApp.getActive();
  const sheetToCopy = ss.getSheetByName('模板');
  let newSheet;

  // 复制模板表,命名为带日期的新表,放在标签栏最后
  const newSheetName = '数据 ' + Utilities.formatDate(new Date(), ss.getSpreadsheetTimeZone(), 'yyyy-MM-dd');
  newSheet = copySheetWithProtections_(sheetToCopy, newSheetName);

  // 复制多个表到当前电子表格末尾
  const sheetsToCopy = ['表1', '表2', '表3'];
  const newSheets = [];
  sheetsToCopy.forEach(sheetName => {
    const sheet = ss.getSheetByName(sheetName);
    newSheets.push(copySheetWithProtections_(sheet, sheetName));
  });
  console.log(`已复制 ${newSheets.length} 个工作表到当前文件。`);

* @param {Sheet} sheet 要复制的工作表对象
* @param {String} optNewSheetName 可选:新工作表名称,默认使用原表名
* @param {Number} optSheetIndex 可选:新表在标签栏的位置(从0开始),默认放在最后
* @return {Sheet} 复制后的新工作表对象
*/
function copySheetWithProtections_(sheet, optNewSheetName, optSheetIndex) {
  // 版本 1.2 修改版,移除跨表复制功能
  // 原作者:Hyde,修改适配需求

  const ss = sheet.getParent();
  const newSheetName = optNewSheetName || sheet.getName();
  const sheetIndex = optSheetIndex ?? ss.getNumSheets(); // 默认放在最后位置
  const me = Session.getEffectiveUser();
  if (!me.getEmail()) {
    throw new Error('无法获取当前有效用户身份,请检查权限设置。');
  }
  const newSheet = sheet.copyTo(ss);
  newSheet.activate();
  ss.moveActiveSheet(sheetIndex);
  try {
    newSheet.setName(newSheetName);
  } catch (error) {
    // 表名已存在,保留默认的「副本」命名
  }
  // 复制工作表级保护
  const sheetProt = sheet.getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
  if (sheetProt) {
    const newSheetProt = newSheet
      .protect()
      .setDescription(sheetProt.getDescription())
      .setWarningOnly(sheetProt.isWarningOnly());
    if (!sheetProt.isWarningOnly()) {
      newSheetProt
        .addEditor(me)
        .removeEditors(newSheetProt.getEditors().filter(user => user.getEmail() !== me))
        .addEditors(sheetProt.getEditors());
      try {
        newSheetProt.setDomainEdit(sheetProt.canDomainEdit());
      } catch (error) {
        // 非Google Workspace域名环境,忽略该设置
      }
    }
    const unprotectedRanges = sheetProt.getUnprotectedRanges()
      .map(range => newSheet.getRange(range.getA1Notation()));
    newSheetProt.setUnprotectedRanges(unprotectedRanges);
  } else {
    // 复制单元格区域级保护
    sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE)
      .forEach(rangeProt => {
        const rangeA1 = rangeProt.getRange().getA1Notation();
        const newRangeProt = newSheet.getRange(rangeA1)
          .protect()
          .setDescription(rangeProt.getDescription())
          .setWarningOnly(rangeProt.isWarningOnly());
        if (!rangeProt.isWarningOnly()) {
          newRangeProt
            .addEditor(me)
            .removeEditors(newRangeProt.getEditors().filter(user => user.getEmail() !== me))
            .addEditors(rangeProt.getEditors());
          try {
            newRangeProt.setDomainEdit(rangeProt.canDomainEdit());
          } catch (error) {
            // 非Google Workspace域名环境,忽略该设置
          }
        }
      });
  }
  return newSheet;
}

二、独立实现「跨表复制同名工作表到标签栏首位」的脚本

该脚本仅专注于将指定工作表复制到目标电子表格,使用原表名,并自动放在标签栏最左侧,同时完整保留原表的所有保护设置。

独立脚本代码

/**
* 将工作表复制到目标电子表格,使用原表名并置于标签栏首位,同时保留保护设置
* 如果目标表中已存在同名工作表,将自动命名为「副本 + 原表名」格式
*
* 使用示例:
  const ss = SpreadsheetApp.getActive();
  const sheetToCopy = ss.getSheetByName('模板');
  // 替换为目标电子表格的ID
  const targetSpreadsheetId = '123abc...cba321';
  const targetSs = SpreadsheetApp.openById(targetSpreadsheetId);
  const newSheet = copySheetToTargetFirst_(sheetToCopy, targetSs);
  console.log(`已将工作表 ${sheetToCopy.getName()} 复制到 ${targetSs.getName()} 的标签栏首位。`);

* @param {Sheet} sheet 要复制的源工作表对象
* @param {Spreadsheet} targetSs 目标电子表格对象
* @return {Sheet} 复制后的新工作表对象
*/
function copySheetToTargetFirst_(sheet, targetSs) {
  // 提取自Hyde原脚本,专注实现跨表复制到首位功能
  const me = Session.getEffectiveUser();
  if (!me.getEmail()) {
    throw new Error('无法获取当前有效用户身份,请检查权限设置。');
  }
  // 复制工作表到目标表并置于首位(索引0)
  const newSheet = sheet.copyTo(targetSs);
  newSheet.activate();
  targetSs.moveActiveSheet(0);
  // 使用原表名命名
  try {
    newSheet.setName(sheet.getName());
  } catch (error) {
    // 表名已存在,保留默认的「副本」命名
  }
  // 复制工作表级保护
  const sheetProt = sheet.getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
  if (sheetProt) {
    const newSheetProt = newSheet
      .protect()
      .setDescription(sheetProt.getDescription())
      .setWarningOnly(sheetProt.isWarningOnly());
    if (!sheetProt.isWarningOnly()) {
      newSheetProt
        .addEditor(me)
        .removeEditors(newSheetProt.getEditors().filter(user => user.getEmail() !== me))
        .addEditors(sheetProt.getEditors());
      try {
        newSheetProt.setDomainEdit(sheetProt.canDomainEdit());
      } catch (error) {
        // 非Google Workspace域名环境,忽略该设置
      }
    }
    const unprotectedRanges = sheetProt.getUnprotectedRanges()
      .map(range => newSheet.getRange(range.getA1Notation()));
    newSheetProt.setUnprotectedRanges(unprotectedRanges);
  } else {
    // 复制单元格区域级保护
    sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE)
      .forEach(rangeProt => {
        const rangeA1 = rangeProt.getRange().getA1Notation();
        const newRangeProt = newSheet.getRange(rangeA1)
          .protect()
          .setDescription(rangeProt.getDescription())
          .setWarningOnly(rangeProt.isWarningOnly());
        if (!rangeProt.isWarningOnly()) {
          newRangeProt
            .addEditor(me)
            .removeEditors(newRangeProt.getEditors().filter(user => user.getEmail() !== me))
            .addEditors(rangeProt.getEditors());
          try {
            newRangeProt.setDomainEdit(rangeProt.canDomainEdit());
          } catch (error) {
            // 非Google Workspace域名环境,忽略该设置
          }
        }
      });
  }
  return newSheet;
}

内容的提问来源于stack exchange,提问作者Badyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:40:24