簡體   English   中英

是否可以通過搜索列名動態插入條件格式的自定義公式?

[英]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 列為例)。

所以重申一下,我想做的是:

  1. 有一個 function 插入一個新的條件格式規則來突出顯示一行中的重復項
  2. 讓新條件格式的公式是動態的,以防列在數據集之間移動(盡管列名將相同)
  3. 讓這個 function 按名稱而不是數字將條件格式插入到列中

我試圖在 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

提前感謝您的幫助,這對學習如何讓函數按名稱查找列和執行項目非常有用。

您不需要任何代碼,只需使用條件格式公式

=AND(a$1="WOW";countif(A$2:A;a2)>1)

在此處輸入圖像描述

  • 使用您當前的 function 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM