【问题标题】:Cells formatting works only on visible (not filtered) rows单元格格式仅适用于可见(未过滤)行
【发布时间】:2015-02-19 11:44:43
【问题描述】:

我正在使用 GDrive 电子表格和 Google 应用脚本。我需要更改所有单元格的格式和背景颜色,并且需要以编程方式进行。以下代码效果很好:

ss.getRange(1, 1, ss.getLastRow(), ss.getLastColumn()).setNumberFormat("@STRING@").setBackground("cyan");

唯一的问题是它适用于可见的行/列 - 即,如果您根据特定列值过滤工作表,则上面的代码将仅适用于当前显示的行。

例如,我有以下电子表格

我继续在第二列添加过滤器:

如您所见,我选择在 zxc 值上过滤第二列。现在我需要使用谷歌应用脚​​本将电子表格的单元格格式化为青色背景。代码如下:

function testFormat(){
  var id = "theIdOfMySpreadsheet";
  var sheet = SpreadsheetApp.openById(id);
  var ss = sheet.getSheets()[0];
  ss.getRange(2, 1, ss.getLastRow() - 1, ss.getLastColumn()).setBackground("cyan");
}

这是电子表格上的结果:

一切似乎都很好。但是看看如果我删除过滤器会发生什么:

5 行中只有 2 行具有正确的背景颜色,即使我已将其设置在 整个 范围内。我已经测试了返回范围的长度,它可以正常工作,因为它返回 5 行和 3 列。

你们中有人遇到过这个问题吗?如何强制它更改过滤出的行的背景?

【问题讨论】:

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


    【解决方案1】:

    如果有相当于 Data - Turn Off Filter 的 Apps Script 方法,那么您可以清除隐藏的行。但目前来看,这种可能性是不存在的。

    一个选项是在应用任何过滤器之前首先突出显示整个范围以及所有数据。当范围被过滤到一个较小的列表时,颜色格式只会出现在较小的列表中。放回去的时候会返回整个列表。

    您首先过滤,然后应用背景。尝试先应用背景颜色。

    如果您不能这样做,那么您可以使用可安装的 onChange 触发器来监控 OTHER 事件类型。 OTHER 事件类型由数据过滤器和其他事件触发。

    但您需要知道过滤器前后的状态。所以你需要以某种方式记录原始状态,然后检查是否有变化,比如显示的行数。

    【讨论】:

    • 我需要的是在继续使用气体脚本之前以编程方式取消工作表过滤器,我需要通过代码来完成,因为我无法手动删除过滤器。无论如何,我认为这是不可能的,不幸的是,当前类 api 没有提供任何允许这样做的功能:( 无论如何感谢您的建议!
    【解决方案2】:

    如果您想要所有行的背景颜色,为什么不先更改颜色然后应用过滤器? (注意:我的声誉不允许我发表评论,因此我将其发布为答案)

    【讨论】:

      【解决方案3】:

      这是我为解决这个问题而编写的一个函数。 它检查工作表上的过滤器并停用列上存在的任何过滤条件,在指定范围内设置背景颜色,然后重新激活过滤条件。

      // Globals
      var SS = SpreadsheetApp.getActive();
      var SH = SS.getSheetByName('Data');
      
      var COLOR = {
        draft: '#d9ead3', // light green
        published: '#93c47d' // dark green
      };
      
      function colorBg_(sheet, a1Notations, color) {
        // color must be null to reset
        // calling the .setBackground method with undefined does nothing 
        // and with no argument throws an error
        color = color? color: null;
      
        // calling .getRangeList with wrapping a1Notation strings in an array throws an error
        a1Notations = !Array.isArray(a1Notations)? [a1Notations]: a1Notations;
      
        const filter = sheet.getFilter(); // returns null if there is no filter present (does not throw error)
        if (!filter) { // no filter, no problems
      
          // this works fine even with a single range in the list
          sheet.getRangeList(a1Notations).setBackground(COLOR.published);
      
        } else { // temporary remove filters so color will be applied to all visible rows
      
          const headerColumns = filter.getRange().getValues()[0];
      
          const filterCriterias = headerColumns.reduce(function(criterias, column, index) {
            const columnPosition = index + 1;
            const criteria = filter.getColumnFilterCriteria(columnPosition);
            if (criteria) {
              criterias[columnPosition] = criteria;
            }
            return criterias;
          }, {});
      
          const filteredColumnPositions = Object.keys(filterCriterias);
      
          filteredColumnPositions.forEach(function(columnPosition) {
          // const columnPosition = parseInt(key, 10); // this step is unnecessary, 
          // columnPosition can be a number or a string
            filter.removeColumnFilterCriteria(columnPosition);
          });
      
          // now that filters are inactive and all rows are visible, set the color
          sheet.getRangeList(a1Notations).setBackground(color);
      
          // replace filter criteria on columns
          filteredColumnPositions.forEach(function(columnPosition) {
            filter.setColumnFilterCriteria(columnPosition, filterCriterias[columnPosition]);
          });
        }
      }
      
      function colorDefault (color) {
        const a1Notation = 'E2:F';
        colorBg_(SH, a1Notation) // colorBg_ function will default color argument to null
      }
      
      function colorPublished () {
        var a1Notations = [
          'E3:F6',
          'F8',
          'E10'
        ];
        colorBg_(SH, a1Notations, COLOR.published);
      }
      

      【讨论】:

        【解决方案4】:
        //Enter your sheet name in getSheetByName function.
        
        function clearFilter() {
        var ss = SpreadsheetApp.getActiveSpreadsheet();
        var ssId = ss.getId();
        var sheetId = ss.getSheetByName("SheetName");
        var filter =sheetId.getFilter();
        
        for(var i=1;i<=column.length;i++)//colunm.length means number of columns.
        {
            filter.removeColumnFilterCriteria(i);
        }
        }
        

        【讨论】:

        • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
        猜你喜欢
        • 2020-07-19
        • 2023-02-23
        • 2012-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多