我可以在Google表格中将标准函数包装在自定义函数中以控制其运行时间吗?

时间:2019-04-29 14:56:45

标签: google-apps-script google-sheets

我最初是在WebApps上问这个的,以为我只是想念一个Google技巧。在那里,我收到了一个答案,那就是它需要一个自定义函数。

https://webapps.stackexchange.com/questions/129068/recalculate-google-sheet-on-demand

这是我最初的问题:

  

我在工作表中有以下公式:

=if(E1="HOLD",,query(Cust_Orders!B6:Z5000,"Select Y,G,I,H,K where H>0  "))
     

将E1下拉为HOLD和FETCH值

     

我去FETCH时重新计算大约需要13秒。

     

但是当它处于HOLD状态时,查询不会执行,一切都会进行   空白。不是我想要的。

     

我试图避免每次我进行一次查询时都重新计算该查询   在Cust_Orders范围内进行更改,但将旧值保留为两个   他人查看的不同数据透视表是依赖的   在上面。

     

Google电子表格的重新计算设置全部为“更改且 foo

     

有没有办法做到这一点?

自定义函数仅在其参数之一更改时更新。因此,如果该函数仅取决于HOLD / FETCH单元格,但执行的公式是查询单元格,那么我认为我赢了。

我的研究:

这个答案google sheets custom function built-in function的具体含义是告诉OP如何用脚本语言执行他想做的事情。我怀疑用appscript重写查询不会获得胜利。

此链接Using Bound Google Scripts to Generate a Query Object

提出了

作为解决方案,但实际上是在脚本中重写了我的内置函数。我想尽可能少地使用脚本,并且尽可能通用地使用脚本,因为这样可以简化长期维护和修改工作。

上面的查询功能是一个示例。我正在寻找一种更通用的解决方案,该解决方案允许我使用同一脚本使用任意公式。

这次在Google产品论坛上的讨论:https://support.google.com/docs/forum/AAAABuH1jm01F-8MzzCxbY/?hl=en&gpf=%23!topic%2Fdocs%2F1F-8MzzCxbY说,您无法通过脚本调用内置函数。但是问题已经有4年了。

我也曾在这里问过这个问题,但通常在Google产品论坛上问的是“冰雹玛丽”。

可行的解决方案:

  • 调用内置函数的脚本示例。
  • 指向附件的链接,该附件允许重新计算范围的开/关
  • 比自定义公式更通用的方法来控制重新计算。

我不想要一个脚本来模拟所需的内置脚本。

1 个答案:

答案 0 :(得分:1)

  
      
  • 比自定义公式更通用的方法来控制重新计算。
  •   

我在为客户进行的项目中要做的是将“昂贵的”公式另存为脚本中的变量,并具有冻结/取消冻结某些范围(对重新计算时间有很大影响的范围)的按钮。 / p>

  • “取消冻结”按钮会将公式添加到电子表格
  • “冻结”按钮将公式结果置于公式使用的范围内
  • 有一个文档属性可存储冻结/未冻结的电子表格状态
  • 侧边栏用于显示电子表格状态按钮。
  
      
  • 调用内置函数的脚本示例。
  •   

脚本可以获取值,显示值,公式和其他内容,但不能调用内置函数。


对于我的客户,他们按表有一个数组公式(IMPORTRANGE,QUERY,FILTER,ARRAYFORMULA等),所有包含的公式都在A1上。公式保存在以下形式的对象数组中

var formulas = [
  {
    name:'Sheet1',
    address:'A1',
    formula:'=IMPORTRANGE(...)'
  }
]

包括了address属性,用于将来的改进。

“冻结”功能的关键代码行是

var dataRange = sheet.getDataRange();
dataRange.copyTo(dataRange, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);

请注意,以上几行复制-粘贴-按值表示整个数据范围。

“取消冻结”功能的关键代码行是

formulas.forEach(function(item){
  var sheet = spreadsheet.getSheetByName(item.name);
  sheet.clear();
  sheet.getRange(item.address).setFormula(item.formula);
});

请注意,以上几行清除了整个工作表。