使用循环删除空行只会删除第一个空行

时间:2019-07-16 14:00:10

标签: google-apps-script google-sheets

我目前正在处理一个脚本,该脚本应该从数据集中删除标记为“完成”或为空的行。我有一个工作循环,该操作会删除所有完成的行,但只删除每组空行的第一行。

我发现了多种解决方案,但是所有这些解决方案都增加了i,因此需要跟踪已删除的行数,以便在删除下一行时匹配正确的行。

function sheetclear(){
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName("Sheet");
    var range = sheet.getDataRange();
    var firstrow = 5;
    var numrow = range.getNumRows()-firstrow;
    var values = sheet.getRange(firstrow,1,numrow+1,8).getValues();


    if(sheet.getRange("h3").getValue() == true){ //h3 acts as a trigger
        for (i = parseInt(numrow)-1; i >= 0; i--){
            var row = values[parseInt(i)]

            if(row[7] == "done" || (row[1] == "" && values[(parseInt(i)+1)][1] != "")){
                sheet.deleteRow((parseInt(i)+firstrow))
            }
        }

        //Re-adding the deleted rows and formatting them
        sheet.insertRowsAfter(sheet.getLastRow(),100-sheet.getLastRow());
        sheet.getRange(firstrow,1,numrow+1,8).setBorder(false, true, false, true, true, false, "silver",SpreadsheetApp.BorderStyle.SOLID)
        sheet.getRange("h3").setValue(false);
    }
}

我是JavaScript的业余爱好者,所以(可能很明显)解决方案使我难以理解。我怀疑这与一次检查值有关,而不是在每次迭代后检查。

这里有人可以指出正确的道路吗?

3 个答案:

答案 0 :(得分:0)

if(row[7] == "done" || (row[1] == "" && values[(parseInt(i)+1)][1] != ""))

在以下情况下,将上述条件评估为真:

  • 行的第7列的值为“完成” 或
  • 行的第一列为空,而下一行的第一列不为空

因此,如果您有多个相邻的行且其值为空,则除一行外,将不满足任何条件。因此,它将仅删除一行。

请删除&&条件的第二部分,使其类似:

if(row[7] == "done" || (row[1] == ""))

答案 1 :(得分:0)

  

您正在向后循环,并将行值和行比较为   您的计数器变量的功能-这会使代码混乱。您   最终会删除错误的行。

我建议您通过以下方式修改代码:

function sheetclear(){
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName("Sheet");
    var range = sheet.getDataRange();
    var firstrow = 1;
    var numrow = range.getNumRows();
    if(sheet.getRange("h3").getValue() == true){ //h3 acts as a trigger
        for (var i = numrow-1; i >0; i--){
            var rowValues=sheet.getRange(i,1,2,sheet.getLastColumn()).getValues();
            if(rowValues[0][7] == "done" || rowValues[0][1] == "" && rowValues[1][1] != ""){
                sheet.deleteRow(i)
            }
        }
    }
}

这将删除B列(数组条目[1])中的单元格为空,而其下方的单元格具有值的所有行。希望我理解得对,这是您想要的功能。

此外,请删除parseInt(),这对于您的代码不是必需的。

答案 2 :(得分:0)

@ziganotschka 感谢您的指导。我不知道循环在删除一行后不会检查数据表的状态。

您的解决方案有效。但是,它似乎要慢得多。我发现的另一种方法是,将一个函数调用添加到我的循环中,以便它根据需要经常通过工作表。

我设置为简单地限制范围,使其在包含书面数据的最后一个单元格中结束(通过使用工作表中的公式),并简化功能,使其成为他的第一个答案中指出的五元素。

它看起来像这样:

function sheetclear(){ 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Sheet");

  var fr = 5;
  var lr = sheet.getRange("i3").getValue() //this is where I calculate the last occupied cell

  var range = sheet.getRange(fr,1,lr,8)
  var val = range.getValues()


  if(sheet.getRange("h3").getValue() == true){
    for (var i = lr; i>=fr; i--){
      if(val[i-fr][1] == "" || val[i-fr][7] == "done"){
        sheet.deleteRow(i)
      }
   }

//Re-adding the deleted rows and formating them
sheet.insertRowsAfter(sheet.getLastRow(),100-sheet.getLastRow());
sheet.getRange(fr,1,sheet.getLastRow(),8).setBorder(false, true, false, true, true, false, "silver",SpreadsheetApp.BorderStyle.SOLID)
sheet.getRange("h3").setValue(false);

  }
}