自定义功能不会随着输入的更改而刷新

时间:2019-07-04 19:34:04

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

我有一个自定义函数,可以找到另一个单元格的值并显示它。当源单元格更改时,该功能不反映。

https://docs.google.com/spreadsheets/d/1wfFe__g0VdXGAAaPthuhmWQo3A2nQtSVUhfGBt6aIQ0/edit?usp=sharing

刷新Google表格

function findRate() {
  var accountName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1).getValue(); //determine the account name to use in the horizontal search
  var rateTab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Rates'); //hold the name of the rate tab for further dissection
  var rateNumColumns =rateTab.getLastColumn(); //count the number of columns on the rate tab so we can later create an array
  var rateNumRows = rateTab.getLastRow(); //count the number of rows on the rate tab so we can create an array
  var rateSheet = rateTab.getRange(1,1,rateNumRows,rateNumColumns).getValues(); //create an array based on the number of rows & columns on the rate tab
  var currentRow = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getRow(); //gets the current row so we can get the name of the rate to search
  var rateToSearch = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(currentRow,1).getValue(); //gets the name of the rate to search on the rates tab
  for(rr=0;rr<rateSheet.length;++rr){
    if (rateSheet[rr][0]==rateToSearch){break} ;// if we find the name of the 
      }
  for(cc=0;cc<rateNumColumns;++cc){
    if (rateSheet[0][cc]==accountName){break};
      }
  var rate = rateSheet[rr][cc] ; //the value of the rate as specified by rate name and account name
  return rate;
}

如果我在“汇率”标签中更改汇率,则需要自定义功能来识别新汇率并更新其值

1 个答案:

答案 0 :(得分:1)

  • 在编辑=findRate()的工作表名称的单元格时,您要重新计算Rates的自定义函数。

如果我的理解是正确的,那么如何添加以下示例脚本?请认为这只是几个答案之一。

解决方案:

为了重新计算自定义函数,在此答案中,=findRate()的公式被运行OnEdit事件触发器(在此例中为简单触发器)的脚本覆盖。由此,执行重新计算。但是,当该公式直接由同一公式替换时,将不执行重新计算。所以我使用以下流程。

  1. 从“预计收入”表中检索公式为=findRate()的所有单元格区域。
  2. 清除范围公式。
  3. 将公式放入范围。

通过此流程,当编辑“费率”工作表的单元格时,通过自动运行=findRate()重新计算onEdit()的自定义函数。

示例脚本:

请复制以下脚本并将其粘贴到脚本编辑器中。 然后,请编辑工作表名称为Rates的单元格。这样,onEdit()将由OnEdit事件触发器自动运行。

function onEdit(e) {
  var range = e.range;
  if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
    var sheetName = "Projected Revenue"; // If you want to change the sheet name, please modify this.
    var formula = "=findRate()";// If you want to change the function name, please modify this.

    var sheet = e.source.getSheetByName(sheetName);
    var ranges = sheet.createTextFinder(formula).matchFormulaText(true).findAll().map(function(e) {return e.getA1Notation()});
    sheet.getRangeList(ranges).clearContent();
    SpreadsheetApp.flush();
    sheet.getRangeList(ranges).setFormula(formula);
  }
}

注意:

  • onEdit(e)由OnEdit事件触发器运行。因此,当您直接运行onEdit(e)时,会发生错误。请注意这一点。
  • 在此示例脚本中,作为示例,即使编辑了“费率”表的行1和列“ A”,也不会重新计算自定义函数。如果要修改此设置并限制要编辑的范围,请修改上面的脚本。

参考文献:

如果我误解了您的问题,而这不是您想要的结果,我深表歉意。

已添加:

来自TheMaster's comment的提案已反映到脚本中。当可以使用sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(formula)时,我还认为处理成本将大大降低。但是在我的环境中,即使使用flush(),似乎也需要清除一次公式以刷新自定义函数。因此,我提出了以上流程。

但是,现在我可以注意到使用replaceAllWith()的TextFinder的解决方法。所以我想添加它。此解决方法的流程如下。

  1. 使用=findRate()Projected Revenue的所有值替换为replaceAllWith()表中的值。
    • 在这种情况下,作为测试用例,公式被替换为sample
  2. 使用sample=findRate()替换为replaceAllWith()

通过此流程,我可以确认重新计算了=findRate()。而且,在这种情况下似乎不需要flush()

示例脚本:

请复制以下脚本并将其粘贴到脚本编辑器中。 然后,请编辑工作表名称为Rates的单元格。这样,onEdit()将由OnEdit事件触发器自动运行。

function onEdit(e) {
  var range = e.range;
  if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
    var sheetName = "Projected Revenue";
    var formula = "=findRate()";
    var tempValue = "sample";

    var sheet = e.source.getSheetByName(sheetName);
    sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(tempValue);
    sheet.createTextFinder(tempValue).matchFormulaText(true).replaceAllWith(formula);
  }
}