我有一张时间表数据的Google电子表格;它每个月都有一张表,每张表有很多六个列块,每个客户一个块。
我创建了一个摘要表,其中包含每个客户的总数并将其显示在列表中:
function getClientTotals(sheetname, colcount)
{
colcount = colcount ? colcount : 6;
var res;
var ss = SpreadsheetApp.openById('myid_goes_here');
if(ss)
{
res = [];
var totrow = ss.getRange(sheetname + '!A1:ZZ1').getValues()[0];
for(var i = 0; i < totrow.length; i += colcount)
{
res.push([totrow[i], totrow[i + colcount - 1]]);
}
}
return res;
}
然后,我在我的摘要表中添加了一个单元格,其中包含=getClientTotals($C$7,$C$8)
,该表格传递了月份的工作表名称和每个客户端的列数(如果是“架构”修改)。
这一切都正常,但是,当源数据发生更改时,它不会更新。我添加了一个onEdit
触发器;没有快乐。如果您转到脚本编辑器并点击“保存”,它会更新,但这没有用。我错过了什么吗?
你错过了挑剔的缓存 窃听器 特征。它以这种方式工作:
Google认为所有自定义函数仅直接依赖于其参数值来返回其结果(您可以选择依赖于其他静态数据)。
鉴于此先决条件,他们只能在参数更改时评估您的函数。例如
假设我们在单元格B1上有文本“10”,然后在其他一些单元格上输入=myFunction(B1)
将评估myFunction并检索其结果。然后,如果将单元格B1值更改为“35”,将按预期重新评估自定义,并正常检索新结果。现在,如果再次将单元格B1更改为原始“10”,则无法重新评估,将立即从缓存中检索原始结果。
因此,当您使用工作表名称作为参数来动态获取它并返回结果时,您将破坏缓存规则。
不幸的是,没有这个惊人的功能,你就无法拥有自定义功能因此,您必须将其更改为直接接收值,而不是表单名称,或者不使用自定义函数。例如,您可以在脚本上有一个参数,告诉摘要应该去哪里,并且只要总数发生变化,就会让onEdit
更新它们。
缓存问题的另一种解决方案。
在您的方法中有一个虚拟变量。通过
Filter(<the cell or cell range>,1=1)
作为该参数的值。
EG
=getValueScript("B1","B4:Z10", filter(B4:Z10,1=1))
不使用过滤器的输出。但是它向电子表格表明该公式对B4:Z10范围敏感。
我有一个类似的问题,为工作创建一个仪表板。 Chamil上面的解决方案(即使用Sheet的Filter函数作为函数传递给函数中的虚拟变量)工作得很好,尽管Arsen最近的评论。在我的情况下,我使用一个函数来监视一个范围,并且无法在相同的范围内使用过滤器,因为它创建了一个循环引用。所以我只有一个单元格(在我的情况下,在下面的代码中为E45),我在任何时候都希望我的函数更新时更改了数字:
=myFunction("E3:E43","D44",filter(E45,1=1))
正如Chamil指出的那样,脚本中没有使用过滤器:
function myFunction(range, colorRef, dummy) {
variable 'dummy' not used in code here
}
我在函数中使用虚拟变量,此变量引用电子表格中的单元格,然后在脚本中有一个Myfunction(),在该单元格中写入Math.Ramdon数字。此“MyFunction”处于触发服务(编辑/当前项目触发器)下,您可以选择不同的事件触发器,例如开启或时间驱动,您可以选择一个时间段,从1分钟到一个月
您可以做的是在电子表格中的某个位置设置另一个单元格,每次添加新工作表时都会更新该单元格。确保它不会针对每个更改进行更新,但仅限于您要进行计算时(在您添加工作表的情况下)。然后,将对此单元格的引用传递给自定义函数。如上所述,自定义函数可以忽略此参数。
鉴于Henrique Abreu解释的功能,您可以尝试开箱即用的电子表格函数QUERY,SQL喜欢的查询是我在处理原始数据时经常使用的,并将数据作为汇总获取到不同的选项卡,结果数据更新在原始数据发生变化后实时进行。
我的建议是基于以下事实:您的脚本没有高级工作,例如URL提取,只是数据工作,因为没有实际数据读取,我无法使用QUERY提供精确的解决方案。
关于Henrique Abreu提到的缓存功能(我没有足够的声誉在他的回答下直接评论),我做了测试并发现:
通过调用单元格在工作表中应用该自定义函数adder(),然后每次看到加载消息和总时间超过5秒时,前后更改该单元格值。它可能与此GAS issue:中提到的更新有关
这个问题现在已得到修复。 New Sheets中的自定义函数现在可以识别上下文,并且不会积极地缓存值。
我不想要一个虚拟参数。 YMMV对此。
1一个“项目列表”的单元格,一个是“刷新”
2如果单元格为“刷新”,则使用'onEdit'编写脚本:
a)清空文档缓存
b)用外部数据填充doc缓存(在我的例子中是一个表)
c)对于我的'getStockoData(...'自定义函数)的所有单元格
d)将(1)中的单元格设置为“Ready”
这确实刷新了你想要的位但不快。
由于google app脚本是JS的扩展,因此函数应该能够处理比函数签名中定义的更多args或更少的args。所以,如果你有一些功能
function ADD(a, b) {
return CONSTANTS!$A$1 + a + b
}
然后你会把这个函数称为
=ADD(A1, B1, $A$2)
其中$ A $ 2是一些复选框(插入 - >复选框),您可以在需要更改工作表和单元格中的值后单击“刷新”CONSTANTS $ A $ 1
正如@Brionius所说,对该功能提出了额外的动态论证。如果你使用now()你可能有超时问题使更新有点慢...
cell A1 = int(now()*1000)
cell A2 = function(args..., A1)