【问题标题】:How to clear conditional formatting (not all formatting) in Google Apps script如何清除 Google Apps 脚本中的条件格式(不是所有格式)
【发布时间】:2017-07-25 01:31:59
【问题描述】:

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

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

如何做到这一点,使得每个电子表格文件只需按下一个按钮?

【问题讨论】:

    标签: google-apps-script google-sheets gs-conditional-formatting


    【解决方案1】:

    Google Apps 脚本现在支持使用 clearConditionalFormatRules 删除条件格式

    var sheet = SpreadsheetApp.getActiveSheet();
    sheet.clearConditionalFormatRules();
    

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

    【讨论】:

    • 很高兴知道。我正在从事的项目有点晚了,但我相信这些知识在某些时候会派上用场。希望我在一年前就有这个选择......
    • 工作出色。只需转到要使用它的工作表上的工具 -> 脚本编辑器,然后粘贴此代码并点击“运行”。保持常规单元格格式不变,仅删除条件格式,正是我需要避免手动删除数百条规则!
    【解决方案2】:

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

    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 开始的“索引”。删除索引为 0 的规则会导致其他索引减少 1。因此循环继续删除 index = 0 规则,直到没有规则,并引发错误(并被捕获,退出循环)。

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

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

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

    没有高级服务

    使用普通的 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
    

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

    【讨论】:

    • 谢谢,亚历克斯。我自己只是在研究它,几乎让它工作了,但很难找到条件格式规则的数量,我想这是不知道的。您处理不知道的解决方案效果很好,但不幸的是我不确定我是否可以使用它,因为我的客户将是使用此脚本的客户,我无权访问所有电子表格来打开 Sheets API他。我认为没有高级服务绝对没有办法做到这一点?
    • 没有高级服务的最好方法是获取条件格式不使用的参数(getFontWeights、getFontStyles等),应用clearFormat然后恢复(setFontWeights...)。如果您所有的条件格式都在单元格背景中,那么其余的将继续存在。
    • 这将是一个很好的方法,但对于我的特定用例,这很遗憾不起作用(格式包括旋转 45 度的文本、带有轮廓的单元格等)。我会接受你的回答,因为我认为它适用于大多数人/情况。谢谢!
    • “但要做到这一点,必须知道有多少条件格式规则(我不知道如何找到)” 根据 API 参考你可以使用带有字段参数 fields=sheets(properties(title,sheetId),conditionalFormats) 的 GET 请求来获取文档所有工作表上所有 Conditional Format 规则的列表,并对其进行解析以确定规则数 完全同意没有用于清除 CF 或完全设置/替换所有 CF 的直接机制是缺少更新请求(
    【解决方案3】:

    所以在我对 if.... 发表评论之后

    但要做到这一点,必须知道有多少条件格式规则(我不知道如何找到)

    决定扩展他的代码:

    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 端的条件格式规则的索引没有可靠地索引,对我来说,它在大约 6 个条件规则处被打破。我发现可靠地做到这一点的唯一方法是正确答案中的解释。不幸的是,如果您有一个复杂的工作表,这会导致大量的 API 调用。对工作表或工作簿进行 API 调用以删除所有条件格式将非常有用。
    【解决方案4】:
    1. 复制没有任何条件格式的单元格。
    2. 选择要从中删除条件格式的单元格。
    3. 编辑 -> 选择性粘贴 -> 仅粘贴条件格式。

    【讨论】:

      【解决方案5】:

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

      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;
      
      }
      

      【讨论】:

        【解决方案6】:

        我最终根据大卫弗里德曼的回答找到了解决方案。此脚本成功地从一列 (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);
         };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-31
          • 2017-07-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多