40

I'd like to be able to delete an entire row in a Google Spreadsheets if the value entered for say column "C" in that row is 0 or blank. Is there a simple script I could write to accomplish this? Thanks!

Rubén
  • 34,714
  • 9
  • 70
  • 166
Zack
  • 399
  • 1
  • 3
  • 4

11 Answers11

36

I can suggest a simple solution without using a script !!

Lets say you want to delete rows with empty text in column C. Sort the data (Data Menu -> Sort sheet by column C, A->Z) in the sheet w.r.t column C, so all your empty text rows will be available together.

Just select those rows all together and right-click -> delete rows. Then you can re-sort your data according to the column you need. Done.

roneo
  • 1,179
  • 13
  • 22
26
function onEdit(e) {
  //Logger.log(JSON.stringify(e)); 
  //{"source":{},"range":{"rowStart":1,"rowEnd":1,"columnEnd":1,"columnStart":1},"value":"1","user":{"email":"","nickname":""},"authMode":{}}
  try {
    var ss = e.source; // Just pull the spreadsheet object from the one already being passed to onEdit
    var s = ss.getActiveSheet();

    // Conditions are by sheet and a single cell in a certain column
    if (s.getName() == 'Sheet1' &&  // change to your own 
        e.range.columnStart == 3 && e.range.columnEnd == 3 &&  // only look at edits happening in col C which is 3
        e.range.rowStart == e.range.rowEnd ) {  // only look at single row edits which will equal a single cell
      checkCellValue(e); 
    }
  } catch (error) { Logger.log(error); }
};

function checkCellValue(e) {
  if ( !e.value || e.value == 0) {  // Delete if value is zero or empty
    e.source.getActiveSheet().deleteRow(e.range.rowStart);
  }
}

This only looks at the value from a single cell edit now and not the values in the whole sheet.

Bryan P
  • 5,031
  • 3
  • 30
  • 44
  • I never use this "shortcut" syntax, that's why I was asking... but my question was silly, I didn't actually see that you were using `values` ,my brain translated it as `values.length`... I guess I must be a bit too tired sometimes ;-) ;Anyway, thanks for the answer, I don't know either what is the best way to proceed... I guess it's more or less a matter of personal prefs ! – Serge insas Nov 16 '12 at 16:59
  • I took this and changed `onEdit()` to an arbitrary function name because I want to run it on data that's already there, and not while when editing, but it has a weird behavior: when I choose it from the Script Manager and run it, it deletes *one* row and stops, then I have to run it again. Does looping get canceled when you change the number of rows that exist? – agentofuser Nov 18 '12 at 21:28
  • Try [this](https://script.google.com/d/15hdvylHsXLp2Tka_JQLg8zUsq6papcMAZhnlKaipry8YqW9qDjzF05FH/edit). That one above won't work if your sheet starts out as already having more than 1 row that needs deleted. – Bryan P Nov 19 '12 at 02:42
  • 3
    @BryanP woudln't it be easier to iterate backwards? `for( var row = values.length -1; row >= 0; --row )` – Henrique G. Abreu Nov 20 '12 at 00:01
  • I'm not catching why it would be. You're thinking we don't need an extra `deleted` counter in there? – Bryan P Nov 20 '12 at 04:03
  • 1
    Yes BrianP, you do not need the extra correction `delete` variable if you iterate backwards. Well, maybe it's simpler just in my head :) – Henrique G. Abreu Nov 20 '12 at 15:22
  • Yep, I see thx. Think it could also use a `SpreadsheetApp.flush();` in there as I wasn't seeing the expected result appear some times. – Bryan P Nov 20 '12 at 16:48
  • 1
    @BryanP you should avoid for-in loops in Javascript because it iterates over all the properties not just the ones you have assigned it. Here is an article that discusses it: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/ – Weehooey Nov 21 '12 at 11:37
  • @Weehooey - In this case, how many properties does the `values` 2D array have? – Bryan P Nov 21 '12 at 15:40
  • @BryanP in this particular case, there are no extra properties inherited so the for-in loop works as expected. – Weehooey Nov 21 '12 at 19:58
  • Revisited this code if anyone wants to comment. OP only wanted to look at a single cell but for some reason I set it up to loop through the entire sheet values before. – Bryan P Aug 01 '14 at 17:17
24

I wrote this script to do the same thing for one of my Google spreadsheets. I wanted to be able to run the script after all the data was in the spreadsheet so I have the script adding a menu option to run the script.

/**
 * Deletes rows in the active spreadsheet that contain 0 or
 * a blank valuein column "C". 
 * For more information on using the Spreadsheet API, see
 * https://developers.google.com/apps-script/service_spreadsheet
 */
function readRows() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var values = rows.getValues();

  var rowsDeleted = 0;
  for (var i = 0; i <= numRows - 1; i++) {
    var row = values[i];
    if (row[2] == 0 || row[2] == '') {
      sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
      rowsDeleted++;
    }
  }
};

