15

我有一张大表,其中包含大约 30 个importxml函数,这些函数从通常每天更新两次的网站获取数据。

我想importxml及时(每 8 小时)运行该功能,以便我的 Google 电子表格将数据保存在另一张工作表中。保存已经有效,但是更新无效!

我在Google 电子表格行更新中读到它可能每 2 小时运行一次,但我不相信这是真的,因为自从我将它添加到我的工作表中,当电子表格未打开时,没有任何更改或更新。

我如何importxml以一种简单的方式“触发”我的 Google 电子表格中的功能,因为其中有很多importxml功能?

4

4 回答 4

18

我对 Mogsdad 的回答做了一些调整:

  • 修复了releaseLock()呼叫位置
  • 在导入函数中更新(或添加)查询字符串参数到 url(而不是存储、删除、等待 5 秒,然后恢复所有相关公式)
  • 适用于电子表格中的特定工作表
  • 显示上次更新时间

...

function RefreshImports() {
  var lock = LockService.getScriptLock();
  if (!lock.tryLock(5000)) return;             // Wait up to 5s for previous refresh to end.

  var id = "[YOUR SPREADSHEET ID]";
  var ss = SpreadsheetApp.openById(id);
  var sheet = ss.getSheetByName("[SHEET NAME]");
  var dataRange = sheet.getDataRange();
  var formulas = dataRange.getFormulas();
  var content = "";
  var now = new Date();
  var time = now.getTime();
  var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
  var re2 = /((\?|&)(update=[0-9]*))/gi;
  var re3 = /(",)/gi;

  for (var row=0; row<formulas.length; row++) {
    for (var col=0; col<formulas[0].length; col++) {
      content = formulas[row][col];
      if (content != "") {
        var match = content.search(re);
        if (match !== -1 ) {
          // import function is used in this cell
          var updatedContent = content.toString().replace(re2,"$2update=" + time);
          if (updatedContent == content) {
            // No querystring exists yet in url
            updatedContent = content.toString().replace(re3,"?update=" + time + "$1");
          }
          // Update url in formula with querystring param
          sheet.getRange(row+1, col+1).setFormula(updatedContent);
        }
      }
    }
  }

  // Done refresh; release the lock.
  lock.releaseLock();

  // Show last updated time on sheet somewhere
  sheet.getRange(7,2).setValue("Rates were last updated at " + now.toLocaleTimeString())
}
于 2017-05-25T00:03:10.023 回答
16

Google 电子表格行更新问题及其答案是指“旧表格”,其行为与 2015 版 Google 表格不同。“新工作表”不会自动刷新内容;现在仅评估更改以响应编辑。

虽然 Sheets 本身不再提供此功能,但我们可以使用脚本来刷新“导入”公式(、IMPORTXMLIMPORTDATA)。IMPORTHTMLIMPORTANGE

实用程序脚本

对于IMPORT公式的定期刷新,将此函数设置为时间驱动触发器

注意事项:

  • 其他脚本或用户在刷新期间对电子表格所做的导入函数公式更改可能会被覆盖
  • 重叠刷新可能会使您的电子表格不稳定。为了缓解这种情况,实用程序脚本使用ScriptLock. 这可能与脚本中该锁的其他用途发生冲突。

 

/**
 * Go through all sheets in a spreadsheet, identify and remove all spreadsheet
 * import functions, then replace them a while later. This causes a "refresh"
 * of the "import" functions. For periodic refresh of these formulas, set this
 * function up as a time-based trigger.
 *
 * Caution: Formula changes made to the spreadsheet by other scripts or users
 * during the refresh period COULD BE OVERWRITTEN.
 *
 * From: https://stackoverflow.com/a/33875957/1677912
 */
function RefreshImports() {
  var lock = LockService.getScriptLock();
  if (!lock.tryLock(5000)) return;             // Wait up to 5s for previous refresh to end.
  // At this point, we are holding the lock.

  var id = "YOUR-SHEET-ID";
  var ss = SpreadsheetApp.openById(id);
  var sheets = ss.getSheets();

  for (var sheetNum=0; sheetNum<sheets.length; sheetNum++) {
    var sheet = sheets[sheetNum];
    var dataRange = sheet.getDataRange();
    var formulas = dataRange.getFormulas();
    var tempFormulas = [];
    for (var row=0; row<formulas.length; row++) {
      for (col=0; col<formulas[0].length; col++) {
        // Blank all formulas containing any "import" function
        // See https://regex101.com/r/bE7fJ6/2
        var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
        if (formulas[row][col].search(re) !== -1 ) {
          tempFormulas.push({row:row+1,
                             col:col+1,
                             formula:formulas[row][col]});
          sheet.getRange(row+1, col+1).setFormula("");
        }
      }
    }

    // After a pause, replace the import functions
    Utilities.sleep(5000);
    for (var i=0; i<tempFormulas.length; i++) {
      var cell = tempFormulas[i];
      sheet.getRange( cell.row, cell.col ).setFormula(cell.formula)
    }

    // Done refresh; release the lock.
    lock.releaseLock();
  }
}
于 2015-11-23T16:33:08.870 回答
15

要回答您的问题以获得简单的“触发器”以强制重新加载函数:

向您正在加载的 url 添加一个额外的未使用参数,同时为该参数的值引用一个单元格。更改该单元格的内容后,该函数将重新加载。

例子:

importxml("http://www.example.com/?noop=" & $A$1,"...")

不幸的是,您不能将日期计算函数放入引用的单元格中,这会引发错误,这是不允许的。

于 2016-12-19T13:58:15.190 回答
0

您还可以将每个 XML 公式作为注释放在相应的单元格中,并记录一个宏以将其复制并粘贴到同一单元格中。稍后使用脚本和触发器功能来安排这个宏。 谷歌表格评论 谷歌脚本 谷歌触发器

于 2020-10-21T15:20:25.690 回答