Using VB to sort and eliminate rows based on a column value.

I have a spreadsheet that has many columns and rows, If the value in the process time column is zero, I want to delete that row using VBA as part of an existing macro. the spreadsheet has about 16,000 rows and the zero values are in about 1,100 rows interspersed randomly throughput the spreadsheet.

One solution is to just loop through all rows and delete the row where the zero values are. However that gets a little tricky as deleting the rows will change the number of rows which will affect the loop counter.

I am hoping there is a way to do this without a loop. Thanks in advance for your help.

Here is the VBA for a macro recorded doing this manually:

Sub EliminateZeroProcessTimes()
'
' EliminateZeroProcessTimes Macro
'
    Cells.Select
    Range("B1").Activate
    ActiveWorkbook.Worksheets("ProcessData").Sort.SortFields.Clear
   
    'Sort the entire worksheet based on the Process Time column (Column G)
    ActiveWorkbook.Worksheets("ProcessData").Sort.SortFields.Add key:=Range( _
        "G2:G14699"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
        xlSortNormal
    With ActiveWorkbook.Worksheets("ProcessData").Sort
        .SetRange Range("A1:M14699")
        .header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
   
    'Manually select the rows with zero values in column G and delete those rows
    Rows("2:1027").Select
    Range("B2").Activate
    Selection.Delete Shift:=xlUp
    Cells.Select
   
    'Sort the entire worksheet to get back in original order (minus delted rows)
    Range("B1").Activate
    ActiveWorkbook.Worksheets("ProcessData").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("ProcessData").Sort.SortFields.Add key:=Range( _
        "A2:A14699"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
        xlSortNormal
    ActiveWorkbook.Worksheets("ProcessData").Sort.SortFields.Add key:=Range( _
        "D2:D14699"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
        xlSortNormal
    With ActiveWorkbook.Worksheets("ProcessData").Sort
        .SetRange Range("A1:M14699")
        .header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub
EdLBAsked:
Who is Participating?
 
Martin LissConnect With a Mentor Older than dirtCommented:
    
Sub delRows()
Worksheets("ProcessData").Activate
    Range("G1").Select
    Selection.AutoFilter
    With ActiveSheet
        .Range("G1:G" & .UsedRange.Rows.Count).AutoFilter Field:=7, Criteria1:="0"
    End With
    If WorksheetFunction.CountIf(ActiveSheet.Columns("G"), "0") > 0 Then
        ActiveSheet.Rows(1).Hidden = True
        Selection.SpecialCells(xlCellTypeVisible).EntireRow.Delete
        ActiveSheet.Rows(1).Hidden = False
    End If
    Selection.AutoFilter
    Range("G1").Select
End Sub

Open in new window

0
 
Martin LissOlder than dirtCommented:
Use Autofilter to leave visible only the rows where the process time is zero and then simply delete those rows all at once.
0
 
FarWestCommented:
In general removing from array or deleteng rows should be in reverse order I.e. you counter should start from a variable that has activesheet.usedrange.rows.count to 1 step -1
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Martin LissOlder than dirtCommented:
This should do it. No sorting or looping needed. It assumes that Process Time is in column D.

   
    Range("D1").Select
    Selection.AutoFilter
    With ActiveSheet
        .Range("D1:D" & .UsedRange.Rows.Count).AutoFilter Field:=1, Criteria1:="0"
    End With
    Selection.SpecialCells(xlCellTypeVisible).EntireRow.Delete

Open in new window

0
 
EdLBAuthor Commented:
Martin, that looks great! Can't get to it right now to try but I have another twist. I have the column heading as a named range called, surprisingly, "ProcessTimes." How would I incorporate use of the named range into your code.
Thanks, Ed
0
 
Martin LissOlder than dirtCommented:
That shouldn't be difficult but first lets see if it does what you want the way it is.
0
 
Rossano PraderiIT ConsultantCommented:
With the code posted by Martin you will delete the first row because there isn't any check.
The following code is not perfect and isn't the faster but is more secure

Sub delRows()
  Dim mRange As Range
  Application.Goto Reference:="ProcessTimes"
  Selection.AutoFilter
  ActiveSheet.Range("ProcessTimes").AutoFilter Field:=4, Criteria1:="0"
  Set mRange = Selection.SpecialCells(xlCellTypeVisible)
  If mRange.Areas.Item(1).Cells(1, 4).Value <> "0" Then mRange.Areas.Item(1).Rows(1).Hidden = True
    Selection.SpecialCells(xlCellTypeVisible).EntireRow.Delete
    Selection.AutoFilter
End Sub

Open in new window


Bregs
Rossano Praderi
0
 
Martin LissOlder than dirtCommented:
Dshortway is right. Using my original code the header would be deleted if there were no process times of zero. However that's easily fixed. Again this assumes that the process times are in column D.

    Range("D1").Select
    Selection.AutoFilter
    With ActiveSheet
        .Range("D1:D" & .UsedRange.Rows.Count).AutoFilter Field:=1, Criteria1:="0"
    End With
    If WorksheetFunction.CountIf(ActiveSheet.Columns(4), "0") > 0 Then
        ActiveSheet.Rows(1).Hidden = True
        Selection.SpecialCells(xlCellTypeVisible).EntireRow.Delete
        ActiveSheet.Rows(1).Hidden = False
    End If
    Selection.AutoFilter

Open in new window

0
 
EdLBAuthor Commented:
Neither solution worked. I have put together a sample file with the macro in it for illustration of the layout. "Process Times" is in column G but I put zeros in column D and it made no difference.
EliminateZeros.xlsm
0
 
FarWestConnect With a Mentor Commented:
here is the code which will delete rows in less than one second
using the idea I told you before
Sub delRows2()
Debug.Print Now()
Dim ii As Integer, rCount, fColumn
fColumn = 4 ' column to check value
rCount = ActiveSheet.UsedRange.Rows.Count
For ii = rCount To 2 Step -1 'end on 2 to exclude header 
If ActiveSheet.Cells(ii, fColumn) = 0 Then ActiveSheet.Rows(ii).EntireRow.Delete
Next
Debug.Print Now()
End Sub

Open in new window

good luck
0
 
EdLBAuthor Commented:
Thanks Martin and FarWest. Both work now. I appreciate the help. Not sure how to split up the points so I split them 50/50.
0
 
Martin LissOlder than dirtCommented:
You're welcome and I'm glad I was able to help.

In my profile you'll find links to some articles I've written that may interest you.
Marty - MVP 2009 to 2014
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.