如果ALL单元格与Apps脚本有值,那么清除行的最有效方法是什么?

时间:2018-06-07 12:20:22

标签: google-apps-script google-sheets

如果某个范围内的所有单元格都有值,我正在尝试创建一个清除内容(不是删除行)的函数。下面的脚本没有按预期运行,我非常感谢你们所有的帮助/建议。它目前只清除一行,并且似乎没有迭代整个数据集。我的想法是迭代行,并单独检查每个单元格。如果每个变量都有一个值,请清除该范围并转到下一行。

这是一个link to a sample Google Sheet,其中包含脚本编辑器中的数据和脚本。

function MassRDDChange() {
       // Google Sheet Record Details
       var ss = SpreadsheetApp.openById('1bcrEZo3IkXiKeyD47C_k2LIRy9N9M6SI2h2MGK1Cj-w');
       var dataSheet = ss.getSheetByName('Data Entry');

       // Initial Sheet Values
       var newLastColumn = dataSheet.getLastColumn();
       var newLastRow = dataSheet.getLastRow();
       var dataToProcess = dataSheet.getRange(2, 1, newLastRow, newLastColumn).getValues().filter(function(row) {
           return row[0]
       }).sort();
       var dLen = dataToProcess.length;

       // Clear intiial sheet
       for (var i = 0; i < dLen; ++i) {
           var row = 2;
           var orderNumber = dataToProcess[i][0].toString();
           var rdd = dataToProcess[i][1].toString();
           var submittedBy = dataToProcess[i][2].toString();
           var submittedOn = dataToProcess[i][3].toString();
           if (orderNumber && rdd && submittedBy && submittedOn) {
               dataSheet.getRange(row, 1, 1, newLastColumn).clear();
               row++;
           } else {
               row++; // Go to the next row
               continue;
           }
       }
   }

谢谢!

1 个答案:

答案 0 :(得分:2)

由于您不想删除行,只需要clear()它们,并且它们全部位于同一工作表标签上,因此这是RangeLists的一个很好的用例,允许您将特定的Range方法应用于非连续的Range。目前,create a RangeList的唯一方法是来自一组参考符号(即RangeListarray of Range objects不同),因此我们的第一个目标是为我们的JavaScript数组添加前缀要使用可用的引用字符串进行检查的工作表数据。我们可以编写一个函数来将数组索引从0基本整数转换为A1表示法,但R1C1引用完全有效传递给RangeList构造函数,所以我们只需要考虑标题行和0-base vs 1-base索引差异。

然后,策略是:

  1. 将表格数据批量读取到JavaScript Array
  2. 使用R1C1字符串标记数组的每个元素(即每行),该字符串标识此元素的来源位置。
  3. Filter基于每个元素的内容的工作表数据数组
    • 保留每个子元素(该行中的列值)转换为布尔值的元素(即,与空单元格的值不同)
  4. 将每个保留行的标签提供给RangeList constructor
  5. RangeList
  6. 上使用RangeList方法

    因为这种方法只使用3个Spreadsheet调用(除了批量读取的初始设置),每行要清除1次,所以它应该快得多。

    function clearFullyFilledRows() {
      // Helper function that counts the number of populated elements of the input array.
      function _countValues(row) {
        return row.reduce(function (acc, val) {
          var hasValue = !!(val || val === false || val === 0); // Coerce to boolean
          return acc + hasValue; // true == 1, false == 0
        }, 0);
      }
      const sheet = SpreadsheetApp.getActiveSheet();
      const numHeaderRows = 1,
          numRows = sheet.getLastRow() - numHeaderRows;
      const startCol = 1,
          numCols = sheet.getLastColumn();
    
      // Read all non-header sheet values into a JavaScript array.
      const values = sheet.getSheetValues(1 + numHeaderRows, startCol, numRows, numCols);
    
      // From these values, return a new array where each row is the origin
      // label and the count of elements in the original row with values.
      const labeledCounts = values.map(function(row, index) {
        var rNc = "R" + (numHeaderRows + 1 + index) + "C";
        return [
          rNc + startCol + ":" + rNc + (startCol + numCols - 1),
          _countValues(row)
        ];
      });
    
      // Filter out any row that is missing a value.
      const toClear = labeledCounts.filter(function (row) { return row[1] === numCols; });
    
      // Create a RangeList from the first index of each row (the R1C1 label):
      const rangeList = sheet.getRangeList(toClear.map(function (row) { return row[0]; }));
      // Clear them all:
      rangeList.clear();
    }
    

    请注意,由于这些已清除的行可能不相交,因此可能会出现包含数据的行和没有数据的行。对sheet.sort(1)的调用将对工作表中的所有非冻结行进行排序,将新空行移动到底部(是的,您可以以编程方式设置冻结的行)。根据其他地方引用此工作表的方式,这可能并不合适。

    其他参考资料: