VBA to Delete Table Rows Based on Two Columns

nirvehex

Well-known Member
Joined
Jul 27, 2011
Messages
503
Office Version
  1. 365
Platform
  1. Windows
Hello All,

I'm trying to write some VBA code that deletes table rows based on data in two columns. The two columns have Headers "LocationCode" and "ServiceType" in my Table, which is "Table2".

What I'm trying to do is look at all like values in the "LocationCode" column and see if there is a row under the "ServiceType" column that has an "H".

If it DOES NOT have an "H" under ServiceType for that LocationCode I want to delete the row.

For example, in the below table, all of the "Loc00002" rows would get deleted because there is no corresponding "H" in the ServiceType column. The other two locations, no lines would get deleted. Any ideas how to code this? Thank you!!

LocationCodeServiceType
Loc000001H
Loc000001Z
Loc000001TST
Loc00002CCS
Loc00002ROC
Loc0000003H
Loc0000003H
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
Try the following macro...

VBA Code:
Option Explicit

Sub Delete_Non_H_Locations()

    'create a dictionary object to hold unique location codes
    Dim locationsDictionary As Object
    Set locationsDictionary = CreateObject("Scripting.Dictionary")
    
    'set dictionary to case-insensitive comparison mode
    locationsDictionary.comparemode = 1 'vbTextCompare
    
    'set the source table (change the sheet name accordingly)
    Dim sourceTable As ListObject
    Set sourceTable = Worksheets("Sheet1").ListObjects("Table2")
    
    'if source table is filtered, clear any and all filters
    With sourceTable
        If .ShowAutoFilter Then
            If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData
        End If
    End With
    
    'loop through each cell in LocationCode column and fill dictionary with unique location codes
    Dim currentCell As Range
    For Each currentCell In sourceTable.ListColumns("LocationCode").DataBodyRange
        locationsDictionary(currentCell.Value) = ""
    Next currentCell
    
    'filter source table for each unique location, and delete all rows if it doesn't have a service type "H"
    With sourceTable
        Dim currentKey As Variant
        For Each currentKey In locationsDictionary
            .Range.AutoFilter field:=.ListColumns("LocationCode").Index, Criteria1:=currentKey
            If Application.CountIf(.ListColumns("ServiceType").DataBodyRange.SpecialCells(xlCellTypeVisible), "H") = 0 Then
                With .Range
                    .Offset(1, 0).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
                End With
            End If
        Next currentKey
        .AutoFilter.ShowAllData
    End With
    
End Sub

Hope this helps!
 
Upvote 0
Here is another macro for you to consider

VBA Code:
Sub test()
  Dim dic As Object, i As Long, m As Variant, tbl As ListObject
  
  Set dic = CreateObject("scripting.dictionary")
  Set tbl = ActiveSheet.ListObjects("Table2")
  
  If tbl.ShowAutoFilter Then tbl.Range.AutoFilter
  For i = 1 To tbl.ListRows.Count
    m = tbl.DataBodyRange(i, tbl.ListColumns("LocationCode").Index).Value
    If WorksheetFunction.CountIfs(tbl.ListColumns("LocationCode").DataBodyRange, m, tbl.ListColumns("ServiceType").DataBodyRange, "H") = 0 Then
      dic(m) = Empty
    End If
  Next
  
  If dic.Count > 0 Then
    tbl.Range.AutoFilter tbl.ListColumns("LocationCode").Index, dic.keys, xlFilterValues
    tbl.AutoFilter.Range.Offset(1).EntireRow.Delete
    If tbl.ShowAutoFilter Then tbl.Range.AutoFilter
  End If
End Sub
 
Upvote 0
Try the following macro...

VBA Code:
Option Explicit

Sub Delete_Non_H_Locations()

    'create a dictionary object to hold unique location codes
    Dim locationsDictionary As Object
    Set locationsDictionary = CreateObject("Scripting.Dictionary")
   
    'set dictionary to case-insensitive comparison mode
    locationsDictionary.comparemode = 1 'vbTextCompare
   
    'set the source table (change the sheet name accordingly)
    Dim sourceTable As ListObject
    Set sourceTable = Worksheets("Sheet1").ListObjects("Table2")
   
    'if source table is filtered, clear any and all filters
    With sourceTable
        If .ShowAutoFilter Then
            If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData
        End If
    End With
   
    'loop through each cell in LocationCode column and fill dictionary with unique location codes
    Dim currentCell As Range
    For Each currentCell In sourceTable.ListColumns("LocationCode").DataBodyRange
        locationsDictionary(currentCell.Value) = ""
    Next currentCell
   
    'filter source table for each unique location, and delete all rows if it doesn't have a service type "H"
    With sourceTable
        Dim currentKey As Variant
        For Each currentKey In locationsDictionary
            .Range.AutoFilter field:=.ListColumns("LocationCode").Index, Criteria1:=currentKey
            If Application.CountIf(.ListColumns("ServiceType").DataBodyRange.SpecialCells(xlCellTypeVisible), "H") = 0 Then
                With .Range
                    .Offset(1, 0).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
                End With
            End If
        Next currentKey
        .AutoFilter.ShowAllData
    End With
   
End Sub

Hope this helps!

Domenic,

Thanks for the detailed explanations in each section! That was so helpful!
 
Upvote 0
Here is another macro for you to consider

VBA Code:
Sub test()
  Dim dic As Object, i As Long, m As Variant, tbl As ListObject
 
  Set dic = CreateObject("scripting.dictionary")
  Set tbl = ActiveSheet.ListObjects("Table2")
 
  If tbl.ShowAutoFilter Then tbl.Range.AutoFilter
  For i = 1 To tbl.ListRows.Count
    m = tbl.DataBodyRange(i, tbl.ListColumns("LocationCode").Index).Value
    If WorksheetFunction.CountIfs(tbl.ListColumns("LocationCode").DataBodyRange, m, tbl.ListColumns("ServiceType").DataBodyRange, "H") = 0 Then
      dic(m) = Empty
    End If
  Next
 
  If dic.Count > 0 Then
    tbl.Range.AutoFilter tbl.ListColumns("LocationCode").Index, dic.keys, xlFilterValues
    tbl.AutoFilter.Range.Offset(1).EntireRow.Delete
    If tbl.ShowAutoFilter Then tbl.Range.AutoFilter
  End If
End Sub

Thanks for the alternative solution!
 
Upvote 0
I'm glad to help you. Thanks for the feedback.
 
Upvote 0

Forum statistics

Threads
1,214,429
Messages
6,119,433
Members
448,897
Latest member
ksjohnson1970

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top