【问题标题】:Color Cells based on chart "Start Date" and "End Date" using Google Script in Google Sheets在 Google 表格中使用 Google 脚本根据图表“开始日期”和“结束日期”为单元格着色
【发布时间】:2018-10-08 21:22:16
【问题描述】:

目前我通过在谷歌表格中使用条件格式有一个工作版本。不幸的是,我添加的条件越多,性能就会降低。我想将我的条件格式转换为每小时运行的谷歌脚本。 这基本上是一个甘特图,非常适合我的需求。

条件格式的公式是

=and(AF$2>=$L3,AF$2<=$M3)

其中 L 列是开始日期,M 列是结束日期

单元格AF$2, AG$2, AH2...是日期,从今天开始,明天开始,后天等等。

使用谷歌脚本的替代方法是什么。 这是我目前所拥有的:

function columnToLetter(column)
{
  var temp, letter = '';
  while (column > 0)
  {
    temp = (column - 1) % 26;
    letter = String.fromCharCode(temp + 65) + letter;
    column = (column - temp - 1) / 26;
  }
  return letter;
}


function setCellBackgrounds() {
  // The name of the sheet to process.
  var sheetName = "MySheet";

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  var range = sheet.getRange("AF3:BJ100");
  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++) {

 //trying to apply the formula "=and(AF$2>=$L3,AF$2<=$M3)" here but I'm getting an error
       if (columnToLetter(32+y)+2 >= columnToLetter(12)+x && columnToLetter(32+y)+2 <= columnToLetter(13)+x ) {
        colors[x][y] = '#999999';
       } else {
         //colors[x][y] = '#ffffff';
       }
    }
  }
  range.setBackgrounds(colors);
}

【问题讨论】:

  • 把错误放在你的问题中。请注意,如果您将值作为数组,则不需要使用字母表示法 - 只需在 2D 数组中偏移适当的量即可。请注意,您需要小心索引不存在的元素(数组是 0-base)
  • 你的意思是值[0][2]之类的东西?如何访问该单元格中的实际值。当我尝试 values[0][2] 或此数组中的任何偏移量时,结果为 null/empty
  • 是的,那是正确的。它是空的,因为 rangeAF3:BJ100 实际上是空的。

标签: google-apps-script google-sheets gantt-chart gs-conditional-formatting


【解决方案1】:

您可以将条件格式公式替换为两个范围的比较,L3:MAF2:BJ2,并将颜色应用于您的输出范围,AF3:BJ

const cols = sheet.getRange("AF2:BJ2").getValues()[0], // Extract the first (& only) row.
      rows = sheet.getRange("L3:M" + sheet.getLastRow()).getValues();

const inWindowColor = "#999999",
      otherColor = null; // null values -> reset color to default.
// Create a rectangular 2D array of color strings. Each row needs an array of colors
// with each inner element corresponding to the given column.
const output = rows.map(function (datePair) {
  var start = datePair[0],
      end = datePair[1];
  return cols.map(function (day) {
    var inWindow = day && start && end // guard against "" values
        && day.getTime() >= start.getTime() && day.getTime() <= end.getTime();
    return (inWindow ? inWindowColor : otherColor);
  });
});

sheet.getRange("AF3").offset(0, 0, output.length, output[0].length)
    .setBackgrounds(output);

上面使用Array#map 类方法,并以数字方式执行日期比较(使用相等检查时需要)。根据method description,为窗口外单元格颜色提供null 值以将背景重置为其默认颜色。可以重写最后一行以消除offset 调用,但我认为"AF3"(3, 32, output.length, output[0].length) 更易于维护。

其他阅读


如果要使用的颜色在同一行和已知列中,则可以在没有显着变化的情况下读取它。显然,您需要颜色范围与rows 范围的大小相同(因为每一行都有相应的颜色)。然后,您只需使用给 Array#map 的第二个自动参数 - 当前元素的索引。这里我展示了一个 2 列的颜色定义范围(“in window”(V)和“ended”(W))

const lastRow = sheet.getLastRow(),
      cols = ...,
      rows = sheet.getRange("L3:M" + lastRow).getValues(),
      colorDefs = sheet.getRange("V3:W" + lastRow).getValues();

const output = rows.map(function (datePair, row) {
  ...
    var color = null;
    if (day && start && end) {
      if (day > end) { // no equality, no `.getTime()` needed
        color = colorDefs[row][1]; // "ended" color is in 2nd index.
      } else if (day.getTime() >= start.getTime()) {
        color = colorDefs[row][0]; // "in window" color is in 1st index.
      } else { /* not started yet */ }
    } else { /* `day`, `start`, and/or `end` were "falsy" */ }
    return color;
 ... 

【讨论】:

  • 哇,第一次尝试就成功了,正是我想要的,谢谢。您能否解释一下有关创建颜色字符串数组的更多信息?我基本上需要它来根据 V 列中该行的值选择不同的颜色。因此,如果 V 列第 13 行是“1”,则将单元格范围着色为红色等。我应该创建另一个范围(3-rd)还是扩展要查看 V 列的第二个范围“行”?
  • 感谢您提供更新的答案。抱歉没有说清楚。看起来您假设列 V 包含颜色,但实际上包含值,例如。 V3=Completed、V4=Pending、V5=Started 等。根据一组定义的单词,我想为 ex 着色(“Completed”范围为红色,Pending 范围为黄色,Started 范围为绿色)
  • 这是一个简单的修改,我会让你处理。第二个示例显示了如何访问同一行中的其他列。您如何处理这些值(例如执行转换 y = f(x))取决于您。
  • 搞定了!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多