刷新Google表格中自定义功能检索的数据

tbk*_*n23 78 google-sheets google-apps-script custom-function

我编写了一个自定义的Google Apps脚本,它将id从Web服务接收和获取信息(价格).

我在电子表格中使用这个脚本,它工作得很好.我的问题是这些价格会发生变化,我的电子表格也不会更新.

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

tbk*_*n23 81

好吧,似乎我的问题是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();
}   
Run Code Online (Sandbox Code Playgroud)

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

=getPrice(5, $A$1)
Run Code Online (Sandbox Code Playgroud)

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

  • 你看,就像我的函数不会被重新评估,因为它的参数没有改变(即单元格的值),now()也不会被重新评估,因为它没有参数,因此它的返回值将是不改变,所以我的函数的参数不会改变.另外,使用now()将导致我的函数重新评估所有时间,考虑到它生成多个HTTP调用,这有点重... (5认同)
  • 为什么不使用now()作为附加参数? (3认同)
  • 好找。我在使用命名范围作为输入时遇到了这个问题。使用您的回答,我发现在输入范围内传递虚拟总和通常就足够了,如在“sum(B:D)”中,其中 BD 行在自定义函数查找的范围内。更改任何单元格将触发总和更改和自定义函数刷新。顺便说一句,似乎自定义函数甚至不必声明忽略的参数。 (2认同)
  • 方便的是,您**不需要**需要将参数添加到脚本中。因此,您可以将脚本保留为“function getPrice(itemId)”,并将其调用为“=getPrice(5, $A$1)”。额外的论点似乎被忽略了。对我来说,这是最好的。然后我要做的就是在“A1”中输入一个字符来触发刷新。就像使用菜单项一样快捷,并且设置更方便。 (2认同)

小智 32

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

我所做的与tbkn23类似.

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

=myFunction(firstParam, $A$1)
Run Code Online (Sandbox Code Playgroud)

但在代码中,函数签名是

function myFunction(firstParam)
Run Code Online (Sandbox Code Playgroud)

我没有使用刷新功能,而是像这样使用了onEdit(e)函数

function onEdit(e)
{
   SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Math.random());
}
Run Code Online (Sandbox Code Playgroud)

只要编辑电子表格中的任何单元格,就会触发此功能.所以现在你编辑一个单元格,一个随机数放在A1中,这会刷新参数列表为tbkn23建议,导致自定义函数被重新评估.

  • 效果很好.下行是,撤消(ctrl + z)历史搞砸了. (4认同)
  • 这个答案的小而迂腐的警告;在极不可能发生的情况下 Math.random 返回相同的数字,在那种情况下它不会更新,因为该特定数字已经被缓存。 (2认同)

Tha*_*ina 12

这是非常晚的,我不知道它会有用但实际上有设置在这里你可以NOW()自动更新

在此输入图像描述

  • 此时自定义函数参数应该是确定性的,换句话说,它们不是NOW()作为参数.请参阅https://developers.google.com/apps-script/guides/sheets/functions (10认同)
  • 如果您尝试在自定义函数中使用 NOW(),则会引发错误 (7认同)
  • `NOW()` 是一个内置函数,而不是自定义函数。 (2认同)

flu*_*flu 7

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

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


The*_*ter 6

脚本逻辑:

  • 除非参数更改,否则自定义函数不会更新。

  • 创建onChange触发器以使用以下命令更改电子表格中所有自定义函数的所有参数TextFinder

  • 通过@tbkn23添加额外的虚拟参数并通过@Lexi Brush使用触发器的想法在此处以随机数作为参数实现。这个答案主要因类的使用而不同TextFinder(Apps 脚本的一个相对较新的补充),这是更好的,因为

    • 不需要额外的单元格。

    • 不需要菜单 > 不需要额外的点击。如果您需要自定义复习,复选框是更好的实现

    • 您还可以更改公式本身而不是更改参数

    • 更改/触发器可以配置为仅过滤掉某些更改。例如,以下示例脚本触发器过滤掉除INSERT_GRID/REMOVE_GRID(Grid=Sheet)之外的所有更改。这适用于提供sheetnames. 任何地方的编辑都不会改变工作表/工作表名称的列表,但插入或删除工作表会改变。

示例脚本(获取工作表列表):

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

/**
 * @listens to changes in a Google sheet
 * @see https://developers.google.com/apps-script/guides/triggers/installable#managing_triggers_manually
 */
function onChange(e) {
  /* Following types of change are available:
   * EDIT
   * INSERT_ROW
   * INSERT_COLUMN
   * REMOVE_ROW
   * REMOVE_COLUMN
   * INSERT_GRID
   * REMOVE_GRID
   * FORMAT
   * OTHER - This usually refers to changes made by the script itself or sheets api
   */
  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) + ')'
    );
}
Run Code Online (Sandbox Code Playgroud)

阅读:


Max*_*rov 5

如前所述:

除非参数更改,否则自定义函数不会更新。

可能的解决方案是在单个单元格中创建一个复选框,并使用该单元格作为自定义函数的参数:

  1. 创建复选框:选择空闲单元格,例如[A1],转到[插入] > [复选框]
  2. 使该单元格成为一个参数:=myFunction(A1)
  3. 单击复选框刷新公式