/**
 * Adds a custom menu to the active spreadsheet, containing a single menu item
 * for invoking the readRows() function specified above.
 * The onOpen() function, when defined, is automatically invoked whenever the
 * spreadsheet is opened.
 * For more information on using the Spreadsheet API, see
 * https://developers.google.com/apps-script/service_spreadsheet
 */
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Remove rows where column C is 0 or blank",
    functionName : "readRows"
  }];
  sheet.addMenu("Script Center Menu", entries);
};

Test spreadsheet before:

enter image description here

Running script from menu:

enter image description here

After running script:

enter image description here

Mike Grace
  • 16,636
  • 8
  • 59
  • 79
  • That doesn't work if the row is completely empty because the .getDataRange() doesn't pick up empty rows. – neydroydrec Oct 14 '14 at 02:43
  • 1
    the Script Center Menu doesn't seem to be added to my spreadsheet. I'm confused on how to do that/ – Thieme Hennis Mar 29 '18 at 08:28
  • 1
    I get the following trying to run: `TypeError: Cannot call method "getDataRange" of null. (line 10, file "Code")`. Likely this is a problem with my knowledge of how to run; this is the first Google script I've tried. – Liam Dec 23 '19 at 03:31
  • I am trying to use this with .clearRows to only clear and not delete the specified rows, but I can not seem to make it work. Could you please help me with this? – Daniel H. Jul 15 '21 at 13:37
7

I was having a few problems with scripts so my workaround was to use the "Filter" tool.

  1. Select all spreadsheet data
  2. Click filter tool icon (looks like wine glass)
  3. Click the newly available filter icon in the first cell of the column you wish to search.
  4. Select "Filter By Condition" > Set the conditions (I was using "Text Contains" > "word")

This will leave the rows that contain the word your searching for and they can be deleted by bulk selecting them while holding the shift key > right click > delete rows.

Adam
  • 71
  • 1
  • 1
4

This is what I managed to make work. You can see that I looped backwards through the sheet so that as a row was deleted the next row wouldn't be skipped. I hope this helps somebody.

  function UpdateLog() {

  var returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RetLog');
  var rowCount = returnSheet.getLastRow();

  for (i = rowCount; i > 0; i--) {
    var rrCell = 'G' + i;
    var cell = returnSheet.getRange(rrCell).getValue();
    if (cell > 0 ){
      logSheet.
      returnSheet.deleteRow(i);
    }
  }
}
MikeD
  • 41
  • 1
2

quite simple request. Try this :

 function try_It(){
 deleteRow(2); //// choose col = 2 for column C
 }

 function deleteRow(col){ // col is the index of the column to check for 0 or empty
 var sh = SpreadsheetApp.getActiveSheet();
 var data = sh.getDataRange().getValues();
 var targetData = new Array();
 for(n=0;n<data.length;++n){
 if(data[n][col]!='' && data[n][col]!=0){ targetData.push(data[n])};
 }
 Logger.log(targetData);
 sh.getDataRange().clear();
 sh.getRange(1,1,targetData.length,targetData[0].length).setValues(targetData);
 }

EDIT : re-reading the question I'm not sure if the question is asking for a 'live' on Edit function or a function (like this above) to apply after data has been entered... It's not very clear to me... so feel free to be more accurate if necessary ;)

