刷新由Google表格中的自定义函数检索的数据


90

我编写了一个自定义Google Apps脚本,该脚本id将从Web服务接收价格并从中获取信息(价格)。

我在电子表格中使用了此脚本,并且效果很好。我的问题是这些价格在变化,我的电子表格没有更新。

如何强制它重新运行脚本并更新单元(无需手动遍历每个单元)?


1
是的,这是我对此所做的解释:stackoverflow.com/questions/9022984/…–
Henrique G. Abreu

在我的研究中,我阅读了您的解释。非常有帮助,谢谢。我在我的答案中添加了链接。
tbkn23

对于遇到类似(定义和逻辑的,但有时是不幸的)行为的用户,在Google Issue Tracker:issuetracker.google.com/issues/36763858中批准该功能请求可能会有所帮助。
蒂莫西·约翰斯

这是我做的一个简单答案
天线

Answers:


91

好的,看来我的问题是google的行为很奇怪-只要脚本参数相似,它就不会重新运行脚本,它会使用以前运行的缓存结果。因此,它不会重新连接到API,也不会重新获取价格,它只会返回先前缓存的脚本结果。

在此处查看更多信息:https : //code.google.com/p/google-apps-script-issues/issues/detail?id=888

此处:总结数据的脚本未更新

我的解决方案是在脚本中添加另一个参数,我什至没有使用。现在,当您使用与先前调用不同的参数来调用该函数时,由于这些参数的结果将不在缓存中,因此必须重新运行脚本。

因此,每当我调用该函数时,对于额外的参数,我都会传递“ $ A $ 1”。我还创建了一个名为refresh的菜单项,当我运行它时,它将当前日期和时间放在A1中,因此必须重新计算以$ A $ 1作为第二个参数的所有脚本调用。这是我脚本中的一些代码:

function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Refresh",
    functionName : "refreshLastUpdate"
  }];
  sheet.addMenu("Refresh", entries);
};

function refreshLastUpdate() {
  SpreadsheetApp.getActiveSpreadsheet().getRange('A1').setValue(new Date().toTimeString());
}

function getPrice(itemId, datetime) {
  var headers =
      {
        "method" : "get",
        "contentType" : "application/json",
        headers : {'Cache-Control' : 'max-age=0'}
      };

  var jsonResponse = UrlFetchApp.fetch("http://someURL?item_id=" + itemId, headers);
  var jsonObj = eval( '(' + jsonResponse + ')' );
  return jsonObj.Price;
  SpreadsheetApp.flush();
}   

当我要将ID为5的商品的价格放在一个单元格中时,我使用以下公式:

=getPrice(5, $A$1)

当我想刷新价格时,只需单击“刷新”->“刷新”菜单项。请记住,更改onOpen()脚本后需要重新加载电子表格。


4
为什么不使用now()作为附加参数?
高级

5
您会看到,就像我的函数不会因为其参数未更改(即单元格的值)而被重新评估一样,now()也将由于没有参数而不会被重新评估,因此它的返回值将不会更改,因此函数的参数不会更改。另外,使用now()会使我的函数一直重新评估,考虑到它会生成多个HTTP调用,这会有点
麻烦

2
好发现。使用命名范围作为输入时遇到了这个问题。使用您的答案,我发现通常足以在输入范围内传递虚拟总和,例如“ sum(B:D)”,其中BD行位于自定义函数查找的范围内。更改任何单元格将触发总和更改,并且自定义函数将刷新。顺便说一句,似乎自定义函数甚至不必声明被忽略的参数。
肖恩·胡佛

1
遗憾的是,这仍然是我发现的最佳解决方案。并非Google只是允许我们为特定的函数调用禁用缓存,我们任意增加了缓存中存储的内容,只是为了确保我们不会得到缓存的值。不过,仍然要感谢帖子,
GrayedFox

尝试为您的自定义函数使用一个参数,例如此示例
天线

33

我知道这是一个老问题了。但是,此方法除了进行更改外不需要任何用户操作。

我所做的与tbkn23类似。

