条件格式化脚本 - 设置迭代
Conditional formatting script - set iteration
我有一个条件格式规则的自定义公式。我正在尝试编写一个脚本来检查列('Mine' sheet 上的 B 列)上的多个值(大约 50 个)以及单元格是否等于特定字符串(M1、M2 或M3) 然后将指定的条件格式公式应用于 "Calendar view" sheet。我目前的代码是:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Calendar View");
sheet.getRange("C4:NC50").clearFormat();
var range = sheet.getRange("C4:NC4");
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=AND(indirect("Mine!$B5")="M1", C>=indirect("Mine!$C5"), C<indirect("Mine!$D5"))')
.setBackground("#FF0000")
.setRanges([range])
.build();
var rules = sheet.getConditionalFormatRules();
rules.push(rule);
sheet.setConditionalFormatRules(rules);
}
如何在.whenFormulaSatisfied上输入迭代方法,例如:
.whenFormulaSatisfied('=AND(indirect("Mine!$B6")="M1", C>=indirect("Mine!$C6"), C<indirect("Mine!$D6"))')
.whenFormulaSatisfied('=AND(indirect("Mine!$B7")="M1", C>=indirect("Mine!$C7"), C<indirect("Mine!$D7"))')
.whenFormulaSatisfied('=AND(indirect("Mine!$B8")="M1", C>=indirect("Mine!$C8"), C<indirect("Mine!$D8"))')
............
这是我正在研究的sheet:
https://docs.google.com/spreadsheets/d/1Af84aHaG0VjXmtaWc0-uAdGFrX1LozRNLQLMatSOqgU/edit?usp=sharing
提问者的方法有一些挑战 - 首先,每个 属性 的开始和结束日期的动态识别,其次,创建多达 50 个单独的条件格式规则。众所周知,电子表格性能受条件格式规则数量的影响。
我建议采用稍微不同的方法。
1) 获取我的数据并构建日历。
2) 在预订日期字段中放置值。
3) 为日历应用 单一 条件格式规则。
确定预订日期的方法是在相应的单元格中插入标称值。然后应用规则 .whenCellNotEmpty()
而不是指定特定值。此外,代码还设置了背景和字体颜色的格式,以便隐藏任何数据。
另请注意:在脚本的开头,代码删除了内容和格式。
function so_53185335() {
// build the spreadsheet app and set source and target sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var calSheet = ss.getSheetByName("Calendar View");
var dataSheet = ss.getSheetByName("Mine");
// get the last rows and start rows for both sheets
var lrMine = dataSheet.getLastRow();
var lrCal = calSheet.getLastRow();
var dataRowStart = 5;
var calRowStart = 4;
// clear formats and data from Calendar
calSheet.getRange(calRowStart, 2, lrCal, 366).clear({
contentsOnly: true,
formatOnly: true
});
// get Mine rows with data, define the range and get data
var dataRows = lrMine - dataRowStart + 1;
//Logger.log("Mine: number of data rows "+dataRows);// DEBUG
var dataRange = dataSheet.getRange(dataRowStart, 2, dataRows, 3);
//Logger.log("data range is "+dataRange.getA1Notation());// DEBUG
var dataValues = dataRange.getValues();
//set some variables for use in loop
var i = 0; // counter
var z = 0; // counter
var calstartCol = 3; // equals first day of the year
var calrow = 0; // counter row for Calendar sheet
var calArray = [];
var masterArray = [];
// loop through the rows in Mine
for (i = 0; i < dataRows; i++) {
// test for value
if (dataValues[i][0] === "M1" || dataValues[i][0] === "M2" || dataValues[i][0] === "M3") {
//Logger.log("Match: i="+i+", value = "+dataValues[i][0]);//DEBUG
calArray = [];
masterArray = [];
calrow = calrow + 1;
// calculate the start day (as a day in the year)
var now = new Date(dataValues[i][1]);
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var startday = Math.floor(diff / oneDay);
// calculate the end day (as a day in the year)
var fnow = new Date(dataValues[i][2]);
var fstart = new Date(fnow.getFullYear(), 0, 0);
var fdiff = (fnow - fstart) + ((fstart.getTimezoneOffset() - fnow.getTimezoneOffset()) * 60 * 1000);
var foneDay = 1000 * 60 * 60 * 24;
var endday = Math.floor(fdiff / foneDay);
var nod = endday - startday + 1;
// assign the value for the Property
var cell = calSheet.getRange(calstartCol + calrow, 2);
cell.setValue(dataValues[i][0]);
// create an array of values for booked dates; just insert the number "1"
for (z = 1; z < nod + 1; z++) {
calArray.push(1);
}
masterArray.push(calArray);
// Assign the values for booked dates
var cell = calSheet.getRange(calstartCol + calrow, startday + 2, 1, nod);
cell.setValue(masterArray);
}
}
// create and apply a single Conditional forma rule for the data range on Calendar
var range = calSheet.getRange(calRowStart, calstartCol, calstartCol + calrow, 366);
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenCellNotEmpty()
.setFontColor("#FF0000")
.setBackground("#FF0000")
.setRanges([range])
.build();
var rules = calSheet.getConditionalFormatRules();
rules.push(rule);
calSheet.setConditionalFormatRules(rules);
}
日历看起来像这样。
我有一个条件格式规则的自定义公式。我正在尝试编写一个脚本来检查列('Mine' sheet 上的 B 列)上的多个值(大约 50 个)以及单元格是否等于特定字符串(M1、M2 或M3) 然后将指定的条件格式公式应用于 "Calendar view" sheet。我目前的代码是:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Calendar View");
sheet.getRange("C4:NC50").clearFormat();
var range = sheet.getRange("C4:NC4");
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=AND(indirect("Mine!$B5")="M1", C>=indirect("Mine!$C5"), C<indirect("Mine!$D5"))')
.setBackground("#FF0000")
.setRanges([range])
.build();
var rules = sheet.getConditionalFormatRules();
rules.push(rule);
sheet.setConditionalFormatRules(rules);
}
如何在.whenFormulaSatisfied上输入迭代方法,例如:
.whenFormulaSatisfied('=AND(indirect("Mine!$B6")="M1", C>=indirect("Mine!$C6"), C<indirect("Mine!$D6"))')
.whenFormulaSatisfied('=AND(indirect("Mine!$B7")="M1", C>=indirect("Mine!$C7"), C<indirect("Mine!$D7"))')
.whenFormulaSatisfied('=AND(indirect("Mine!$B8")="M1", C>=indirect("Mine!$C8"), C<indirect("Mine!$D8"))')
............
这是我正在研究的sheet: https://docs.google.com/spreadsheets/d/1Af84aHaG0VjXmtaWc0-uAdGFrX1LozRNLQLMatSOqgU/edit?usp=sharing
提问者的方法有一些挑战 - 首先,每个 属性 的开始和结束日期的动态识别,其次,创建多达 50 个单独的条件格式规则。众所周知,电子表格性能受条件格式规则数量的影响。
我建议采用稍微不同的方法。
1) 获取我的数据并构建日历。
2) 在预订日期字段中放置值。
3) 为日历应用 单一 条件格式规则。
确定预订日期的方法是在相应的单元格中插入标称值。然后应用规则 .whenCellNotEmpty()
而不是指定特定值。此外,代码还设置了背景和字体颜色的格式,以便隐藏任何数据。
另请注意:在脚本的开头,代码删除了内容和格式。
function so_53185335() {
// build the spreadsheet app and set source and target sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var calSheet = ss.getSheetByName("Calendar View");
var dataSheet = ss.getSheetByName("Mine");
// get the last rows and start rows for both sheets
var lrMine = dataSheet.getLastRow();
var lrCal = calSheet.getLastRow();
var dataRowStart = 5;
var calRowStart = 4;
// clear formats and data from Calendar
calSheet.getRange(calRowStart, 2, lrCal, 366).clear({
contentsOnly: true,
formatOnly: true
});
// get Mine rows with data, define the range and get data
var dataRows = lrMine - dataRowStart + 1;
//Logger.log("Mine: number of data rows "+dataRows);// DEBUG
var dataRange = dataSheet.getRange(dataRowStart, 2, dataRows, 3);
//Logger.log("data range is "+dataRange.getA1Notation());// DEBUG
var dataValues = dataRange.getValues();
//set some variables for use in loop
var i = 0; // counter
var z = 0; // counter
var calstartCol = 3; // equals first day of the year
var calrow = 0; // counter row for Calendar sheet
var calArray = [];
var masterArray = [];
// loop through the rows in Mine
for (i = 0; i < dataRows; i++) {
// test for value
if (dataValues[i][0] === "M1" || dataValues[i][0] === "M2" || dataValues[i][0] === "M3") {
//Logger.log("Match: i="+i+", value = "+dataValues[i][0]);//DEBUG
calArray = [];
masterArray = [];
calrow = calrow + 1;
// calculate the start day (as a day in the year)
var now = new Date(dataValues[i][1]);
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var startday = Math.floor(diff / oneDay);
// calculate the end day (as a day in the year)
var fnow = new Date(dataValues[i][2]);
var fstart = new Date(fnow.getFullYear(), 0, 0);
var fdiff = (fnow - fstart) + ((fstart.getTimezoneOffset() - fnow.getTimezoneOffset()) * 60 * 1000);
var foneDay = 1000 * 60 * 60 * 24;
var endday = Math.floor(fdiff / foneDay);
var nod = endday - startday + 1;
// assign the value for the Property
var cell = calSheet.getRange(calstartCol + calrow, 2);
cell.setValue(dataValues[i][0]);
// create an array of values for booked dates; just insert the number "1"
for (z = 1; z < nod + 1; z++) {
calArray.push(1);
}
masterArray.push(calArray);
// Assign the values for booked dates
var cell = calSheet.getRange(calstartCol + calrow, startday + 2, 1, nod);
cell.setValue(masterArray);
}
}
// create and apply a single Conditional forma rule for the data range on Calendar
var range = calSheet.getRange(calRowStart, calstartCol, calstartCol + calrow, 366);
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenCellNotEmpty()
.setFontColor("#FF0000")
.setBackground("#FF0000")
.setRanges([range])
.build();
var rules = calSheet.getConditionalFormatRules();
rules.push(rule);
calSheet.setConditionalFormatRules(rules);
}
日历看起来像这样。