使用 Google 表格中的 Google 脚本基于图表 "Start Date" 和 "End Date" 的颜色单元格
Color Cells based on chart "Start Date" and "End Date" using Google Script in Google Sheets
目前,我通过在 google 工作表中使用条件格式来获得此功能的工作版本。不幸的是,我添加的条件越多,性能就越差。我想将我的条件格式转换为每小时运行一次的 google 脚本。
这基本上是一个非常适合我需要的甘特图。
条件格式的公式是
=and(AF>=$L3,AF<=$M3)
其中 L 列是开始日期,M 列是结束日期
Cell AF$2,AG$2,AH2...都是日期,从今天开始,明天,后天等等。
使用 google 脚本的替代方法是什么?
这是我目前所拥有的:
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>=$L3,AF<=$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);
}
您可以将条件格式公式替换为比较两个范围 L3:M
和 AF2: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
class 方法,并以数字方式执行日期比较(使用相等性检查时需要)。根据 method description,window 单元格颜色之外的 null
值用于将背景重置为其默认颜色。可以重写最后一行以消除 offset
调用,但我认为 "AF3"
比 (3, 32, output.length, output[0].length)
.
更容易维护
其他阅读
Array#map
Range#offset
- JavaScript date comparisons
如果要使用的颜色在同一行和已知列中,则无需进行重大更改即可阅读。显然,您需要颜色范围与 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;
...
目前,我通过在 google 工作表中使用条件格式来获得此功能的工作版本。不幸的是,我添加的条件越多,性能就越差。我想将我的条件格式转换为每小时运行一次的 google 脚本。 这基本上是一个非常适合我需要的甘特图。
条件格式的公式是
=and(AF>=$L3,AF<=$M3)
其中 L 列是开始日期,M 列是结束日期
Cell AF$2,AG$2,AH2...都是日期,从今天开始,明天,后天等等。
使用 google 脚本的替代方法是什么? 这是我目前所拥有的:
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>=$L3,AF<=$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);
}
您可以将条件格式公式替换为比较两个范围 L3:M
和 AF2: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
class 方法,并以数字方式执行日期比较(使用相等性检查时需要)。根据 method description,window 单元格颜色之外的 null
值用于将背景重置为其默认颜色。可以重写最后一行以消除 offset
调用,但我认为 "AF3"
比 (3, 32, output.length, output[0].length)
.
其他阅读
Array#map
Range#offset
- JavaScript date comparisons
如果要使用的颜色在同一行和已知列中,则无需进行重大更改即可阅读。显然,您需要颜色范围与 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;
...