【问题标题】:Google script change row color based on data change, sheet sorted谷歌脚本根据数据变化改变行颜色,工作表排序
【发布时间】:2020-06-26 22:19:30
【问题描述】:

Link to demo sheet

我有一张按 E 列排序的工作表。E 列中的值可以重复,这意味着 E 列中的几行可以具有相同的值。 现在我想为表示 E 列发生变化的行着色。 这是我根据 StackOverflow 上的一些出色答案构建的代码:

function quicktest() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
  var rangeData = spreadsheet.getDataRange().getValues();
  var lastRow = spreadsheet.getLastRow();
  //  var searchRange = spreadsheet.getRange(1, 1, lastRow-1, 5);
//  var rangeValues = searchRange.getValues();
  var previousclient = rangeData[2][5];
  console.log(previousclient);
  for ( j = 1 ; j < lastRow - 1; j++){
    var currentclient = rangeData[j][5];
    console.log(previousclient," ",currentclient);
    if (previousclient != currentclient) {
      spreadsheet.getRange(j,1,1,5).setBackground("#cc4125");
      previousclient = currentclient;  
    }; 
}

代码运行,但结果是它“绘制”了错误的单元格,而且它也没有绘制整行(A 到 H 列),它只绘制了 A 到 C。 我还在这里阅读了一些建议将值发送到 rangeValues 的答案,但这对我不起作用。这就是为什么它在代码中被列为注释。也许我确实需要使用它。 这是运行此代码后我希望演示表的样子:

谢谢

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    注意索引 - 数组以 [0] 开头

    各自的混淆会导致您的代码出现几个问题:

    • rangeData[2][5] 表示单元格F3 - 不是E,如果你想检索列E - 它对应于数组索引4(对于以前的和当前的客户!)
    • 鉴于最初的previousclient 不应该被着色(仅以下一个),您应该将其设置为标题行,所以rangeData[0][4]
    • 当您使用getRange() 方法时,行索引以1 开头(与数组元素不同!!!),因此数组元素i 对应于行i+1

    要解决这些问题,请按以下方式修改您的代码:

    function change_row_color() {
      var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
      var rangeData = spreadsheet.getDataRange().getValues();
      var lastRow = spreadsheet.getLastRow();
      var previousclient = rangeData[0][4];
      console.log(previousclient);
      for ( j = 1 ; j < lastRow - 1; j++){
        var currentclient = rangeData[j][4];
        console.log(previousclient," ",currentclient);
        if (previousclient != currentclient) {
          spreadsheet.getRange(j+1,1,1,5).setBackground("#cc4125");
          previousclient = currentclient;  
        };
      }}
    

    更新

    调用外部服务,包括 SpreadsheetApp 方法 should be minimized,因为它们会使您的代码变慢。

    因此,例如在每个循环中调用 setBackground 会导致执行时间更长。
    如果您只想使用setBackgrounds 而不是setBackground 设置颜色一次,您可以这样做:

    function change_row_color() {
      var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
      var range = spreadsheet.getDataRange();
      var rangeData = range.getValues();
      var lastRow = spreadsheet.getLastRow();
      var previousclient = rangeData[0][4];
      console.log(previousclient);
      var colors = [[0,0,0,0,0]];
      for ( j = 1 ; j < lastRow; j++){
        var currentclient = rangeData[j][4];
        console.log(previousclient," ",currentclient);
        if (previousclient != currentclient) {
          colors.push(["#cc4125","#cc4125","#cc4125","#cc4125","#cc4125"]);
          previousclient = currentclient;  
        } else{
          colors.push([0,0,0,0,0]);
        }
      }
    range.setBackgrounds(colors);
    }
    

    这种方法是否会更快,很大程度上取决于您的数据大小和重复数量。

    【讨论】:

    • 谢谢@ziganotschka!现在就像一个魅力。然而,魅力需要相当长的时间才能发生。关于如何让它运行得更快的任何想法?也许使用在我上面的原始代码中设置为注释的 rangeValues 想法?
    • rangevaluesrangeData 完全相同(它获取一个范围),唯一的区别是它不是检索工作表上的整个数据,而是检索您指定的行和列。如果您的工作表包含大量数据,但您的函数只能在其中的一部分上运行,则手动定义范围是有意义的。但我相信您想对所有数据运行该函数?
    • 为了加快代码速度,您可以在每次迭代中将 setBackground 替换为在代码末尾只调用一次的 setBackgrounds
    • 是的。事实上,我想了解工作表的全部内容。我不确定我是否理解 setBackgrounds 过程。您能否解释一下,或者用这个新想法编辑您的答案?我正在考虑使用缓存。这会有所帮助还是我完全放弃了?
    • 感谢您编辑您的答案。这个新代码确实更快,但是对于 350 行的小测试范围仍然需要大约 20 秒。我的实际范围有接近 10K 行,所以这个代码在工作日不是一个好主意。问题是我们需要临时运行,并且无法承受夜间或其他非即时运行。有任何想法吗?缓存?顺便说一句 - 我正在处理的数组是一个 IMPORTRANGE 数组。这会延长这段代码的运行时间吗?
    猜你喜欢
    • 2015-09-29
    • 1970-01-01
    • 2019-04-30
    • 2023-03-13
    • 2012-11-06
    • 2019-11-19
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多