在 Google Apps 脚本中将整个 sheet 替换为另一个

Replace entire sheet with another in Google Apps Scripts

我想做的是在价差sheet 中的特定sheet 的仓库信息,并在每天结束时将其复制到第二个价差sheet。第二个传播sheet 将 运行 复杂的枢轴和报告复制的信息,这些信息不需要全天 运行。

我可以设置一个 time-driven trigger,它将在一个小时内每天 运行 作业。

我正在编写以下使用 SpreadsheetApp.getActiveSpreadsheet to get the current Spreadsheet. Then gets the individual sheet to backup with spreadsheet.getSheetByName. And then uses the sheet.copyTo method to add the current sheet to a new spreadsheet. I'm getting the new spreadsheet by looking up the id with SpreadsheetApp.openById 的脚本:

function startBackupJob() {

  var currentSpreadSheet = SpreadsheetApp.getActiveSpreadsheet()
  var masterSheet = currentSpreadSheet.getSheetByName("Sheet1")

  var backupSpreadSheetId = "#######################################";
  var backupSpreadSheet = SpreadsheetApp.openById(backupSpreadSheetId);

  // var backupSheet = backupSpreadSheet.getSheetByName("Sheet1");
  // backupSpreadSheet.deleteSheet(backupSheet);

  masterSheet.copyTo(backupSpreadSheet).setName("Sheet1");

}

我遇到的问题是 copyTo 将创建一个新作品sheet 而不是覆盖现有的传播sheet。移动到新工作簿的目的是 运行 数据透视表而不是重新连接它们以指向新的 sheet.

我可以删除以前的 sheet 来为新的腾出空间,但这也会破坏数据透视表上的引用,所以没有太大帮助。

有没有简单的方法可以将一部作品sheet的全部内容转移到另一部作品?


这类似于(但不同于)以下问题:


更新

我可以像这样调用 getRange on each sheet and then using getValues and setValues 来做到这一点:

var currentValues = masterSheet.getRange(1, 1, 50, 50).getValues()
backupSheet.getRange(1, 1, 50, 50).setValues(currentValues)

但我担心主 sheet 的可用范围与备份 sheet 不同的边缘情况。我也不想在范围内进行硬编码,但要让它包含整个 sheet。如果我调用 .getRange("A:E"),那么两个工作 sheet 必须具有完全相同的行数,这不太可能。

您的更新已经完成了大约 90%。诀窍是在将数据复制到其中之前明确检查目标 sheet 的大小。例如,如果我做了这样的事情:

var cromulentDocument = SpreadsheetApp.getActiveSpreadsheet();
var masterSheet = cromulentDocument.getSheetByName('master');
var logSheet = cromulentDocument.getSheetByName('log');
var hugeData = masterSheet.getDataRange().getValues();
var rowsInHugeData = hugeData.length;
var colsInHugeData = hugeData[0].length;

/* cross fingers */
logSheet.getRange(1, 1, rowsInHugeData, colsInHugeData).setValues(hugeData);

...那么我的成功将完全取决于 logSheet 是否至少与 masterSheet 一样大。这很明显,但不太明显的是,如果 logSheet 更大 那么边缘周围会留下一些旧垃圾。不好。

我们试试别的吧。和以前一样,我们将获取主数据,但我们也会调整大小 logSheet。如果我们不关心 logSheet 太大,我们可能只 clear() 里面的数据,但让我们保持整洁。

var cromulentDocument = SpreadsheetApp.getActiveSpreadsheet();
var masterSheet = cromulentDocument.getSheetByName('master');
var logSheet = cromulentDocument.getSheetByName('log');
var hugeData = masterSheet.getDataRange().getValues();
var rowsInHugeData = hugeData.length;
var colsInHugeData = hugeData[0].length;

/* no finger crossing necessary */
var rowsInLogSheet = logSheet.getMaxRows();
var colsInLogSheet = logSheet.getMaxColumns();

/* adjust logSheet length, but only if we need to... */
if (rowsInLogSheet < rowsInHugeData) {
  logSheet.insertRowsAfter(rowsInLogSheet, rowsInHugeData - rowsInLogSheet);
} else if (rowsInLogSheet > rowsInHugeData) {
  logSheet.deleteRows(rowsInHugeData, rowsInLogSheet - rowsInHugeData);
}

/* likewise, adjust width */
if (colsInLogSheet < colsInHugeData) {
  logSheet.insertColumnsAfter(colsInLogSheet, colsInHugeData - colsInLogSheet);
} else if (colsInLogSheet > colsInHugeData) {
  logSheet.deleteColumns(colsInHugeData, colsInLogSheet - colsInHugeData);
}

/* barring typos, insert data with confidence */
logSheet.getRange(1, 1, rowsInHugeData, colsInHugeData).setValues(hugeData);

这里发生的事情非常简单。我们计算出日志需要多大,然后调整目标 sheet 的大小以匹配该数据。