使用Google脚本复制页面后,电子表格公式不会更新。我该如何解决这个问题

时间:2014-10-11 02:04:27

标签: javascript google-apps-script google-sheets

首先,这是我正在讨论的两个基本电子表格:

第一页:https://docs.google.com/spreadsheets/d/1GZs_I9_beIO9xYBXatoxStRMmk9Aj3-UxPQpB9-iA-I/edit?usp=sharing

第二页:https://docs.google.com/spreadsheets/d/1R86_0SrAtyIJPAhMW0Ura-3gwOLn5l9u7Seuj2V0YCA/edit?usp=sharing

基本上我使用Google脚本来“更新”标题为“要更新的副本”的电子表格。此副本将自动复制“复制到从中提取更新”中的所有页面,删除“要更新的副本”上的当前页面,然后将复制的页面重命名为之前的页面。这意味着我对“从中提取更新的副本”所做的任何更改都将自动在其他电子表格中更新,而无需重新分发电子表格。

当在“更新页面”表单上按下按钮时,页面成功传输。更新电子表格上的更改已成功“更新”。但是,代码中首先更新的页面有错误。具有从另一张纸张获取数据的公式的任何单元格都会返回“#REF!”错误“未解析的工作表名称'在此处插入工作表名称'。”这意味着公式/单元格无法从脚本中看到新复制的工作表。我可以通过点击受此影响的任何细胞并按下输入来解决这种情况 - 基本上“刷新”细胞。但是我在一个100多个像这样的单元格的项目中这样做,我只想按一个按钮就可以做到这一点。

我应该尝试使用脚本解决此问题,还是以不同的方式更改我更新电子表格页面的方法?感谢提前帮助!

以下是我正在使用的脚本:

<code>
function Update() {
//Sets the ID of the page to update from
var ID = "1R86_0SrAtyIJPAhMW0Ura-3gwOLn5l9u7Seuj2V0YCA"
//Pulls the correct sheet using the ID
var source = SpreadsheetApp.openById(ID);
//Identifies the active spreadsheet in use to update. (The spreadsheet you pressed "Update" on)
var destination = SpreadsheetApp.getActiveSpreadsheet();
//Sheet to pull and copy to the current spreadsheet
var sheet1 = source.getSheetByName("1");
//Copying the sheet accross
sheet1.copyTo(destination);
//Identifies the old copy of the sheet
var sheet1 = destination.getSheetByName('1');
//Deletes the old copy of the sheet
destination.deleteSheet(sheet1);
//Gets the new copy of the sheet
var sheet1 = destination.getSheetByName('Copy of 1');
//Renames the new copy of the sheet
sheet1.setName("1")
//Repeating the same code with page 2
//Sheet to pull and copy to the current spreadsheet
var sheet1 = source.getSheetByName("2");
//Copying the sheet accross
sheet1.copyTo(destination);
//Identifies the old copy of the sheet
var sheet1 = destination.getSheetByName('2');
//Deletes the old copy of the sheet
destination.deleteSheet(sheet1);
//Gets the new copy of the sheet
var sheet1 = destination.getSheetByName('Copy of 2');
//Renames the new copy of the sheet
sheet1.setName("2")
//Repeating the same code
}
</code>

2 个答案:

答案 0 :(得分:1)

这与Force formula refresh through Apps Script

有关

我有完全相同的问题。我的大多数公式都是第一行或第二行中的=ArrayFormula公式。我的解决方案遍历给定电子表格的前两行中的所有单元格,并重新评估任何公式。

如果它是一个公式(而不是重置非公式的文本值),这可能会被清理为仅修改单元格。也可以通过更改指定的范围来修改它以在整个电子表格上运行。

您可以在工作表复制到新位置后在工作表上运行此功能,也可以在所需工作表处于活动状态时调用myFunction

function updateFormulasTwoRows(given_sheet) {
  var last_col = given_sheet.getDataRange().getLastColumn();
  var range = given_sheet.getRange(1,1,2,last_col);
  // contains empty strings or cell formulas
  var formulas = range.getFormulas();
  // contains text, formula errors, formula output
  var contents = range.getValues(); 

  // formulas[0][0].length > 1 ==> is a formula
  for (var r = 0; r < range.getHeight(); r++) {
    for (var c = 0; c < range.getWidth(); c++) {
      var cell = range.getCell(r+1,c+1);
      // clear only the contents, not notes or comments or formatting.
      cell.clearContent();
      if (formulas[r][c].length > 1) {
        // cell was a formula, so insert the formula back in place
        cell.setValue(formulas[r][c]);
      } else {
        // cell was not a formula, so insert the text content back in place
        cell.setValue(contents[r][c]);
      }
    }
  }
}

// run this after selecting a sheet to reevalute formulas on
function myFunction() {
  var curr_sheet = SpreadsheetApp.getActiveSheet();
  updateFormulasTwoRows(curr_sheet);
}

答案 1 :(得分:0)

在上面@bryan的答案的基础上,我发现下面的代码更有效,它在范围级别而不是在每个单元格上执行clearContent()setValue()调用,从而节省了对后端的大量呼叫。

var updateFormulasAllRows = function updateFormulasAllRows(sheet) {
  var range = sheet.getDataRange();
  var formulas = range.getFormulas();
  var contents = range.getValues();
  var rangeWidth = range.getWidth(), rangeHeight = range.getHeight();
  for (var r = 0; r < rangeHeight; r++) {
    for (var c = 0; c < rangeWidth; c++) {
      if (formulas[r][c].length > 1) {
        contents[r][c] = formulas[r][c];
      }
    }
  }
  range.clearContent().setValues(contents);
};

作为改进建议,这还会更改代码以使其可以在电子表格的所有行上运行。