Странное поведение цикла while в скрипте office

#excel #typescript #office-scripts

#excel #typescript #office-скрипты

Вопрос:

Я использую следующий код для обновления ячейки A1, но он не работает:

 function main(workbook: ExcelScript.Workbook) { 

    let worksheet = workbook.getWorksheet("Sheet1");
    var i: number = 0; 

    while (true) {
        worksheet.getRange("A1").setValue(i);
        i = i   1;
    }
}
 

При запуске кода ничего не произошло.

Однако, если я добавлю нерелевантную строку

 console.log("abc")
 

в конце цикла, как вы можете видеть ниже:

 function main(workbook: ExcelScript.Workbook) { 

    let worksheet = workbook.getWorksheet("Sheet1");
    var i: number = 0; 

    while (true) {
        worksheet.getRange("A1").setValue(i);
        i = i   1;
        console.log("abc");
    }
}
 

все будет работать гладко.

Итак, что здесь на самом деле происходит?

Комментарии:

1. Тем не менее, у вас, вероятно, не должно быть бесконечного цикла. Я удивлен, что все работает с ним на месте.

2. Я предполагаю, что при входе в консоль он выполняет ожидающие выполнения инструкции. Таким образом, даже если вы находитесь в бесконечном цикле, при входе в консоль выполняется обновление ячейки A1 здесь. Я бы предположил, что в обычной процедуре это происходит после завершения основной функции. Итак, в вашем первом примере этого не происходит, потому что вы никогда не выходите из бесконечного цикла, и функция никогда не завершается. Но это все предположения с моей стороны.

Ответ №1:

Для повышения производительности Office Scripts публикует результаты вашего скрипта только после «синхронизации» с ним. console.log() это один из способов заставить это, но есть и другие.


Из сценариев Office в Excel> Устранение неполадок> Повышение производительности скрипта (выделение мое):

Удалите ненужные console.log инструкции

Консольное ведение журнала является жизненно важным инструментом для отладки ваших скриптов. Тем не менее, это заставляет скрипт синхронизироваться с рабочей книгой, чтобы обеспечить актуальность зарегистрированной информации. Подумайте об удалении ненужных операторов ведения журнала (например, используемых для тестирования), прежде чем делиться своим скриптом. Обычно это не вызывает заметных проблем с производительностью, если console.log() оператор не находится в цикле.

Аналогично, из статьи Избегайте использования метода context.sync в циклах:

Обычно рекомендуется ставить have final context.sync непосредственно перед закрывающим символом «}» run метода приложения (например Excel.run , Word.run , и т.д.). Это связано с тем, что run метод выполняет скрытый вызов context.sync как последнее, что он делает, если и только если есть команды в очереди, которые еще не были синхронизированы. Тот факт, что этот вызов скрыт, может сбивать с толку, поэтому мы обычно рекомендуем добавить явный context.sync . Однако, учитывая, что эта статья посвящена минимизации вызовов context.sync , на самом деле более запутанным является добавление совершенно ненужного final context.sync . Итак, в этой статье мы оставляем это, когда в конце выполнения нет несинхронизированных команд.

Ваш документ Office обновляется только при синхронизации рабочей книги. Это происходит при context.sync запуске, что происходит неявно в конце вашего скрипта; это также происходит, когда вы выполняете синхронизированную команду, например console.log . Если бы вы сделали свой цикл конечным, а не бесконечным, то ваш скрипт автоматически синхронизировался бы при достижении предела вашего цикла, и ваша рабочая книга соответствующим образом обновлялась бы ровно один раз.

Если вы хотите увидеть частичный прогресс, вы также можете принудительно выполнить обновление в середине вашего скрипта с console.log помощью или context.sync , но вы должны знать, что эти вызовы стоят дорого, и вы можете быть осторожны, чтобы использовать их минимально, как в связанных статьях.

Ответ №2:

Приведенный выше ответ правильный, хотя я хотел бы дать некоторые разъяснения по context.sync . Office Scripts представляет синхронный API, который не требует от пользователя явного выполнения операций синхронизации (и не предоставляет объект контекста). Все последовательные записи действительно собираются и отправляются один раз. В вашем первоначальном примере вы просто добавляете в пакет навсегда. Любая консоль.запись или операция чтения в книгу приведет к принудительной синхронизации, и вы увидите операции записи, которые вы выполнили до этого момента.