用于汇总数据未更新的脚本

时间:2012-01-26 18:05:24

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

我有一张时间表数据的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触发器;没有快乐。如果您转到脚本编辑器并点击“保存”,它会更新,但这没有用。我错过了什么吗?

10 个答案:

答案 0 :(得分:33)

你错过了挑剔的缓存 bug 功能。它的工作原理如下:

Google认为您的所有自定义函数都直接依赖 参数值来返回结果(您可以选择依赖其他静态数据)。

鉴于此先决条件,他们只能在参数更改时评估您的功能。 e.g。

假设我们在单元格B1上有文本“10”,然后在其他一些单元格上输入=myFunction(B1)

将评估myFunction并检索其结果。然后,如果将单元格B1值更改为“35”,将按预期重新评估自定义,并正常检索新结果。 现在,如果再次将单元格B1更改为原始“10”,则无法重新评估,将立即从缓存中检索原始结果。

因此,当您使用工作表名称作为参数来动态获取它并返回结果时,您将破坏缓存规则。

不幸的是,没有这个惊人的功能,你就无法拥有自定义功能。因此,您必须将其更改为直接接收值,而不是表单名称,或者不使用自定义函数。例如,您可以在脚本上设置一个参数,告诉摘要应该去哪里,并在总计更改时让onEdit更新它们。

答案 1 :(得分:1)

缓存问题的另一种解决方案。

在您的方法中有一个虚拟变量。 传递

Filter(<the cell or cell range>,1=1)

作为该参数的值。

e.g。

=getValueScript("B1","B4:Z10", filter(B4:Z10,1=1))

不使用过滤器的输出。但是它向电子表格表明该公式对B4:Z10范围敏感。

答案 2 :(得分:1)

我有一个类似的问题,为工作创建一个仪表板。 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
}

答案 3 :(得分:1)

我在函数中使用了虚拟变量,该变量引用电子表格中的单元格 那么y在脚本中有一个Myfunction(),可以在该单元格中写入Math.Ramdon数字。 此“ MyFunction”位于触发器服务(“编辑” /“当前项目”触发器)下,您可以选择不同的事件触发器,例如“打开”或“时间驱动”,在那里您可以选择例如从1分钟到一个月的时间段

答案 4 :(得分:0)

您可以做的是在电子表格中的某个位置设置另一个单元格,每次添加新工作表时都会更新该单元格。确保它不会针对每个更改进行更新,但仅限于您要进行计算时(在您添加工作表的情况下)。然后,将对此单元格的引用传递给自定义函数。如上所述,自定义函数可以忽略此参数。

答案 5 :(得分:0)

鉴于Henrique Abreu解释的功能,您可以尝试开箱即用的电子表格功能QUERY ,SQL喜欢的查询是我经常在工作中使用的 在原始数据上,并将数据作为摘要获取到不同的选项卡,结果数据在原始数据更改后实时更新。

我的建议是基于以下事实:您的脚本没有高级工作,例如URL提取,只是数据工作,因为没有实际数据读取,我无法使用QUERY提供精确的解决方案。

关于Henrique Abreu提到的缓存功能(我没有足够的声誉直接根据他的回答发表评论),我做了测试并发现:

  1. 看起来没有缓存工作,测试功能的脚本如下所示:

    function adder(base){ 使用Utilities.sleep(5000); 返回基数+10; }

  2. 通过调用单元格在工作表中应用该自定义函数adder(),然后每次看到加载消息和总时间超过5秒时,前后更改该单元格值。 它可能与此GAS issue:

    中提到的更新有关
      

    此问题现已修复。新表中的自定义函数现在可以识别上下文,并且不会积极地缓存值。

    1. 本主题中提到的问题仍然存在,我的测试表明,Google表格每次重新计算自定义功能

      • 函数直接调用的值已更改。

      function getCellValue(sheetName,row,col) { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sh = ss.getSheetByName(sheetName); return sh.getRange(row,col).getValue(); }

      enter image description here
      黄色单元格中任何值的更改都将导致重新计算自定义函数;函数忽略实际数据源值的变化。

      • 包含单元格位置的函数在工作表中更改。恩。插入/移除上方或左侧的行/列。

答案 6 :(得分:0)

我不想有一个虚拟参数。 YMMV对此。

1作为&#39;项目列表的单元格,其中一个是&#34;刷新&#34;

如果单元格为&#34;刷新&#34;

a)清空文档缓存

b)使用外部数据(在我的情况下为表格)填充文档缓存

c)对于我的&#39; getStockoData(...&#39;自定义函数

的所有单元格
  • 得到公式

  • 设置&#39; = 0&#39;

  • 设置fromula

d)将(1)中的单元格设置为&#34; Ready&#34;

这会刷新您想要的位但不快。

答案 7 :(得分:0)

由于google app脚本是JS的扩展,因此函数应该能够处理比函数签名中定义的参数更多或更少的args。因此,如果您有类似的功能

function ADD(a, b) {
  return CONSTANTS!$A$1 + a + b
}

然后您将这个函数称为

=ADD(A1, B1, $A$2)

其中$ A $ 2是一些复选框(插入->复选框),在您需要从工作表和单元格中更改值CONSTANTS $ A $ 1

时,可以单击以“刷新”

答案 8 :(得分:0)

使用google财务函数作为参数。像= GOOGLEFINANCE(“ CURRENCY:CADARS”)

这些功能每x分钟强制重新加载

答案 9 :(得分:-1)

正如@Brionius所说,对该功能提出了额外的动态论证。如果你使用now()你可能有超时问题使更新有点慢......

cell A1 = int(now()*1000)
cell A2 = function(args..., A1)