11

Because google spreadsheets does not support iterations, I wrote my own simple app script to adjust an input based upon the calculation of the spreadsheet output. However, after I change the input variable, the spreadsheet recalculates but app scripts does not seem to wait for that recalculation so I end up retrieving values such as "Thinking..." or "#NA". Is there a way to pause a script and wait for the calculation to complete before moving to the next line in the script?

Currently, I am just using a loop to watch the cell but I wanted to find out if there was a more elegant way to pause the execution until the sheet was done calculating.

I write a lot of Excel Macros and Excel VBA always waits for the calculation to complete before moving to the next line in the code. Apps Script does not seem to do this so I am hoping there is an easy way to do this.

A second question: Because this iteration can take some time, how does one interrupt and terminate a script from running? I can't seem to find a way to do this.

4

5 回答 5

8

这是一种非常简单的方法,可以防止下一个脚本启动,直到当前脚本在 google 应用程序脚本中完成。只需在您连续处理的每个脚本之后添加对 testWait() 的调用。SpreadsheetApp.flush() 似乎还将电子表格上的超时计时器重置为默认的 5 分钟,因此您有更多时间一次性处理多个脚本。

//holds processing of next script till last one has completed
function testWait(){
  var lock = LockService.getScriptLock(); lock.waitLock(300000); 
  SpreadsheetApp.flush(); lock.releaseLock();
}
于 2017-04-17T01:46:42.817 回答
5

脚本在大约 6 分钟后超时,以防止无限循环和不断运行的程序。我认为没有手动方法可以停止脚本。

编辑:哎呀,忘了回答你的第一个问题:我认为 onEdit 在重新计算值后运行,但显然我没有使用足够的公式来查看这一点。如果它不等待,那么最好的方法是做这样的事情:

while(value === "Thinking..." || value === "#NA") {
  Utilities.sleep(10000);
}

它暂停脚本几秒钟,然后再次检查。

于 2012-10-09T01:01:12.160 回答
3

我还在 Excel VBA 中写了一点,本地的计算函数就派上用场了。我在 Google Apps/Docs 中多次遇到同样的问题,希望在计算完成时执行代码。我想知道为什么 Google Apps/Docs 中没有本机功能来处理这个问题。无论如何,我写了这段代码来解决这个问题。希望能帮助到你。

function onEdit() {

Refresh();

};

function Refresh () {

     var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
     var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");

     // set the range wherever you want to make sure loading is done    

     var range = sheet.getRange('A:A')
     var values = range.getValues();

     var string = values.toString();

     var loading = "Loading";

                    do
                      {var randomWait = Math.floor(Math.random()*1+0); randomWait;}
                    while (string.search(loading) ==! 0);

      range.copyTo(sheet2.getRange('A1'), {contentsOnly:true});

customMsgBox();

};

function customMsgBox() {
  Browser.msgBox("Data refreshed.");
};

这是一个实际示例:
https ://docs.google.com/spreadsheet/ccc?key=0AkK50_KKCI_pdHJvQXdnTmpiOWM4Rk5PV2k5OUNudVE#gid=0

如果您想玩弄它,请制作一个副本。

于 2012-11-17T04:42:51.877 回答
1

我有同样的问题。我使用 2 个脚本解决了这个问题,因为我需要确保电子表格包含我需要的数据。

第一个脚本提供种子值以通过 IMPORTXML 函数填充电子表格。

第二个脚本处理这些数据。

我使用基于时间的触发器来运行脚本,从而为第一个脚本提供足够的时间来完成

于 2020-04-23T09:13:44.853 回答
0

您可以将递归结构放在 code.js 文件中,而不是放在电子表格中。Javascript 可以很好地处理递归。然后,您可以让脚本在每次迭代(或每 100 次)时更新电子表格。

于 2012-10-10T20:05:06.043 回答