删除/解决 google 张 运行-时间限制

Removing / working around google sheets run-time limit

我最近获得了一个 google sheets 文件,它可以让我在传播中使用 ImportXML 超过 50 次sheet。 https://docs.google.com/spreadsheets/d/1VriaQ6QMq69Ya3734DKRBZ1eUBRd3B1jCD-P6DUHKLA/edit?usp=sharing

我 运行 遇到脚本超时的问题,因为它必须 运行 通过如此多的链接(目前不能超过 250 个)到达脚本 运行-时限.

我想知道是否有办法关闭脚本 运行-时间限制或让它每 5 分钟中断并重新启动。我现在不太擅长应用程序脚本,因为我刚开始学习它,希望有人能给我指明正确的方向。

我链接了上面的传播sheet(出于保护原因带有示例链接)。但是这里是 运行ning 的 sheet 代码,如果你想看一下:

function bulkXml() {

    var sheet = SpreadsheetApp.getActiveSheet();
    var lastRow = sheet.getLastRow()
    var Num = sheet.getRange(2, 1, lastRow, 1).getValues();

    Num = Num.filter(function(u) {
        return u[0].length > 2
    })

    //  Logger.log(a)
    // return false

    for (var y = 0; y < 2; y++) {
        for (var x = 2; x - 2 < Num.length; x++) {
            var url = sheet.getRange(x, 1).getValue();
            sheet.getRange(2, 6).setValue(url);
            var xpathResult = sheet.getRange(3, 6).getValue();
            var counter = x - 1;
            sheet.getRange("C4").setValue(" PLEASE WAIT...CURRENTLY FETCHING " + counter + " OUT OF " + Num.length);

            if (y === 1) {
                sheet.getRange(x, 2).setValue(xpathResult);
                sheet.getRange("C4").setValue("PROCESSED " + counter + " OUT OF " + Num.length);
                SpreadsheetApp.flush();
            }

        }

    }

}

您所要做的就是像这样将公式嵌套在 if 语句中...例如,假设您在单元格 A1 中有一个 importxml 并且想在单元格 B1 中加载更多内容等等,您可以这样做...这样下一个将不会执行,直到第一个执行完。

=if(iferror(A1,"")="Loading...","",importxml(

我认为绕过 6 分钟时间限制的一个好方法是将操作分成几个部分,并在每个部分的末尾创建一个基于时间的触发器,它将在指定的时间后调用以下部分时间量。

这里要注意的方法是after(durationMilliseconds)。多亏了这一点,您可以 运行 在指定的毫秒数后指定任何函数。

在这种情况下,此解决方法会变得更加复杂,因为您处于循环中并且没有明确的位置可以将您的函数拆分为几个部分。

(1) 一种选择是在每次迭代后(或在指定的迭代次数后)计算脚本中的执行时间,如果此执行时间接近 6 分钟的时间限制,则停止脚本并创建一个将再次调用该函数的触发器。

(2) 另一种选择是或多或少地知道您可以在 6 分钟内进行多少次迭代,然后停止该函数并在该次迭代后再次调用它。

这个想法是每次触发函数时,它都会从它离开的地方恢复循环。在这种情况下,下次调用该函数时(使用上面指定的基于时间的触发器),它需要有关我们处于循环的哪一部分的信息:即 xy 索引。

下面是基本上完成所有这些事情的代码示例。不过,关于此示例必须考虑几点:

  • 我删除了外面的 for,因为我不明白它的用途。如果您需要它,您将不得不稍微修改此代码以包含它。
  • 可以使用 Properties Service 或您喜欢的任何其他工具来存储有关索引(或在本示例中为索引 x)的信息。但是我每次都使用 sheet 本身来存储和检索值,以便更容易地跟踪它。
  • 我在此示例中使用了方法 (2)(我定义了在脚本停止并再次调用之前要执行的迭代次数,在本例中为 25)。相应更改。
function bulkXml() {  
  var sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow()  
  var Num = sheet.getRange(2, 1, lastRow, 1).getValues();  
  Num = Num.filter(function(u) { 
   return u[0].length > 2
  });

  // Delete all triggers to avoid duplication:
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }

  // Define the index to start with loop (information coming from sheet):
  var x_range = sheet.getRange(20, 8);
  var x_old = x_range.getValue();  
  if (x_old == "") {
    x_old = 2;
    x_range.setValue(x_old);
  }

  // Looping through each row (from the index it stopped last time till 25 rows below that):
  for (var x = x_old; x - 2 < Num.length && x < x_old + 25; x++) {
    var url = sheet.getRange(x, 1).getValue();
    sheet.getRange(2, 6).setValue(url);
    var xpathResult = sheet.getRange(3,6).getValue();    
    var counter = x - 1;  
    sheet.getRange(x, 2).setValue(xpathResult);
    sheet.getRange("C4").setValue("PROCESSED " + counter + " OUT OF " + Num.length);
    SpreadsheetApp.flush();
  }
  x_range.setValue(x); // Set index to start from next time

  // Calling the script again after some time:
  ScriptApp.newTrigger("bulkXml")
  .timeBased()
  .after(1000)
  .create();
}

希望对您有所帮助。