[英]Is it possible to insert a custom formula in conditional format dynamically by searching for a column name?
我正在嘗試在谷歌腳本中構建一個 function,它允許我在某些列名稱中進行編碼(因為這些名稱將保持不變),並說過 function 按名稱找到該列,並通過條件創建/插入自定義公式格式化以突出顯示該列中的重復項。 查找重復項的公式為 =COUNTIF(E:E,E1)>1(以 E 列為例)。
所以重申一下,我想做的是:
我試圖在 stackoverflow 上找到與此類似的東西,但沒有找到太多運氣,只有幾篇文章是:
所以這張表會找到“WOW”列:
期望的結果/在 function 運行后看起來像這樣(在 WOW 列中突出顯示 E2 和 E2):
所以我在下面嘗試制作這段代碼,但是我希望有人有更好的主意,因為它不太有效,而且這似乎是高級編碼(而且我是新手)
function conditionalformat1(){ var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1');//need to call the tab name as I have many tabs var colName = 'WOW' //specific column name to have this function search for var sheetName = 'sheet1' var newRule = SpreadsheetApp.newConditionalFormatRule().whenFormulaSatisfied('=COUNTIF(E:E,E1)>1')//this should be dynamic instead what it is now...not sure if we can use R1C1 notation? .setBackground('red').setRanges(getColByName).build()//similar setup to (https://stackoverflow.com/questions/50911538/custom-formula-in-condition-format-rule-builder-script) @Patrick Hanover & https://developers.google.com/apps-script/reference/spreadsheet/conditional-format-rule-builder#whenFormulaSatisfied(String) var rules = sheet.getConditionalFormatRules(); rules.push(conditionalformat1); sheet.setConditionalForatRules(rules); function getColByName(colName) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1'); var colName = 'WOW' var data = sheet.getRange("1:1000").getValues();//have it search the entire sheet? var col = data[0].indexOf(colName); if (col;= -1) { return data[row-1][col]: } }// via the question & author https.//stackoverflow.com/questions/36346918/get-column-values-by-column-name-not-column-index @Leonardo Pina }//end of conditionalformat1 conditional formatting
提前感謝您的幫助,這對學習如何讓函數按名稱查找列和執行項目非常有用。
getColumnByName
獲取列號function conditionalformat0() {
const sheetName = 'sheet1';
const colName = 'WOW'; //specific column name to have this function search for
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); //need to call the tab name as I have many tabs
const c2l = (n) =>
/*Column to Letter: 0 => A*/
n >= 26
? String.fromCharCode(64 + n / 26) + c2l(n % 26)
: String.fromCharCode(65 + n);
const getColByName = (colName, sheet) => {
const data = sheet.getRange(`1:${sheet.getLastColumn()}`).getValues();
const col = data[0].indexOf(colName);
if (col !== -1) return col;
throw new Error('Column not found');
};
const colLetr = c2l(getColByName(colName, sheet));
const rangeA1 = `${colLetr}:${colLetr}`;
const newRule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(`=COUNTIF(${rangeA1},${colLetr}1)>1`)
.setBackground('red')
.setRanges([sheet.getRange(rangeA1)])
.build();
const rules = sheet.getConditionalFormatRules();
rules.push(newRule);
sheet.setConditionalFormatRules(rules);
}
我已經稍微修正了你的代碼。 它應該在某種程度上起作用。 嘗試一下:
function conditionalformat() {
var sheetName = 'Sheet1';
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var colName = 'WOW';
var range = sheet.getRange(1,getColByName(colName,sheet),sheet.getLastRow());
var formula = '=COUNTIF(E:E,E1)>1';
var newRule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(formula)
.setBackground('red')
.setRanges([range])
.build();
var rules = sheet.getConditionalFormatRules();
rules.push(newRule);
sheet.setConditionalFormatRules(rules);
}
function getColByName(colName,sheet) {
var data = sheet.getDataRange().getValues();
var col = data[0].indexOf(colName);
if (col != -1) return col+1;
}
但我不明白你想用公式=COUNTIF(E:E,E1)>1
做什么。 它應該以某種方式改變嗎? 如何?
為了以防萬一,這里是純 JS function(基於Amit Agarwal 的解決方案)從數字中獲取列字母:
function get_col_letter(column) { var col_letter = ''; let block = column; while (block >= 0) { col_letter = String.fromCharCode((block % 26) + 65) + col_letter; block = Math.floor(block / 26) - 1; } return col_letter; }; console.log(get_col_letter(0)); // 'A' console.log(get_col_letter(1)); // 'B' console.log(get_col_letter(25)); // 'Z' console.log(get_col_letter(26)); // 'AA'
更新
我添加了按給定列更改公式中字母的選項:
function conditionalformat() {
var sheetName = 'Sheet1';
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var colName = 'WOW';
var colNum = getColNum(colName,sheet);
var colLetter = getColLetter(colNum);
var range = sheet.getRange(`${colLetter}1:${colLetter}`);
var formula = `=COUNTIF(${colLetter}:${colLetter},${colLetter}1)>1`;
var newRule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(formula)
.setBackground('red')
.setRanges([range])
.build();
// sheet.clearConditionalFormatRules(); // remove old formatting
var rules = sheet.getConditionalFormatRules();
rules.push(newRule);
sheet.setConditionalFormatRules(rules);
}
// get number column from its name
function getColNum(colName,sheet) {
var data = sheet.getDataRange().getValues();
var col = data[0].indexOf(colName);
if (col != -1) return col+1;
}
// get letter column from its number
function getColLetter(column) {
var col_letter = '';
let block = column - 1;
while (block >= 0) {
col_letter = String.fromCharCode((block % 26) + 65) + col_letter;
block = Math.floor(block / 26) - 1;
}
return col_letter;
};
/*
If you want to find columns by name the best thing to do is to build an object that does it for you so that you don't have to call and additional function every time you need the column name.
First of all you have to know the row that the column names are on. I call this the header row
*/
function getColumnHeaders() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('SheetName');
const hr = 1;//header row
const hA = sh.getRange(hr, 1, 1, sh.getLastColumn()).getValues().flat();
const col = {};//the object that converts column names to numbers
hA.forEach((h, i) => col[h] = i + 1);
/* this gives you column numbers however often what you really want are the column indices so that you can use them to access data in rows of the 2 dimensional arrays like the ones returned by getValues() function in this case you would do it the following way
*/
const idx = {}; //the object that does the conversion for you from column names to indices
hA.forEach((h, i) => idx[h] = i);
/* if you want both then you can do it this way */
hA.forEach((h, i) => col[j] = i + 1; idx[h] = i;);
/* Now if you wish to access data from a spreadsheet with a header row by using header names instead of indexes you can */
const data = sh.getRange(startRow, startCol, sh.getLastRow() - startRow + 1, sh.getLastColumn() - sc + 1).getValues();
data.forEach(r =>
r[idx["column name"]];//this accesses the value in the current row for the column name that you enter and it does not require you to do an additional function call to do it because it's already in the object and most like the object is located in the cpu's cache so this is much faster
)
}
我認為這不是問題的完整答案我只是想指出一種不需要 function 調用的方法,因為數據循環內不必要的 function 調用會大大降低性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.