【问题标题】:Filter Or Hide Row过滤或隐藏行
【发布时间】:2013-09-13 11:04:06
【问题描述】:

[背景故事] 我有一个 Google 表格,用于通过电子邮件将时间表发送给分包商。每个分包商都有自己的工作表,我还有最后一张名为 MasterSchedule 的工作表。

主计划使用对所有单个工作表的引用,以便所有分包商计划都可见。不过,这真的很长。因此,我在所有工作表中都包含了一个辅助列,它只返回 truefalse 指示是否应在母版上显示一行。

但是,该行仍然显示在 master 上,但 helper 列恰好显示为 false。所以我使用了自动过滤器来隐藏它。

TLDR:

问题:Google Apps 脚本没有用于自动过滤的 API。就像使用标准等的 VBA。所以我看到的唯一选择是隐藏行。但这非常慢。我知道这个想法是减少对谷歌服务的调用次数,谷歌建议制作一个数组,然后在数组上执行一个调用。我不知道该怎么做。

我需要一个高效的脚本/函数来查看一列和每个读取 false 的单元格,该函数将隐藏整行,并显示所有其他行。

最快的非脚本方法是使用 Google 表格版本的自动过滤器,只需取消选中 false

我尝试制作一个 for 循环来读取列中的每个单元格,如果单元格值为 false,则每次迭代都会隐藏该行。 速度非常慢。

见:

function MasterFilter() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var maxRows = sheet.getMaxRows();

  //show all the rows
  sheet.showRows(1, maxRows);

  //get data from column B
  var data = sheet.getRange('B:B').getValues();

  //iterate over all rows
  for(var i=5; i< data.length; i++){
    if(sheet.getRange(i,2).getValue() == false){
      sheet.hideRow(i);
    }
  }
}

【问题讨论】:

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


    【解决方案1】:

    我不得不更改您的原始代码的一行,以使其正常工作:

      sheet.hideRow(sheet.getRange(i,2));  // Operates on a range
    

    有了这个,我在一个测试电子表格上计时,大约 200 行,true / false 单元格均匀分布。执行记录报告[4.656 seconds total runtime]

    正如您所怀疑的,您可以通过使用包含一组数据的数组(在本例中为 B 列的所有数据)来减少服务调用。这是“隐藏”方法,使用数组来测试可见性:

    function MasterFilter() {
      var headers = 4; // # rows to skip
      var sheet = SpreadsheetApp.getActiveSheet();
      var maxRows = sheet.getMaxRows();
    
      //show all the rows
      sheet.showRows(1, maxRows);
    
      //get data from column B
      var data = sheet.getRange('B:B').getValues();
    
      //iterate over all rows
      for(var i=headers; i< data.length; i++){
        if(data[i][0] == false){
          sheet.hideRow(sheet.getRange(i+1,1));
        }
      }
    }
    

    根据执行记录,测试表使用了[0.106 seconds total runtime]。看着屏幕,刷新的时候大概有 3 到 4 秒。

    这是另一种方法。在这一个中,我们读取了 Master Sheet 上的所有数据,然后使用 Array.filter() 将二维数组缩减为 B 列中带有 true 的行。然后将这个较小的集合写入 Master Sheet,之后我们清除所有以前的内容。这将执行时间减少了一半,[0.059 seconds total runtime] 根据执行记录。再次,查看副本的刷新延迟使其看起来像几秒钟。

    // Evaluation function for Array.filter()
    function isVisible(row) {
      return (row[1] === true);  // Check column B
    }
    
    function MasterFilter2() {
      var headers = 4; // # rows to skip
      var sheet = SpreadsheetApp.getActiveSheet();
      var data = sheet.getDataRange().getValues();
      var headerData = data.splice(0,headers); // Skip header rows
      var filteredData = data.filter( isVisible );
      var outputData = headerData.concat(filteredData);  // Put headers back
    
      sheet.clearContents();  // Clear content, keep format
    
      // Save filtered values
      sheet.getRange(1, 1, outputData.length, outputData[0].length).setValues(outputData); 
    }
    

    【讨论】:

    • 嘿 Mogsdad,为了隐私起见,这是一个更改了名称的副本:docs.google.com/spreadsheet/…Master2() 它利用了数组,速度快如闪电,但它似乎跳过了一些真实的 -行。 ●它还“粘贴”在首先从其他工作表中获取数据的公式之上(如果我只是让 Master2() set Values 也是一个额外的工作表,这不是一个大问题。)我是否正在处理这一切一个复杂的方式? gscript 是否应该首先为“大师”提供数据?
    • 重新跳过;我在第 51 行放了一个断点,filteredData 中有 69 行,电子表格上的“真”数量相同——所以看起来很完整。重新公式 - 你最初没有提到那些,它们确实改变了一些事情。当然,如果我们clear()setValues(),所有公式都会被吹走。如果您需要保留它们,请使用MasterFilter(),它仍然比您拥有的要快得多,并且会保留公式和格式。不过我喜欢最后一个想法——你可以从每个承包商的工作表中提取过滤后的数据版本,然后append()他们来构建主控。
    猜你喜欢
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    相关资源
    最近更新 更多