我要重新评估的函数有一个额外的未使用参数$ A $ 1。所以函数调用是

=myFunction(firstParam, $A$1)

但是在代码中,函数签名是

function myFunction(firstParam)

我没有使用Refresh函数,而是使用了像这样的onEdit(e)函数

function onEdit(e)
{
   SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Math.random());
}

每当编辑电子表格中的任何单元格时,都会触发此功能。因此,现在您编辑一个单元格,在A1中放置一个随机数,这将按照tbkn23的建议刷新参数列表,从而导致重新评估自定义函数。


5
效果很好。不利的一面是,撤销(ctrl + z)历史被搞砸了。
2016年

1
正如乔恩(Jon)所指出的那样,它具有令人讨厌的缺点,它是个不错的选择...我希望有人能改善它:-)
Enissay 2016年

小而古怪的告诫:在难以置信的事件Math.random返回相同的数字的情况下,由于该特定数字已经被缓存,因此它不会更新。
伍迪·佩恩

12

这已经很晚了,我不知道它是否有用,但实际上这里有一些设置,您可以NOW()自动进行更新

在此处输入图片说明


1
NOW()是内置函数,而不是自定义函数。
鲁本

@Rubén重点是,您可以在要对其进行更新的任何自定义函数中包括NOW()函数
Thaina 2016年

13
这时,自定义函数参数应该是确定性的,换句话说,它们不分配NOW()作为参数。见developers.google.com/apps-script/guides/sheets/functions
鲁本

3
如果您尝试使用NOW()的自定义函数内部它抛出一个错误
斯蒂法诺Giacone

6

如果您的自定义函数在特定列内,只需按该列对电子表格进行排序。

排序操作将强制刷新数据,这将立即为该列的所有行调用自定义函数。


1

这可能是一个超旧的线程,但对尝试这样做的人可能很有用,就像我刚才一样。

按照Lexi的脚本原样工作,它似乎不适用于当前的Sheets,但是如果我将哑变量作为参数添加到函数中(无需在函数内部实际使用),它将确实强制Google表格再次刷新页面。

因此,像这样的声明:function myFunction(firstParam,dummy)然后再调用它就像建议的那样。那对我有用。

另外,如果随机变量出现在您编辑的所有工作表上很麻烦,则限制为一张工作表的简单补救措施如下:

function onEdit(e)
{
  e.source.getSheetByName('THESHEETNAME').getRange('J1').setValue(Math.random());
}

1
@Rubén它非常相似,但是令人讨厌。而不是使用它使用一个定义表名称活动工作表,提高你的历史
乔纳斯D.

0

脚本逻辑:

  • 除非参数更改,否则自定义函数不会更新。
  • 创建一个onChange触发器以使用textFinder更改电子表格中所有自定义函数的所有参数

片段:

/*@customfunction*/
function sheetNames(e) {
  return SpreadsheetApp.getActive()
    .getSheets()
    .map(function(sheet) {
      return sheet.getName();
    });
}

/*Create a installable trigger to listen to grid changes on the sheet*/
function onChange(e) {
  if (!/GRID/.test(e.changeType)) return; //Listen only to grid change
  SpreadsheetApp.getActive()
    .createTextFinder('=SHEETNAMES\\([^)]*\\)')
    .matchFormulaText(true)
    .matchCase(false)
    .useRegularExpression(true)
    .replaceAllWith(
      '=SHEETNAMES(' + (Math.floor(Math.random() * 500) + 1) + ')'
    );
}

读书:


-3

如果编写了自定义函数并将其在电子表格中用作公式,则每次打开电子表格或修改任何引用单元格时,都会重新计算公式。

如果您只想盯着电子表格并希望更改其值,则可以考虑添加定时触发器以更新单元格。在此处阅读有关触发器的更多信息


10
那会很好,除非它不起作用...重新加载页面不会刷新值。此外,删除单元格并重新输入相同的函数调用,仍保留旧值。如果我从另一个单元格中完全调用相同的函数,它将显示新值,但不会在旧单元格中显示。
tbkn23 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.