如何清除 Google Apps 脚本中的条件格式(不是所有格式)

How to clear conditional formatting (not all formatting) in Google Apps script

我需要一种通过 运行 脚本删除所有条件格式的方法(我的客户将使用这个,他不想重复删除每个工作表中每个工作表的条件格式的过程大量电子表格文件)。

有什么方法可以通过 Google Apps 脚本来做到这一点吗?我只看到.clearFormat(),不幸的是,它清除了所有格式,其中很多不应该被删除(例如,字体颜色、背景颜色、字体、字体粗细、字体旋转、单元格轮廓)

如何做到每个电子表格文件只需要按一个按钮?

这可以通过 Google Sheets API v4, which Apps Script can access via Advanced Sheets Service 实现(请注意,在使用前必须启用它,如链接页面的指示)。这是一个脚本,用于删除当前跨页 sheet 的 Sheet1 中的所有条件格式规则(您需要循环遍历 sheet 等)。

function clearSheet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var ssId = ss.getId();
  var sheet = ss.getSheetByName("Sheet1");
  var sheetId = sheet.getSheetId(); 
  var format_req = {
    "requests": [{
      "deleteConditionalFormatRule": { 
        "index": 0,
        "sheetId": sheetId
      }
    }]
  };
  var string_req = JSON.stringify(format_req);
  while (true) {
    try {
      Sheets.Spreadsheets.batchUpdate(string_req, ssId);
    }
    catch(e) {
      break;
    }
  }
}

每个条件格式规则都有一个从 0 开始的 "index"。删除索引为 0 的规则会导致其他索引减少 1。因此循环会继续删除索引 = 0 的规则,直到没有规则为止,并引发错误(并被捕获,退出循环)。

这是一种奇怪的发送请求方式:我更愿意像这样发送一个批处理请求:

  var format_req = {
    "requests": [
    {
      "deleteConditionalFormatRule": { 
        "index": 0,
        "sheetId": sheetId
      }
    },
    {
      "deleteConditionalFormatRule": { 
        "index": 1,
        "sheetId": sheetId
      }
    }]
  };

但要做到这一点,必须知道有多少条件格式规则(我不知道如何找到)。如果您请求删除的规则多于 sheet 中存在的规则,则整个请求将失败并且不会删除任何内容。

没有高级服务

对于普通的 Apps 脚本,最好的做法是:

  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns());
  var backgrounds = range.getBackgrounds(); 
  var fontColors = range.getFontColor(); 
  var fontFamilies = range.getFontFamilies();
  // ... other get methods from https://developers.google.com/apps-script/reference/spreadsheet/range 

  // tricky part: modify the backgrounds, replacing the colors used in conditional formatting by white 

  range.clearFormat();
  range.setBackgrounds(backgrounds)
       .setFontColors(fontColors)
       .setFontFamilies(fontFamilies)
    // .set  other things

这里我假设条件格式只影响单元格背景。如果无法过滤背景色(这需要确切知道条件格式规则中使用的颜色),条件格式的效果将变成普通的背景色,这是非常不可取的......最好放弃设置根本没有背景颜色。

所以在我对 if....

发表评论之后

