【问题标题】:How to copy format and values, not formulas, when creating a spreadsheet backup in Google Apps Script?在 Google Apps 脚本中创建电子表格备份时,如何复制格式和值,而不是公式?
【发布时间】:2020-10-22 10:48:13
【问题描述】:

目标是创建包含多个工作表的电子表格的冻结备份。备份电子表格需要复制值和格式,而不是公式。

有些工作表有=IMPORTRANGE,如果先复制电子表格,然后将值复制到同一范围内,这将成为一个问题,再次摆脱公式,因为新电子表格需要访问导入的范围在函数的中间(导致 A1 中的#REF)。

这个问题显然被问了很多次,但似乎没有一个答案能解决这个问题。我看过这些问题(实际上还有更多问题):Link 1Link 2Link 3Link 4Link 5Link 6。我尝试从这些问题的答案或它们的组合中实施 sn-ps 无济于事。跟踪我测试的每一点 sn-p 变得很困难。

我尝试使用copyTo()forEach 函数中复制整个工作表,使用选项{contentsOnly:true}{formatOnly:true} 进行复制,但均未成功。 copyTo() 希望范围在同一个电子表格/工作表中,或者 getDataRange() 与备份范围不匹配...

这是我当前使用的脚本,它成功地创建了整个电子表格的副本,其中仅包含值。我不记得我是从哪个问题得到的。

function copyEntireSpreadsheet(){
  var ss,ssName,sheet,sheetName,data,destination
  ss = SpreadsheetApp.openById("id").getSheets();
  ssName = SpreadsheetApp.openById("id").getName();
  destination = SpreadsheetApp.create(ssName + " - " + new Date().toLocaleString());

  for (var i = 0; i < ss.length; i++){
    sheet = ss[i];
    sheetName = sheet.getSheetName();
    data = sheet.getSheetValues(1, 1, sheet.getLastRow(), sheet.getLastColumn());
    destination.insertSheet(sheetName);
    destination.getSheets()[i+1].getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).setValues(data);
  }

 destination.deleteSheet(destination.getSheetByName('Sheet1'));
}

源电子表格包含许多包含合并单元格、条件格式等的格式,非常适合复制。我也可以将某些工作表硬编码到脚本中,如果这对替代方法有任何影响的话。

简而言之:我正在寻找具有多张工作表的电子表格的冻结备份。需要复制值和格式,而不是公式。

我可能在所有这些问题的答案中遗漏了一些东西,所以我会继续尝试。同时,任何帮助/指导将不胜感激。提前致谢!

已解决:@Tanaike 下面的第二个示例脚本是复制引用其他电子表格的工作表的绝佳解决方法,因此需要在仅被值覆盖之前访问它们.非常感谢 @Tanaike 对此提供的广泛帮助——非常感谢。

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:
    • 您希望将电子表格中所有工作表的值和格式复制到新的电子表格中。
      • 在这种情况下,您只想复制没有公式的值。
      • The source spreadsheet has a lot of formatting with merged cells, conditional formatting, etc.
      • 源电子表格包含使用IMPORTRANGE 放置的值。
    • 您希望使用 Google Apps 脚本实现此目的。

    上述目标的示例脚本流程如下。

    流程:

    1. 将源电子表格中的所有工作表复制为临时工作表。
    2. 在复制的工作表中,单元格仅被值覆盖。这样,可以删除公式。
      • 如果复制源电子表格,使用IMPORTRANGE 检索的值将变为#REF。因为需要在新复制的电子表格上进行授权。为了避免这种情况,临时表被复制到源电子表格中。
    3. 复制源电子表格。
    4. 删除源电子表格中的临时工作表。
    5. 删除目标电子表格中的原始工作表。

    通过以上流程,未经IMPORTRANGE授权,只能复制值。

    示例脚本:

    function copyEntireSpreadsheet() {
      var id = "###"; // Please set the source Spreadsheet ID.
    
      var ss = SpreadsheetApp.openById(id);
      var srcSheets = ss.getSheets();
      var tempSheets = srcSheets.map(function(sheet, i) {
        var sheetName = sheet.getSheetName();
        var dstSheet = sheet.copyTo(ss).setName(sheetName + "_temp");
        var src = dstSheet.getDataRange();
        src.copyTo(src, {contentsOnly: true});
        return dstSheet;
      });
      var destination = ss.copy(ss.getName() + " - " + new Date().toLocaleString());
      tempSheets.forEach(function(sheet) {ss.deleteSheet(sheet)});
      var dstSheets = destination.getSheets();
      dstSheets.forEach(function(sheet) {
        var sheetName = sheet.getSheetName();
        if (sheetName.indexOf("_temp") == -1) {
          destination.deleteSheet(sheet);
        } else {
          sheet.setName(sheetName.slice(0, -5));
        }
      });
    }
    

    参考资料:

    【讨论】:

    • 非常感谢@Tanaike。您的示例脚本是解决临时工作表问题的巧妙方法!它几乎完美地工作,除了它无法获取在A1 中具有=IMPORTRANGE 的工作表的值。该源表将在A:X 列中有几千行。可能是脚本处理工作表的速度太快,IMPORTRANGE 无法将数据拉入创建的临时工作表,因此当临时工作表复制到新电子表格时,A1 中的唯一值是 #REF .
    • 也许我可以复制公式,冻结源工作表,将冻结的源工作表复制到新的电子表格中,清除源工作表,然后将公式重新写入源工作表?这将是一个很好的解决方法,除非有更简单的方法来暂停脚本以给公式工作时间?
    • @BearsBeetsBSG 感谢您的回复。在您的问题中,我了解到您只想将电子表格中所有工作表的值和格式复制到新的电子表格中。但是在你的回复中,你说Maybe I can copy the formula, freeze the source sheet, copy the frozen source sheet into the new spreadsheet, clear the source sheet, and re-write the formula into the source sheet?。所以我很困惑。你能解释一下你的目标的细节吗?如果我的回答对您的情况没有用,我必须道歉。
    • 对任何混淆表示歉意。除了具有=IMPORTRANGE 的工作表之外,您的示例脚本几乎可以完美运行。我猜想,当脚本循环遍历工作表时,在源电子表格中创建的临时工作表没有足够的时间在复制到新电子表格之前提取IMPORTRANGE 数据。你引用的我的评论部分是我大声思考来克服这个问题。总之:剩下的就是用IMPORTRANGE 复制工作表,因为现在,使用您的示例脚本,新复制的工作表有#REF。这有意义吗?
    • 再次感谢您的帮助。编辑看起来很棒。 :)
    猜你喜欢
    • 1970-01-01
    • 2020-12-31
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多