【问题标题】:Google Apps Script - Sheets - Conditional Formatting - X = highlightGoogle Apps 脚本 - 表格 - 条件格式 - X = 突出显示
【发布时间】:2018-05-30 03:38:33
【问题描述】:

我有一张包含超过 100,000 个单元格(很快将超过 300,000 个单元格)的表格用作甘特图。每个单元格都有一个 IF 公式,如果相应列的标题(日期)在行的开始日期和结束日期之间,则返回字母 X。

但是,显着降低工作表速度的是其背后的条件格式。条件格式表示如果单元格的值为 X,则将单元格的背景颜色和字体颜色更改为绿色。如果没有 X,则背景颜色应为白色。据我了解,由于条件格式会在您对工作表进行任何编辑时重新计算,因此性能非常差。所以我的想法是删除条件格式并将其添加为脚本,并带有一个菜单按钮,我可以随时单击它运行,而不是每次我对工作表进行编辑时运行条件格式。

这是我使用脚本的地方,但它不起作用。我已经尝试了几十种变体,但找不到有效的方法 - 有时我让它运行没有错误,有时会出现错误。我的上下文是不是哪里错了?

function formatting() {

  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
  var range = ss.getRange("A1:A100");
  var cellValue = range.getValues();
  if (cellValue === 'X') {
    ss.range.setBackgroundColor('#000000'); }
  else {
    cellValue.setBackgroundColor('#ffffff'); }
}

【问题讨论】:

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


    【解决方案1】:

    这是一种使用批处理函数Range.setBackgrounds() 的方法。此函数将二维值数组作为参数,允许您在单个 API 调用中设置范围的所有单元格背景。

    另请注意,函数Range.getValues() 返回一个二维数组值。要检查每个单独的单元格值,您需要遍历数组。

    由于您将二维数组作为输入和输出处理,因此构建背景值输出数组的逻辑反映了您检查当前单元格值所需的逻辑。因此,您可以在循环单元格值时构建背景值的二维数组。

    function setCellBackgrounds() {
      // The name of the sheet to process.
      var sheetName = "Sheet1";
      // The range of cells to inspect.
      var range = "A1:Z100";
    
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
      var range = sheet.getRange(range);
      var values = range.getValues();
      var colors = [];
      for (var x = 0; x < values.length; x++) {
        colors[x] = [];
        for (var y = 0; y < values[x].length; y++) {
           if (values[x][y] == 'X') {
             colors[x][y] = '#999999';
           } else {
             colors[x][y] = '#ffffff';
           }
        }
      }
      range.setBackgrounds(colors);
    }
    

    使用批处理函数,而不是重复调用非批处理版本,是a documented Apps Script best practice

    【讨论】:

    • 非常感谢!这似乎也有效。现在会做更多的测试。也试图弄清楚这个 IF 语句(上面评论过)
    【解决方案2】:
    • cellValues 是一个二维数组;必须检查每个单元格是否为X。循环运行,得到被测元素的(x, y)。
    • ss.rangecellValue 都不能用于设置背景。它必须是 ss.getRange(x, y).setBackground...,使用 (x, y) 坐标来指定 Xed 单元格。

    还没有测试过,但这应该可以工作:

    function formatting() {
      var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
      var range = ss.getRange("A1:A100");
      for (var x = 0; x < range.length; x++) {
        for (var y = 0; x < range[0].length; y++) {
          if (cellValue == 'X') {
            ss.getRange(x, y).setBackgroundColor('#000000');
          } else {
            ss.getRange(x, y).setBackgroundColor('#ffffff');
          }
        }
      }
    }
    

    虽然这可能是您正在寻找的内容,但您还是担心速度。另一种方法是在需要时添加/删除规则。如果经常手动重新创建太多,可以使用ConditionalFormatRule 以编程方式完成。

    【讨论】:

    • 这将比 OP 目标工作表大小的现有条件格式还要慢。
    • 好点,但运行频率会低得多,因此速度仍有提升,可能会更好。我认为没有办法更有效地(重新)在 Google Apps 脚本中实现条件格式,但这就是这里的问题。
    【解决方案3】:

    here 所述,您没有正确引用支票。然而,使用setBackground 甚至不能用于 100 个单元格,更不用说 1000 或 300,000 个单元格了。您会发现需要使用批处理方法 Range#setBackgrounds() 和您希望应用的背景颜色的“2D”数组。

    您可以通过使用有关甘特图电子表格的构造和操作的特定于应用程序的详细信息来减少您修改的范围,从而进一步减少对大量 API 的需求。也许 X 只能在刚刚编辑过的单元格中出现或消失,或者它们只能从左到右或从上到下等填充。

    此函数假定最坏的情况 - 每次调用它时,您都需要重新计算背景颜色。

    function greenify() {
      const sheet = SpreadsheetApp.getActive().getSheetByName("Gantt");
      const HAS_X = "green", NO_X = null;
      const dr = sheet.getDataRange();
      const colors = dr.getBackgrounds();
      const VALUES = dr.getValues();
    
      // Inspect the value array and modify the corresponding index in colors.
      for (var r = 0, rows = VALUES.length; r < rows; ++r)
        for (var c = 0, cols = VALUES[0].length; c < cols; ++c)
          colors[r][c] = (VALUES[r][c] === "X") ? HAS_X : NO_X;
    
      // Write the output.
      dr.setBackgrounds(colors);
    }
    

    如果只需要考虑刚刚修改的单元格,我建议使用"simple trigger."

    【讨论】:

    • 谢谢!似乎可以正常工作,现在将进行更多测试。您是绝对正确的,甘特图的构建也是缓慢的原因。我的 IF 语句 (=IF($K2="N/A","",IF(AND(L$1>=$H2,L$1
    • (在另一个线程中正确询问我的 IF 问题)。非常感谢您在这里的回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多