性能问题:谷歌脚本过滤行



下面的函数基于特定的列筛选器参数作为表行筛选器(隐藏行)。执行非常慢,尽管该表总共有115条记录。

有什么建议让它运行得更快吗?是否有任何后台功能我可以关闭,如在Excel(屏幕更新,表格计算)?

function filterOnDate(rowHeader, colFirst, colDate, typeFilter, valueFilter){
  /* Hides rows of table where a date column meets a year or a month criteria. Params:
  rowHeader: row number of table headers.
  colFirst: column number of first table column.
  colDate: column number of filter column (listing dates).
  typeFilter: two possible types: "month", "year". Are we filtering on date's month or year.
  valueFilter: filter value (i.e. month name or year number).
  */
  if (valueFilter===undefined){ return; }
  filterClearFilters(true); //Clear existing filters

 var sh = SpreadsheetApp.getActiveSpreadsheet();
 var ss = sh.getActiveSheet();
 var tableData = ss.getRange(rowHeader+1, colFirst,ss.getDataRange().getLastRow()-rowHeader, ss.getDataRange().getLastColumn()-colFirst);
 var numRows = tableData.getNumRows();
 var values = tableData.getValues();
 var months = ss.getRange("Months_Table").getValues();
  if (typeFilter=="year") {
    ss.getRange("Members_Filter_Month").clearContent();
  } else {
    ss.getRange("Members_Filter_Year").clearContent();
  } 
 for (var i=0; i <=numRows-1 ; i++){
   var row =values[i];
   var myValue = row[colDate-colFirst]; //Date value of current row in loop, on filtered column
   var bolHideRow = true;
   if (!myValue=='') {
     if (typeFilter="month" && months[myValue.getMonth()]==valueFilter){
       bolHideRow = false;
     }
     if (typeFilter="year" && myValue.getFullYear()==valueFilter){
       bolHideRow = false;
     }
   }
   if (bolHideRow) {
   ss.hideRows(i+rowHeader+1);
   }
 }
}

这是缓慢的,因为像在工作表上调用hideRows()这样的操作需要在底层调用API Service,每次可能需要几秒钟的时间。您无法做任何事情来加速API调用,最好的办法是尽可能避免以这种方式对它们执行许多操作。像你提到的Excel这样的显示问题在这里不是一个因素。

我看到一些选项。首先,您是否需要使用脚本来完成此操作?你可以用内置的表单过滤很容易地做到这一点。(见"数据"菜单下的"过滤器")

如果出于某种原因它绝对必须是一个脚本,那么您应该尝试尽可能地减少服务调用。

如果你隐藏的行比你显示的多,你可以翻转逻辑,在开始隐藏所有行,然后只显示你需要的行。

如果一系列的几行经常隐藏在一起,您可以跟踪要隐藏的连续行,然后将它们分组隐藏,而不是一次隐藏一个。

您可以将感兴趣的行写入单独的工作表,而不是隐藏行。使用像"setValues()"这样的单个函数一次写出许多值只是一个API服务调用,所以它花费的时间与在单行上调用hideRows()的时间相同。

当只有选定数量的列应用了过滤器时,我能够通过仅在应用了on的列上删除过滤器来提高性能。

  sheet = SpreadsheetApp.getActiveSheet(); //for testing purpose only
  var filter = sheet.getFilter();
  if (filter !== null) {  // tests if there is a filter applied
    var range = filter.getRange(); // prevents exception in case the filter is not applied to all columns
    var firstColumn = range.getColumn();
    var lastColumn = range.getLastColumn();
    for (var i = firstColumn; i < lastColumn; i++) {
      if (filter.getColumnFilterCriteria(i) !== null) { // only remove filter on column if one exists.
        filter.removeColumnFilterCriteria(i); // this is expensive (slow) 
      };
    }

最新更新