Google 表格 - 替换 sheet 而不破坏对 sheet 的引用

Google Sheets - Replace sheet without breaking references to that sheet

我们正在构建一个 google sheets 数据库,其中每个用户都有自己的传播sheet,可以使用应用程序脚本访问中央 sheet 信息。

这意味着有 50 名员工,我们有 50 个价差sheet要维护。我正在尝试找到一种方法来将更新推送到所有 50 个 spreadsheets 而不必手动更新每个。我在一个库中拥有每个用户 sheet 引用的所有应用程序脚本代码,因此我已经弄清楚了编码维护。但是事实证明,要让每个用户的实际传播sheet 与最新功能保持同步是很困难的。

我打算这样做的一种方法是让 "Template" 用户 sheet 更新 changes/new 功能。然后,当每个用户打开他们的 spreadsheet 时,它会将其所有 sheet 交叉引用到模板 sheet,并检查是否需要将其 sheet 替换为最新的sheet 基于在模板中更新的时间 sheet。例如,当模板中的sheet"Project Report"比用户spreadsheet中的"Project Report"sheet更新时,用户SS删除当前的"Project Report" 并通过 copyTo() 方法将模板 "Project Report" sheet 复制到它自己的模板。

我所有这些都与应用程序脚本一起使用,但现在的问题是,当用户的本地 sheet 被删除并替换为新的更新集时,所有对 sheet 的公式引用在其他 sheets 中断并用 #REF 替换引用。我曾计划通过仅使用命名范围来克服这个问题,但是当 sheet 被替换到应用程序脚本无法再找到命名范围的地步时,甚至命名范围也会中断,因为它正在寻找命名范围在导入新版本的 sheet 时自动重命名(也就是模板 SS 中的 "CustomNamedRange" 在用户 SS 中重命名为“'SheetName'!CustomNamedRange”)。

目前我知道解决这个问题的唯一方法是创建一个集中式 "Range Index" 传播sheet,其中包含所有命名范围及其目的地 sheet 和范围。我将不得不创建一个自定义函数来过滤范围索引并根据给定的名称找到它需要的地址。例如,我不会在 sheet 公式中调用 "CustomNamedRange",而是调用自定义函数:getNamedRange("CustomNamedRange"),应用程序脚本会 return 在范围内找到的范围指数。当 sheet 被新版本替换时,没有引用会中断,因为所有引用都通过应用程序脚本过滤器函数。

唯一的问题是我可以预见这种方法(通过自定义函数调用脚本中需要的每个范围)会减慢我的传播速度sheet很多,因为每次调用范围时,它必须通过范围索引进行搜索才能找到它 return 它。

有没有人对如何完成我正在寻找的东西有任何其他想法?就像保持 50 多个单独的 spreadsheets 更新新功能而无需手动进行并且不会破坏所有参考文献一样?

抱歉这么长post,但我很感激任何想法!

我遇到了类似的问题,可以通过使用 SheetAPI 替换文本来解决。我有一个名为 Sheet1_Template 的模板,它是隐藏的。我删除 Sheet1,复制 Sheet1_Template,显示它,然后将公式中出现的所有 "Sheet1" 替换为 "Sheet1"。 Sheet API 必须在资源和 Google API 控制台中启用。

function copyTemplate() {
  try {
    var spread = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = spread.getSheetByName("Sheet1");
    if( sheet !== null ) spread.deleteSheet(sheet);
    sheet = spread.getSheetByName("Sheet1_Template");
    sheet = sheet.copyTo(spread);
    sheet.setName("Sheet1");
    sheet.showSheet();
    sheet.activate();
    spread.moveActiveSheet(0);
    var requests = {"requests":[{"findReplace":{"allSheets":true,"find":"Sheet1","replacement":"Sheet1","includeFormulas":true}}]};
    Sheets.Spreadsheets.batchUpdate(requests, spread.getId());
  }
  catch(err) {
    Logger.log("error in copyTemplate: "+err);
  }
}

我还没有能够测试它的实现,但我相信上面的答案就是我最初想要的。

我还没有花时间弄乱 API,所以与此同时我找到了另一个解决方案:

Google Sheets 最近在其功能集中添加了宏。这样做的好处是您可以在 sheet 中记录您的操作后查看和编辑宏代码。现在,我计划在更新模板 sheet 时录制一个宏,然后将该宏的脚本复制到我的库中的自定义函数中,每次用户打开它们时都会 运行 sheet。当他们打开他们的 SS 时,应用程序脚本将检查库的宏函数的日期是否比上次打开 sheet 的日期晚。如果它确实有新日期,那么它将 运行 宏脚本,并且该用户的 SS 应该更新为与模板相同的状态。

此外,如果您发现无法运行来自@TheWizEd

的查询

这可能是由于 "Sheets API" 未在高级 Google 服务中启用。请启用>

在脚本编辑器中,select资源>高级Google服务在出现的对话框中,单击Google工作表API的on/off开关v4.请开机。单击“确定”按钮。

非常感谢 让我开始(请也为 post 投票)。

这就是我需要的:

function replaceFormulasInSheet(sheet, searchFor, replaceWith) {
  // 
  // First you need to do this to enable the feature: https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services
  // https://developers.google.com/sheets/api/quickstart/apps-script
  // https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#findreplacerequest
  // https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate
  const spread = SpreadsheetApp.getActiveSpreadsheet();
  const requests = {
    "requests": [
      {
        "findReplace": {
          // "allSheets": true, Omitting this property and instead setting the sheetId property is the only way to effectively set allSheets as false.
          "sheetId": sheet.getSheetId(),
          "find": searchFor,
          "replacement": replaceWith,
          "includeFormulas": true
        }
      }
    ]
  }; 
  return Sheets.Spreadsheets.batchUpdate(requests, spread.getId()); 
}

另请注意,它不适用于名称中包含连字符的工作表。如果您需要在他们的名字中使用连字符,请事先删除连字符并在之后重新添加它们。