Сценарий Google Apps - Листы - Условное форматирование - X = выделение - PullRequest
0 голосов
/ 30 мая 2018

У меня есть лист с более чем 100 000 ячеек (скоро будет более 300 000 ячеек), используемый в качестве диаграммы Ганта.Каждая ячейка имеет формулу IF, которая возвращает букву X, если заголовок соответствующего столбца (дата) находится между датой начала и окончания строки.

Но то, что существенно замедляет лист, - это условное форматирование.Условное форматирование говорит, что если значением ячейки является X, то измените цвет фона ячейки и цвет шрифта на зеленый.Если нет X, цвет фона должен быть белым.Поскольку условное форматирование, насколько я понимаю, пересчитывается каждый раз, когда вы вносите какие-либо изменения в лист, производительность существенно ухудшается.Поэтому я решил удалить условное форматирование и добавить его в виде сценария с помощью кнопки меню, которую я могу щелкнуть в любое время, когда захочу, чтобы он запускался, в отличие от условного форматирования, запускаемого каждый раз, когда я выполняю редактирование листа.

Вот где я получил сценарий, который не работает.Я попробовал пару десятков вариантов этого, но не могу найти то, что работает - иногда я запускаю его без ошибок, иногда возникает ошибка.Мой контекст где-то неверен?

function formatting() {

  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
  var range = ss.getRange("A1:A100");
  var cellValue = range.getValues();
  if (cellValue === 'X') {
    ss.range.setBackgroundColor('#000000'); }
  else {
    cellValue.setBackgroundColor('#ffffff'); }
}

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Вот подход с использованием пакетной функции Range.setBackgrounds () .Эта функция принимает двумерный массив значений в качестве аргумента, позволяя вам установить все фоновые ячейки для диапазона в одном вызове API.

Также обратите внимание, что функция Range.getValues ​​() возвращает двумерный массив значений.Для проверки каждого отдельного значения ячейки вам нужно пройтись по массивам.

Поскольку вы имеете дело с двумерным массивом как с входом, так и с выходом, логика для построения выходного массива фоновых значений отражает логику, которую вы должны использовать для проверки текущих значений ячеек.Таким образом, вы можете построить двумерный массив значений фона, пока вы просматриваете значения ячеек.

function setCellBackgrounds() {
  // The name of the sheet to process.
  var sheetName = "Sheet1";
  // The range of cells to inspect.
  var range = "A1:Z100";

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  var range = sheet.getRange(range);
  var values = range.getValues();
  var colors = [];
  for (var x = 0; x < values.length; x++) {
    colors[x] = [];
    for (var y = 0; y < values[x].length; y++) {
       if (values[x][y] == 'X') {
         colors[x][y] = '#999999';
       } else {
         colors[x][y] = '#ffffff';
       }
    }
  }
  range.setBackgrounds(colors);
}

Использование пакетных функций вместо повторных вызовов не-пакетной версии является документированнымЛучшая практика для скриптов приложений .

0 голосов
/ 30 мая 2018

Как уже упоминалось здесь , вы неправильно ссылаетесь на чек.Однако использование setBackground на самом деле не поддается даже 100 ячейкам, а тем более 1000 или 300 000.Вам будет необходимо использовать пакетный метод Range#setBackgrounds() с «2D» массивом цветов фона, которые вы хотите применить.

Вы можете еще больше сократить потребность в массивном APIиспользуя подробные сведения о приложении, касающиеся построения и работы электронной таблицы Ганта, чтобы уменьшить изменяемые диапазоны.Возможно, X могут появляться или исчезать только в только что отредактированной ячейке, или, возможно, они заполняются только слева направо или сверху вниз и т. Д.

Эта функция предполагает худшее-case - при каждом вызове необходим полный пересчет цветов фона.

function greenify() {
  const sheet = SpreadsheetApp.getActive().getSheetByName("Gantt");
  const HAS_X = "green", NO_X = null;
  const dr = sheet.getDataRange();
  const colors = dr.getBackgrounds();
  const VALUES = dr.getValues();

  // Inspect the value array and modify the corresponding index in colors.
  for (var r = 0, rows = VALUES.length; r < rows; ++r)
    for (var c = 0, cols = VALUES[0].length; c < cols; ++c)
      colors[r][c] = (VALUES[r][c] === "X") ? HAS_X : NO_X;

  // Write the output.
  dr.setBackgrounds(colors);
}

Если необходимо учитывать только что измененную ячейку, я рекомендую использовать простой "триггер.«

0 голосов
/ 30 мая 2018
  • cellValues - двумерный массив;каждая клетка должна быть проверена на наличие X.Запустите его в цикле, чтобы получить (x, y) тестируемого элемента.
  • Ни ss.range, ни cellValue не могут быть использованы для установки фона.Это должно быть ss.getRange(x, y).setBackground... с использованием координат (x, y) для указания X ed ячейки.

Не проверял это, но это должно работать:

function formatting() {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
  var range = ss.getRange("A1:A100");
  for (var x = 0; x < range.length; x++) {
    for (var y = 0; x < range[0].length; y++) {
      if (cellValue == 'X') {
        ss.getRange(x, y).setBackgroundColor('#000000');
      } else {
        ss.getRange(x, y).setBackgroundColor('#ffffff');
      }
    }
  }
}

Хотя это может быть то, что вы ищете, есть проблемы со скоростью.Другим способом было бы просто добавить / удалить правило при желании.Это может быть сделано программно с помощью ConditionalFormatRule, если слишком часто приходится часто воссоздавать вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...