如何使我的 Google Apps 脚本 运行 更快地用于电子表格多色甘特图?

How to make my Google Apps script run faster for spreadsheet multi-color gantt-chart?

我正在将 google sheet 的列和行格式化成一个大甘特图 chart.This 图表是为了显示每个员工为每个项目占用了多少周。每个人都有一个独特的颜色条。颜色条的位置和长度基于项目的开始周和持续时间。我创建了一个 "Update All" 按钮并将函数 update_all() 分配给该按钮。一旦我 运行 这个函数,我想要更新所有的颜色条。

我的脚本运行正常。但是,更新 70 行需要 40 秒,这使得它很难扩展到更大的员工组。耗时最长的操作是将单元格的背景颜色设置为员工指定的颜色。关于如何改进脚本以使其更快的任何建议?

这是甘特图的样子 -- goole sheet 文件 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()]);

  }
  }
 }

我相信你的目标如下。

  • 您想减少脚本的处理成本。

为此,这个答案怎么样?

修改点:

  • 在您的脚本中,循环中使用了 getRangegetValuesetBackground。我认为在这种情况下,脚本的处理成本会很高。为了降低您的脚本成本,我想提出以下流程。在这次修改中,我在你的脚本中修改了Step3

    1. 检索 E3:I121 范围内的所有值。
      • getValues()已使用。
    2. 使用检索到的值创建一个数组来放置颜色。
      • 在这种情况下,您要设置的颜色使用的是您创建的dict_data。并且,没有颜色的单元格设置为null。因此,在您的情况下,ssPlanner.getRange("I4:BU120").setBackground('#ffffff') 可能可以修改为 ssPlanner.getRange("I4:BU120").setBackground(null).
      • getRangegetValuesetBackground 未使用。
    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);

参考文献: