删除/处理谷歌工作表运行时限制



我最近获得了一个谷歌表单文件,该文件允许我在电子表格中使用ImportXML 50多次。https://docs.google.com/spreadsheets/d/1VriaQ6QMq69Ya3734DKRBZ1eUBRd3B1jCD-P6DUHKLA/edit?usp=sharing

我遇到了一个问题,脚本超时了,因为它必须运行太多的链接(目前不能超过250(,以至于达到了脚本运行时的限制。

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

我链接了上面的电子表格(出于保护原因,使用示例链接(。但如果你想看一看,这里是我为工作表运行的代码:

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();
}
}
}
}

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

这里要注意的方法是在(durationMilliseconds(之后。正因为如此,您可以在指定的毫秒数之后运行指定的任何函数。

在这种情况下,这种解决方法会变得更加复杂,因为您处于一个循环中,没有明确的地方可以将您的功能划分为几个部分。

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

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

其想法是,每次触发函数时,它都会从原来的位置恢复循环。在这种情况下,下次调用函数(使用上面指定的基于时间的触发器(时,它将需要关于我们在循环的哪个部分的信息:即xy索引的值。

下面是一个代码示例,它基本上完成了所有这些事情。但是,关于这个样本,必须考虑以下几点:

  • 我删除了外部for,因为我不明白它的用途。如果您需要它,您必须稍微修改此代码以包含它
  • 关于索引的信息(或者在本示例中,索引x(可以使用Properties Service或您喜欢的任何其他工具进行存储。但我每次都使用工作表本身来存储和检索值,以便更容易地跟踪它
  • 我在这个例子中使用了方法(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();
}

我希望这能有所帮助。

您所要做的就是将公式嵌套在if语句中,如so…例如,假设您在单元格A1中有一个importxml,并希望在单元格B1中加载更多内容,依此类推,您可以这样做…这样,下一个公式在第一个完成执行之前不会执行。

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

相关内容

最新更新