使用Google Apps脚本删除Google表格中的行

时间:2016-06-20 14:16:54

标签: google-apps-script google-sheets

我尝试使用google脚本删除与特定值匹配的行时遇到了最奇怪的错误。

这是我的代码:

function myFunction() {
  var doc = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = doc.getSheetByName("file.csv");

  var values = sheet.getRange("N2:N").getValues();

  var row_del = new Array();

  for(var i=0;i<values.length;i++)
  {
    if(values[i] == 'del'){
      row_del.push(i+2); // This line was added for debugging purposes.
     // sheet.deleteRow(i+2) was the line that was in this condition
     // (i+2) is used because row 1 has headers and the range starts from 0.
    }
  }

//  Logger.log(row_del);
//  GmailApp.sendEmail("my_email_address", "subject", row_del)

  for (var i = 0; i < row_del.length; i++)
  {
    sheet.deleteRow(row_del[i]);
  }

}

我编写的代码会选择应删除的行号,但在第一次尝试时不会删除所有这些行。我应该多次执行我的脚本以删除这些行。

如果我的代码有错误,它应该显示,如果逻辑错误,则必须删除不正确的行。我没有遇到这些情况,我应该多次执行此功能。

这里有什么我想念的吗?

9 个答案:

答案 0 :(得分:11)

当从工作表中删除行时,即使脚本继续运行,它下面的行也会重新编号。如果脚本随后尝试也删除这些行,则结果是不可预测的。出于这个原因,当删除行时,应该从下到上进行。在你的情况下,像这样:

for (var i = row_del.length - 1; i>=0; i--) {
  sheet.deleteRow(row_del[i]); 
}

答案 1 :(得分:1)

请参阅Google团队建议的锁定功能:

  var lock = LockService.getScriptLock();
  lock.waitLock(30000); // lock 30 seconds
  //do whatever you want here
  lock.releaseLock();

这样,您一次完成了删除作业!由于或释放锁,系统线程要等30秒才能继续执行其他作业。

google dev-document:https://developers.google.com/apps-script/reference/lock/lock

答案 2 :(得分:0)

那么,这应该是什么样子?

{{1}}

答案 3 :(得分:0)

仅在您没有删除行

时才增加i
function del_F_rows(){
 var i=1;
 while(!sht_balanceHistory.getRange(i,1).isBlank()){
  if(sht_balanceHistory.getRange(i,3).getValue()=="F")
     sht_balanceHistory.deleteRow(i);
  else
     i=i+1;
    }
}

答案 4 :(得分:0)

复制粘贴自https://gist.github.com/dDondero/285f8fd557c07e07af0e

您可以计算删除mwny行的次数,而不用遍历两次行,以计算下一个要删除的行的正确索引。

sync()

答案 5 :(得分:0)

您可以像这样使用deleteRows函数删除最后一行之后的行:

var maxRows = newsheet.getMaxRows(); 
var lastRow = newsheet.getLastRow();
if (maxRows-lastRow != 0)
{
  newsheet.deleteRows(lastRow+1, maxRows-lastRow);
}

答案 6 :(得分:0)

这是一个我用来删除除某些值以外的所有内容的脚本,但是可以轻松修改以保留某些字符串,并且比循环遍历所有数据过滤器并删除要删除的值和批量删除要快得多。我的数据大约有10000行,因此循环将永远持续下去。

function DeleteCertainRows(){

  columnCopy("D","Z","YourSheetName");//Copy from your target column in this case D to another column in this case Z

  replaceInSheet("Z","YourSheetName","keep String 1","keep");//find and replace the value with what you want to keep
  replaceInSheet("Z","YourSheetName","keep String 2","keep");//Can repeat for additional values

  DeleteValueInColumn("Z","YourSheet","keep");//filters and deletes all other values Column is case sensitive and cant go past Z

};

function replaceInSheet(repColumn,sheetname, to_replace, replace_with) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);

  var values = sheet.getRange(repColumn+'1:'+repColumn+sheet.getMaxRows());

  var textFinder = values.createTextFinder(to_replace); 
  var replaceall = textFinder.replaceAllWith(replace_with);

};

function columnCopy(copyfrm,copyto,sheetname){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
    var copyrange = sheet.getRange(copyfrm+'1:'+copyfrm+sheet.getMaxRows());
    var pasterange = sheet.getRange(copyto+'1:'+copyto+sheet.getMaxRows());

  copyrange.copyTo(pasterange);

};

function DeleteValueInColumn(colStr, sheetname, deleteval){
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
  var filterRange=sheet.getDataRange();
  var myFilter = filterRange.createFilter();
  var CriteriaBuild = SpreadsheetApp.newFilterCriteria();
  var Criteria = CriteriaBuild.whenTextDoesNotContain(deleteval);//change to whenTextContains to delete your string value instead of everything else
  var myCriteria = Criteria.build();

  var str = colStr;
  var myCol = parseInt(str.charCodeAt(0) - 64);
  Logger.log(myCol);

  myFilter.setColumnFilterCriteria(myCol, myCriteria);

  var deleterange=sheet.getRange('2:'+sheet.getLastRow());
  sheet.deleteRows(deleterange.getRow(), deleterange.getNumRows());

  myFilter.remove();


};

答案 7 :(得分:0)

要从单个命名工作表中删除空白行,请假定列1在有效行中包含数据。 搜索并从最高行号到最低行号删除。

// Deletes any row whose first column is blank
// WARNING: Assumes any valid row has data in column 1
function deleteBlankRows() {
  var doc = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = doc.getSheetByName("Sheet3");
  var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();

  for (var i = lastRow; i > 0; i--) {
    var range = sheet.getRange(i,1); 
    var data = range.getValue();
    if (data == '') {
      sheet.deleteRow(i);
    }
  }
}

答案 8 :(得分:0)

更新2020

一种更快,更现代的JavaScript方法是使用forEachreverse()进行向后迭代。

flat简化values数组会更有意义,因为它涉及单个列的数据。

解决方案:

function myFunction() {
  const doc = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = doc.getSheetByName("file.csv");
  const values = sheet.getRange("N2:N").getValues().flat();
  values.reverse().forEach((r,i)=>{
      if (r=='del'){
         sheet.deleteRow(values.length-i+1);
      }
  });
}