【问题标题】:Force Google Spreadsheet formula to recalculate强制 Google 电子表格公式重新计算
【发布时间】:2018-02-16 12:08:42
【问题描述】:

我以前知道这个问题has been asked,但给出的答案对我的情况无效,因为它略有不同。

我创建了一个公式,用于查找名称中带有模式的工作表,然后使用其内容生成输出。例如

function sampleFormula(searchTerm) {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheets = spreadsheet.getSheets()
    .filter(function(sheet) {
      // If sheet name starts with DATA_SHEET_...
      return sheet.getSheetName().indexOf('DATA_SHEET_') === 0;
    });

  const result = [];

  sheets.forEach(function(sheet) {
    // We get all the rows in the sheet
    const rows = sheet.getDataRange().getValues();

    rows.forEach(function(row) => {
      // If the row it's what we are looking for we pick the columns A and C
      if (row[1] === searchTerm) {
        result.push([ row[0], row[2] ])
      }
    });
  });

  // If we found values we return them, otherwise we return emptry string
  return result.length ? result : '';
}

问题是,当工作表中名称以DATA_SHEET_ 开头的单元格发生变化时,我需要重新计算此公式。

我看到大多数答案(以及我通常做的)是将我们想要观察的范围作为公式的参数传递,即使它没有被使用。但在这种情况下,它不起作用,因为我们不知道我们正在观看多少个范围,我们甚至不知道整个工作表名称(它是由使用 Google 电子表格 API 的网络服务注入的)。

我原以为 Google Script 会有 range.watch(formula)range.onChange(this) 之类的东西,但我找不到类似的东西。

我还尝试创建一个简单的函数来更改每个公式所依赖的单元格 B2 的值,但我需要立即恢复它,因此它不被视为更改(如果我真的更改它,所有公式都会中断):

// This does NOT work
function forceUpdate() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getActiveSheet();
  const range = sheet.getRange(1, 1);
  const content = range.getValue();

  range.setValue('POTATO');
  range.setValue(content);
}

所以我不知道我还能做什么,我在多个工作表上有一百个公式这样做,当我修改 DATA_SHEET_... 工作表时它们没有更新。

【问题讨论】:

  • 包含这些公式的单元格是随机放置的,还是总是一个正方形范围(连续的列和行集)?另外,我是否正确理解数据表值会自动更新?
  • 公式被放置在不同的非相邻单元格中。数据表中有一些列是手动更新的,一些是自动更新的。

标签: google-apps-script google-sheets custom-function


【解决方案1】:

要强制重新计算自定义函数,我们可以使用“触发参数”,它只是触发自定义函数重新计算。这个触发参数可以是一个单元格引用,它将由一个简单的编辑触发器更新,或者我们可以使用一个可编辑的可安装触发器来更新所有公式。

使用单元格引用作为触发参数的示例

=sampleFormula("searchTerm",Triggers!A1)

使用可编辑的可安装触发器更新所有公式的示例

假设公式具有以下形式,包含公式的单元格是 Test!A1 和 Test!F5

=sampleFormula("searchTerm",0)

其中 0 将被 sampleFormula 忽略,但会重新计算。

设置编辑安装触发器以触发以下功能

function forceRecalculation(){
  updateFormula(['Test!A1','Test!F5']);
}

进行更新的函数可能如下所示:

function updateFormula(references){
  var rL = SpreadsheetApp.getActive().getRangeList(references);
  rL.getRanges().forEach(function(r){
    var formula = r.getFormula();
    var x = formula.match(/,(\d+)\)/)[1];
    var y = parseInt(x)+1;
    var newFormula = formula.replace(x,y.toString());
    r.setFormula(newFormula);
  });
}

您可以想象,上面的示例会比使用单元格引用作为触发参数要慢,但在某些情况下可能会很方便。

【讨论】:

    猜你喜欢
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多