Serge insas
  • 45,904
  • 7
  • 105
  • 131
  • Just for info, the other answer is better since mine doesnt' handle formulas (if ever there are formulas in the SS) and is more straightforward. – Serge insas Nov 16 '12 at 11:42
  • 1
    The code on this answer is the most efficient in terms of time execution, I think. This should be used when the sheet only has cell values (there aren't notes, comments, data validations, custom formatting, ...). – Rubén Sep 20 '16 at 02:26
2

There is a simpler way:

  1. Use filtering to only show the rows which you want to delete. For example, my column based on which I want to delete rows had categories on them, A, B, C. Through the filtering interface I selected only A and B, which I wanted to delete.
  2. Select all rows and delete them. Doing this, in my example, effectively selected all A and B rows and deleted them; now my spreadsheet does not show any rows.
  3. Turn off the filter. This unhides my C rows. Done!
Dominykas Mostauskis
  • 7,797
  • 3
  • 48
  • 67
1

There is a short way to solve that instead of a script. Select entire data > Go to menu > click Data tab > select create filter > click on filter next to column header > pop-up will appear then check values you want to delete > click okay and copy the filtered data to a different sheet > FINISH

blessel
  • 11
  • 1
0

reading your question carefully, I came up with this solution:

function onOpen() {
  // get active spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // create menu
  var menu = [{name: "Evaluate Column C", functionName: "deleteRow"}];

  // add to menu
  ss.addMenu("Check", menu);
}

function deleteRow() {
  // get active spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // get active/selected row
  var activeRow = ss.getActiveRange().getRowIndex();

  // get content column C
  var columnC = ss.getRange("C"+activeRow).getValue();

  // evaluate whether content is blank or 0 (null)
  if (columnC == '' || columnC == 0) {
    ss.deleteRow(parseInt(activeRow));
  }
}

This script will create a menu upon file load and will enable you to delete a row, based on those criteria set in column C, or not.

Jacob Jan Tuinstra
  • 1,197
  • 3
  • 19
  • 50
0

This simple code did the job for me!

    function myFunction() {

      var ss = SpreadsheetApp.getActiveSpreadsheet();  // get active spreadsheet

      var activeRow = ss.getActiveRange().getRowIndex();  // get active/selected row

var start=1;
var end=650;
var match='';
var match2=0;   //Edit this according to your choice.

     for (var i = start; i <= end; i++) {
      var columnC = ss.getRange("C"+i).getValue();
      if (columnC ==match  || columnC ==match2){ ss.deleteRow(i); }
     }
    }
Udayraj Deshmukh
  • 1,814
  • 1
  • 14
  • 22
0

The below code was able to delete rows containing a date more than 50 days before today in a particular column G , move these row values to back up sheet and delete the rows from source sheet.

The code is better as it deletes the rows at one go rather than deleting one by one. Runs much faster.

It does not copy back values like some solutions suggested (by pushing into an array and copying back to sheet). If I follow that logic, I am losing formulas contained in these cells.

I run the function everyday in the night (scheduled) when no one is using the sheet.

function delete_old(){
  //delete > 50 day old records and copy to backup
  //run daily from owner login
  var ss = SpreadsheetApp.getActiveSpreadsheet();  
  var bill = ss.getSheetByName("Allotted");
  var backss = SpreadsheetApp.openById("..."); //backup spreadsheet
  var bill2 = backss.getSheetByName("Allotted");
  var today=new Date();
  //process allotted sheet (bills)
  bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
  ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 7, ascending: true});
  var data = bill.getDataRange().getValues();
  var delData = new Array();
  for(n=data.length-1; n>1; n--){
    if(data[n][6] !=="" &&  data[n][6]  < today.getTime()-(50*24*3600*1000) ){  //change the condition as per your situation
      delData.push(data[n]);
    }//if
   }//for
   //get first and last row no to be deleted
   for(n=1;n<data.length; n++){
    if(data[n][6] !=="" &&  data[n][6]  < today.getTime()-(50*24*3600*1000) ){ 
      var strow=n+1 ; //first row
      break
    }//if
   }//for
   for(n=data.length-1; n>1; n--){
    if(data[n][6] !=="" &&  data[n][6]  < today.getTime()-(50*24*3600*1000) ){ 
      var ltrow=n+1 ; //last row
      break
    }//if
   }//for
   var bill2lr=bill2.getLastRow();
   bill2.getRange((bill2lr+1),1,delData.length,delData[0].length).setValues(delData);
   bill.deleteRows(strow, 1+ltrow-strow);
   bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
   ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 6, ascending: true}); //get back ordinal sorting order as per column F
}//function
arul selvan
  • 616
  • 4
  • 17