Страницы

Поиск по вопросам

четверг, 2 апреля 2020 г.

28.02.2018 перестала работать функция “Вставить результат вычисления формулы как значения”

#google_spreadsheet #google_apps_script

                    
Именно сегодня перестала работать функция - вставить результат вычисления формулы
как значения. (В Google Apps Scripts, Google Spreadsheets). На сейчас эта функция работает
как clearContents() - просто затирает все значения.

Пример:

function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet()
  var sheet = ss.getActiveSheet()
  var range = sheet.getRange("A1:C3")
  range.setFormula("=1+2")

  range.copyTo(range, {contentsOnly:true})
  //Или так:
  //range.copyValuesToRange(sheet, range.getColumn(), range.getLastColumn(), range.getRow(),
range.getRowIndex())
  //range.copyTo(range, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false)
}


Можно использовать другие методы, поколдовав с форматами, но почему же перестало
работать??

range.setValue(range.getValues())
range.setValue(range.getDisplayValues())

    


Ответы

Ответ 1



Вдруг кому интересно будет не смотря на минусовой вопрос: Необходимо добавить перед range.copyTo(range, {contentsOnly:true}) SpreadsheetApp.flush() Согласно документации, этот метод применяет все ожидающие изменения в таблице Applies all pending Spreadsheet changes. То есть, как я понимаю, ранее, при вызове copyTo, google перед тем, как брать данные из ячеек, сам применял все изменения (высчитывал результаты формул), а после этого уже делал копирование. Сейчас же нужно этот момент задавать вручную. UPD1: Согласно комментарию oshliaer, можно и Sheets API использовать. Насколько я понимаю, код будет где-то такой: // ss = SpreadsheetApp.getActiveSpreadsheet() // sheet = ss.getSheetByName("NAME") //Для примера: range = sheet.getRange("A1:C") function killAllFormulas2(ss, sheet, range) { // Обязателен вызов flush(), иначе если вы только вставили сложные формулы и сразу захотели вставить результаты вычисления как значения - они могут не успеть обновить данные в ячейках SpreadsheetApp.flush() // Получаем ID вашего Spreadsheet var ssID = ss.getId() // Если выбран такой диапазон как в примере - его обязательно нужно перевести в вид A1:C1000 (условно) var rangeA1 = sheet.getRange(range.getRow(), range.getColumn(), range.getLastRow()-range.getRow()+1, range.getLastColumn()-range.getColumn()+1).getA1Notation() // Получаем значения var values = Sheets.Spreadsheets.Values.get(ssID, sheet.getName() + "!" + rangeA1) // Вставляем значения Sheets.Spreadsheets.Values.update(values, ssID, sheet.getName() + "!" + rangeA1, {valueInputOption:"USER_ENTERED"}) } В примерах, которые встречаются вот здесь указано, что для большинства случаев использования лучше использовать стандартные методы встроенного SpreadsheetApp (например цитата для записи данных: This code uses the Sheets Advanced Service, but for most use cases the built-in method SpreadsheetApp.getActiveSpreadsheet().getRange(range).getValues(values) is more appropriate. По скорости работы я проверял на некоторых диапазонах со сложными формулами - разницы вообще не увидел. Скорее всего это все один и тот же алгоритм. Надеюсь, этот ответ поможет кому-то не тратить драгоценное время на поиски истины.

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

Отправить комментарий