but to do this, one must know how many conditional formatting rules are there (and I don't see how one would find out)

决定扩展他的代码:

function get_clear_Formatting() {

 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var ssId = ss.getId();

// 1 部分 - 获取活动电子表格中所有工作表的条件格式数据

 var params = {
  'fields': "sheets(properties(title,sheetId),conditionalFormats)"
 };

 var getFormatResult = Sheets.Spreadsheets.get(
   ssId,
   params
 );

  var sheets = getFormatResult.sheets;

  var ConditionalFormatIndex = {
      "sheetID" : [],
      "sheetTitle" : [],
      "formatRulesCount" : []
      }

  for (var i = 0; i < sheets.length; i++) {
    ConditionalFormatIndex.sheetID[i]          = sheets[i].properties.sheetId;
    ConditionalFormatIndex.sheetTitle[i]       = sheets[i].properties.title
    ConditionalFormatIndex.formatRulesCount[i] = (sheets[i].conditionalFormats) ?
                                                  sheets[i].conditionalFormats.length :
                                                  0;
  }

// 2 部分 - 清除活动电子表格中所有工作表中的所有条件格式

  var ClearFormat_req = []

  for (var i = 0; i < ConditionalFormatIndex.sheetID.length; i++) {
    if ( ConditionalFormatIndex.formatRulesCount[i] ) {
      for (var cf = 0; cf < ConditionalFormatIndex.formatRulesCount[i]; cf++) {

        ClearFormat_req.push(
          {
            "deleteConditionalFormatRule": { 
              "index": 0,
              "sheetId": ConditionalFormatIndex.sheetID[i]
            }
          }); 
      }
    };  
  }

  Sheets.Spreadsheets.batchUpdate({'requests': ClearFormat_req}, ssId);

}

Google Apps 脚本现在支持使用 clearConditionalFormatRules

删除条件格式
var sheet = SpreadsheetApp.getActiveSheet();
sheet.clearConditionalFormatRules();

https://developers.google.com/apps-script/reference/spreadsheet/sheet#clearconditionalformatrules

  1. 复制没有任何条件格式的单元格。
  2. Select 您要从中删除条件格式的单元格。
  3. 编辑 -> 选择性粘贴 -> 仅粘贴条件格式。

有点晚了,但我找到了一个方法,如果这对某人有帮助的话。 删除与参数中的范围相交的所有条件格式 然后保持所有其他条件格式不变(实际上:重建它)。

function test(){

  var sh=shWork;//define your sheet
  var r= sh.getRange("A3:A6");//example
  clearEveryConditionalFormattingOnRange(sh,r)

}

function clearEveryConditionalFormattingOnRange(sh,r){  
  //build a parallel rules at looping on initial rule, in order to rebuild it without unwanted elements

  //get rules
  var rules=sh.getConditionalFormatRules();

  //create new rules
  var a_newRules= new Array();

  //loop on rules
  for (var i=0;i<rules.length;i++){

    //create new currentRanges
    var a_newCurrentRanges=new Array();

    //loop on ranges from rule
    var currentRule=rules[i];
    var currentRanges=currentRule.getRanges();
    for (var j=0;j<currentRanges.length;j++){

      var currentRange=currentRanges[j];
      var testIfIntersect_OK=RangeIntersect(r,currentRange);

      //add this range to a_newCurrentRanges
      if (!testIfIntersect_OK){        
        a_newCurrentRanges.push(currentRange);        
      }//if (testIfIntersect_OK){

    }//for (var j=0;j<currentRanges.length;j++){

    //create then add new rule to a_newRules
    if (a_newCurrentRanges.length>0){

      var a_newRule = SpreadsheetApp.newConditionalFormatRule()
      .whenFormulaSatisfied(currentRule.getBooleanCondition().getCriteriaValues())
      .setBackground(currentRule.getBooleanCondition().getBackground())
      .setRanges(a_newCurrentRanges)
      .build();     
      a_newRules.push(a_newRule);

    }//if (a_newCurrentRanges.length>0){

  }//for (var i=0;i<rules.lengthi++){

  sh.setConditionalFormatRules(a_newRules);

}

//returns true if intersection between range1 and range2
function RangeIntersect(R1, R2) {

  var LR1 = R1.getLastRow();
  var Ro2 = R2.getRow();
  if (LR1 < Ro2) return false;


  var LR2 = R2.getLastRow();
  var Ro1 = R1.getRow();
  if (LR2 < Ro1) return false;

  var LC1 = R1.getLastColumn();
  var C2 = R2.getColumn();
  if (LC1 < C2) return false;

  var LC2 = R2.getLastColumn();
  var C1 = R1.getColumn();
  if (LC2 < C1) return false;

  return true;

}

我最终根据 David Friedman 的回答找到了解决方案。此脚本仅从一列 (D) 中成功删除了条件格式,而其他列中的条件格式保持不变。

// clearConditionalFormat
// Data must have header row that does NOT have conditional formatting
// Otherwise you must identify some other cell on the sheet that does not 
//                 have conditional formatting

function test(){
var sheetName = "Sheet13";   // replace with your sheet's name
var rangeText = "D3:D";      // replace with the your range
clearConditionalFormat(rangeText,sheetName);
};


function clearConditionalFormat(rangeText,sheetName){
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var rangeText = rangeText.toString().toUpperCase();
var range =  ss.getRange(rangeText).activate();

var rangeTextSplit = rangeText.split(":");               
     // example: returns  AA22 from AA22:AZ37
var rangeFirstLetter = rangeTextSplit[0].replace(/[0-9]+/g, ""); 
    // example: returns  AA from AA22
var rangeRowNum1 = rangeTextSplit[0].replace(/[A-Z]+/g, "")*1; 
    // example: returns the 22 of AA22:AZ37
var rangeHeaderText = rangeFirstLetter + (rangeRowNum1 - 1);

sheet.getRange(rangeHeaderText)
    .copyTo(range,SpreadsheetApp.CopyPasteType
    .PASTE_CONDITIONAL_FORMATTING, false);
 };