Как приостановить скрипты приложения, пока электронная таблица не закончит вычисление
Поскольку электронные таблицы Google не поддерживают итерации, я написал свой собственный простой скрипт приложения, чтобы настроить входные данные на основе расчета выходных данных электронной таблицы. Однако после того, как я изменил входную переменную, электронная таблица пересчитывает, но сценарии приложения, похоже, не ждут этого пересчета, поэтому я в итоге получаю такие значения, как "Мышление..." или "#NA". Есть ли способ приостановить выполнение сценария и дождаться завершения расчета, прежде чем перейти к следующей строке в сценарии?
В настоящее время я просто использую цикл для наблюдения за ячейкой, но я хотел выяснить, существует ли более элегантный способ приостановить выполнение, пока лист не закончил вычисление.
Я пишу много макросов Excel, и Excel VBA всегда ждет завершения вычислений, прежде чем перейти к следующей строке кода. Сценарий приложения, кажется, не делает этого, поэтому я надеюсь, что есть простой способ сделать это.
Второй вопрос: поскольку эта итерация может занять некоторое время, как можно прервать выполнение сценария и прекратить его выполнение? Я не могу найти способ сделать это.
6 ответов
Вот очень простой способ предотвратить запуск следующего сценария, пока текущий сценарий не завершится в сценариях приложений 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();
}
Время ожидания сценариев составляет около 6 минут для предотвращения бесконечных циклов и постоянно работающих программ. Я не думаю, что есть ручной способ остановить сценарий.
Изменить: Ой, забыл ответить на ваш первый вопрос: я думал, что onEdit запускается после пересчета значений, но, видимо, я не использую достаточно формул, чтобы увидеть это. Если это не ожидание, то лучший способ сделать что-то вроде этого:
while(value === "Thinking..." || value === "#NA") {
Utilities.sleep(10000);
}
Он останавливает сценарий на несколько секунд, а затем проверяет снова.
Я также немного пишу в 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
Сделайте копию, если вы хотите поиграть с ней.
У меня такая же проблема. Я решил это, используя 2 сценария, поскольку мне нужно было убедиться, что в электронной таблице есть нужные мне данные.
Первый сценарий предоставляет начальное значение для заполнения электронной таблицы с помощью функции IMPORTXML.
Второй скрипт обрабатывает эти данные.
Я использовал триггеры на основе времени для запуска сценариев, давая достаточно времени для завершения первого сценария.
Вы можете поместить рекурсивную структуру в файл code.js, а не в электронную таблицу. Javascript действительно хорошо справляется с рекурсией. Затем вы можете сделать так, чтобы скрипт обновлял электронную таблицу на каждой итерации (или каждые 100).
теперь вы можете использовать SpreadsheetApp.flush(). Я обнаружил это по этой ссылке здесь.