Как ускорить работу моего скрипта Google Apps для многоцветной диаграммы Ганта в виде электронных таблиц? - PullRequest
1 голос
/ 20 июня 2020

Я форматирую столбцы и строки таблицы Google в большую диаграмму Ганта. Эта диаграмма показывает, сколько недель каждый сотрудник занят для каждого проекта. У каждого человека есть уникальная цветовая полоса. Положение и длина цветной полосы зависят от начальной недели и продолжительности проекта. Я создал кнопку «Обновить все» и назначил ей функцию update_all (). После запуска этой функции я хочу, чтобы все цветные полосы были обновлены.

Мой скрипт работает нормально. Однако обновление 70 строк занимает 40 секунд, что затрудняет масштабирование для более крупной группы сотрудников. Действие, которое занимает больше всего времени, - это установить цвет фона ячеек с назначенным цветом сотрудника. Есть какие-нибудь советы, как улучшить скрипт, чтобы он работал быстрее?

Вот как выглядит диаграмма Ганта - файл таблицы goole https://docs.google.com/spreadsheets/d/1nvnZB62CYUeUUZSkAuHsxMJF5MBr7D1rNG3ffU8jKdI/edit?usp=sharing

Вот мой код

function updateall(){

     var sss = SpreadsheetApp.openById("1nvnZB62CYUeUUZSkAuHsxMJF5MBr7D1rNG3ffU8jKdI");
  var ssColor = sss.getSheetByName("2. Color Legend");
  var ssPlanner = sss.getSheetByName("Project Planner");

  // Step 1: clear all the orginal color 
  ssPlanner.getRange("I4:BU120").setBackground('#ffffff');

  // Step 2: create a dictionay {staff name : coloe code}
   var keycolumns = ssColor.getRange(3,2,16,1).getValues();
  var data = ssColor.getRange(3,3,16,1).getValues();
  var dict_data = {};
  for (var keys in keycolumns) {
    var key = keycolumns[keys];
    dict_data[key] = data[keys];
  }

  Logger.log(dict_data["BBB"]);

  //Step3:set background color for each row
    for (var bRow=4; bRow<121; bRow++){
    if (ssPlanner.getRange("E"+bRow).getValue()!=""){

    var start = ssPlanner.getRange(bRow,7).getValue()-ssPlanner.getRange(3,9).getValue()+9;
    var duration = ssPlanner.getRange(bRow,8).getValue();

  ssPlanner.getRange(bRow,start,1,duration).setBackground(dict_data[ssPlanner.getRange(bRow,5).getValue()]);

  }
  }
 }

1 Ответ

1 голос
/ 21 июня 2020

Я считаю, что ваша цель следующая.

  • Вы хотите снизить стоимость процесса вашего скрипта.

Для этого, как насчет этого ответа?

Точки модификации:

  • В вашем скрипте getRange, getValue и setBackground используются в l oop. Думаю, что в этом случае стоимость процесса скрипта будет высокой. Чтобы снизить стоимость вашего скрипта, я хотел бы предложить следующую схему. В этой модификации я изменил Step3 в вашем скрипте.

    1. Получить все значения из диапазона E3:I121. Используется
      • getValues().
    2. Создайте массив для размещения цветов с использованием полученных значений.
      • В этом случае цвет, который вы хотите установить, используется из dict_data, созданного вами. И ячейки, у которых нет цветов, устанавливаются как null. Таким образом, в вашем случае ssPlanner.getRange("I4:BU120").setBackground('#ffffff') можно изменить на ssPlanner.getRange("I4:BU120").setBackground(null).
      • getRange, getValue и setBackground не используются.
    3. Установите цвета, используя созданный массив, включая цветовые коды. Используется
      • setBackgrounds.

Когда указанный выше поток отражается в вашем скрипте, он становится следующим:

Измененный скрипт:

Когда ваш скрипт изменен, пожалуйста, измените следующее.

От:
//Step3:set background color for each row
  for (var bRow=4; bRow<121; bRow++){
  if (ssPlanner.getRange("E"+bRow).getValue()!=""){

  var start = ssPlanner.getRange(bRow,7).getValue()-ssPlanner.getRange(3,9).getValue()+9;
  var duration = ssPlanner.getRange(bRow,8).getValue();

ssPlanner.getRange(bRow,start,1,duration).setBackground(dict_data[ssPlanner.getRange(bRow,5).getValue()]);

}
}
Кому:
// Step3:set background color for each row
// 1. Retrieve all values from the range of `E3:I121`.
const values = ssPlanner.getRange("E3:I121").getValues();
const offset = values.shift()[4];

// 2. Create an array for putting the colors using the retrieved values.
const colors = values.reduce((ar, [e,f,g,h]) => {
  let base = Array(65).fill(null);
  if (e != "") Array.prototype.splice.apply(base, [g - offset, h].concat(Array(h).fill(dict_data[e][0])));
  ar.push(base);
  return ar;
}, []);

// 3. Set the colors using the created array including the color codes.
ssPlanner.getRange(4, 9, colors.length, colors[0].length).setBackgrounds(colors);

Ссылки:

...