I have vba code that loops through a large number of records and deletes rows based on criteria. The issue at hand is that it takes far too long to run. I have never actually let it finish because it takes so long (about five minutes puts it around row 700 out of ~250000). Basically, I need to loop through and see if cell contents contain the string template (or some variation as shown in code below) and if so delete that row.
First Attempt
lr = sht.Cells(Rows.Count, 1).End(xlUp).Row 'LastRow For i = lr To 2 Step -1 If sht.Cells(i, 1).Value Like "*template*" Or sht.Cells(i, 1).Value Like "*TEMPLATE*" _ Or sht.Cells(i, 1).Value Like "*Template*" Or _ sht.Cells(i, 3).Value Like "*template*" Or sht.Cells(i, 3).Value Like "*TEMPLATE*" _ Or sht.Cells(i, 3).Value Like "*Template*" Then sht.Cells(i, 1).EntireRow.delete End If Next i but after This Post on SO, I tried reworking it.
Second Attempt (and currently in use)
Dim delete as Range Set delete = Nothing Set myRange = sht.Range("A2", sht.Cells(lr, 1)) For Each myCell In myRange If myCell.Value Like "*template*" Or myCell.Value Like "*TEMPLATE*" _ Or myCell.Value Like "*Template*" Or myCell.Offset(0, 2).Value Like "*template*" _ Or myCell.Offset(0, 2).Value Like "*TEMPLATE*" _ Or myCell.Offset(0, 2).Value Like "*Template*" Then If Not delete Is Nothing Then Set delete = Union(delete, myCell) Else Set delete = myCell End If End If Next myCell If Not delete Is Nothing Then delete.EntireRow.delete End If Full Code (You asked for it....)
Public Sub EntitlementReport() Application.ScreenUpdating = False Dim accountBook As Workbook, entitlementsBk As Workbook, groupBk As Workbook Dim wb As Workbook, final As Workbook Dim sht As Worksheet Dim aBkFound As Boolean, eBkFound As Boolean, gBkFound As Boolean aBkFound = False eBkFound = False gBkFound = False Set final = ActiveWorkbook Set sht = final.Sheets(1) For Each wb In Workbooks If wb.name Like "Accounts*" Then Set accountBook = wb aBkFound = True ElseIf wb.name Like "GroupMembership*" Then Set groupBk = wb gBkFound = True ElseIf wb.name Like "UserEntitlements*" Then Set entitlementsBk = wb eBkFound = True End If If aBkFound And gBkFound And eBkFound Then Exit For End If Next wb If Not aBkFound Then MsgBox ("Could not find the Accounts file. Please make sure it is open." & vbNewLine & _ "Exiting procedure.") End End If If Not eBkFound Then MsgBox ("Could not find the UserEntitlements file. Please make sure it is open." & vbNewLine & _ "Exiting procedure.") End End If If Not gBkFound Then MsgBox ("Could not find the GroupMembers file. Please make sure it is open." & vbNewLine & _ "Exiting procedure.") End End If Dim ws As Worksheet For Each ws In final.Worksheets If ws.name = "Entitlements" Or ws.name = "Groups" Or ws.name = "Accounts" Then Application.DisplayAlerts = False ws.delete Application.DisplayAlerts = True End If Next ws final.Sheets.Add after:=final.Sheets(1) ActiveSheet.name = "Entitlements" final.Sheets.Add after:=final.Sheets(1) ActiveSheet.name = "Groups" final.Sheets.Add after:=final.Sheets(1) ActiveSheet.name = "Accounts" sht.Cells.Clear Dim eSht As Worksheet, gSht As Worksheet, aSht As Worksheet Set eSht = final.Sheets("Entitlements") Set gSht = final.Sheets("Groups") Set aSht = final.Sheets("Accounts") Dim lr As Long, lc As Long lr = groupBk.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row lc = groupBk.Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Column With groupBk.Sheets(1) lr = .Cells(Rows.Count, 1).End(xlUp).row lc = .Cells(1, Columns.Count).End(xlToLeft).Column .Range("A1", .Cells(lr, lc)).Copy End With gSht.Range("A1").PasteSpecial xlPasteAll Application.CutCopyMode = False lr = accountBook.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row lc = accountBook.Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Column With accountBook.Sheets(1) lr = .Cells(Rows.Count, 1).End(xlUp).row lc = .Cells(1, Columns.Count).End(xlToLeft).Column .Range("A1", .Cells(lr, lc)).Copy End With aSht.Range("A1").PasteSpecial xlPasteAll Application.CutCopyMode = False aSht.Range("A1", aSht.Cells(lr, lc)).RemoveDuplicates Columns:=2, header:=xlYes lr = entitlementsBk.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row lc = entitlementsBk.Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Column With entitlementsBk.Sheets(1) lr = .Cells(Rows.Count, 1).End(xlUp).row lc = .Cells(1, Columns.Count).End(xlToLeft).Column .Range("A1", .Cells(lr, lc)).Copy End With eSht.Range("A1").PasteSpecial xlPasteAll Application.CutCopyMode = False Dim myRange As Range, myCell As Range Set myRange = eSht.Range("A1", eSht.Cells(lr, lc)) For Each myCell In myRange myCell.Value = Replace(myCell.Value, Chr(34), vbNullString) Next myCell Dim sortRange As Range Set sortRange = eSht.Range(eSht.Cells(1, "G"), eSht.Cells(lr, "G")) eSht.Range("G1").AutoFilter eSht.AutoFilter.sort.SortFields.Clear eSht.AutoFilter.sort.SortFields.Add key:=sortRange, SortOn:=xlSortOnValues, _ Order:=xlAscending, DataOption:=xlSortNormal With eSht.AutoFilter.sort .header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With eSht.Range("G1").AutoFilter Set sortRange = eSht.Range(eSht.Cells(2, "G"), eSht.Cells(lr, "G")) Set myRange = gSht.Range(gSht.Cells(2, 1), _ gSht.Cells(gSht.Cells(Rows.Count, 1).End(xlUp).row, 1)) Dim nextOpenRow As Long nextOpenRow = 2 For Each myCell In sortRange Set c = myRange.Find(myCell.Offset(0, -2).Value) If Not c Is Nothing Then firstAddress = c.address Do sht.Cells(nextOpenRow, 1).Value = c.Offset(0, 2).Value sht.Cells(nextOpenRow, 2).Value = c.Offset(0, 3).Value & ", " & c.Offset(0, 4).Value sht.Cells(nextOpenRow, 3).Value = myCell.Offset(0, -1).Value sht.Cells(nextOpenRow, 4).Value = myCell.Value sht.Cells(nextOpenRow, 5).Value = myCell.Offset(0, 3).Value sht.Cells(nextOpenRow, 6).Value = myCell.Offset(0, -2).Value nextOpenRow = nextOpenRow + 1 Set c = myRange.FindNext(c) Loop While Not c Is Nothing And c.address <> firstAddress End If Next myCell ' For Each myCell In sortRange ' Set myRange = gSht.Range(gSht.Cells(2, 1), _ ' gSht.Cells(gSht.Cells(Rows.Count, 1).End(xlUp).row, 1)) ' On Error GoTo Finish ' Do ' c = Application.WorksheetFunction.Match(myCell.Offset(0, -2).Value, myRange, 0) ' sht.Cells(nextOpenRow, 1).Value = myRange(c, 1).Offset(0, 2).Value ' sht.Cells(nextOpenRow, 2).Value = myRange(c, 1).Offset(0, 3).Value ' sht.Cells(nextOpenRow, 3).Value = myCell.Offset(0, -1).Value ' sht.Cells(nextOpenRow, 4).Value = myCell.Value ' sht.Cells(nextOpenRow, 5).Value = myCell.Offset(0, 3).Value ' sht.Cells(nextOpenRow, 6).Value = myCell.Offset(0, -2).Value ' nextOpenRow = nextOpenRow + 1 ' Set myRange = myRange.Resize(myRange.Rows.Count - c, 1).Offset(c, 0) ' Loop 'Finish: ' Resume NextCell 'NextCell: ' Next myCell ' ' On Error GoTo 0 sht.Cells(1, 1).Value = "UserID" sht.Cells(1, 2).Value = "User" sht.Cells(1, 3).Value = "System Name" sht.Cells(1, 4).Value = "Account Name" sht.Cells(1, 5).Value = "Policy Name" sht.Cells(1, 6).Value = "Group Name" sht.Cells(1, 7).Value = "Owner Name" lr = sht.Cells(Rows.Count, 1).End(xlUp).row lc = sht.Cells(1, Columns.Count).End(xlToLeft).Column Dim delete As Range On Error Resume Next Set delete = sht.Range(sht.Cells(1, 4), sht.Cells(lr, 4)).SpecialCells(xlCellTypeBlanks) On Error GoTo 0 delete.EntireRow.delete Set delete = Nothing lr = sht.Cells(Rows.Count, 1).End(xlUp).row ' ' For i = lr To 2 Step -1 ' If sht.Cells(i, 1).Value Like "*template*" Or sht.Cells(i, 1).Value Like "*TEMPLATE*" _ ' Or sht.Cells(i, 1).Value Like "*Template*" Or _ ' sht.Cells(i, 3).Value Like "*template*" Or sht.Cells(i, 3).Value Like "*TEMPLATE*" _ ' Or sht.Cells(i, 3).Value Like "*Template*" Then ' sht.Cells(i, 1).EntireRow.delete ' End If ' Next i ' Set myRange = sht.Range("A2", sht.Cells(lr, 1)) For Each myCell In myRange If myCell.Value Like "*template*" Or myCell.Value Like "*TEMPLATE*" _ Or myCell.Value Like "*Template*" Or myCell.Offset(0, 2).Value Like "*template*" _ Or myCell.Offset(0, 2).Value Like "*TEMPLATE*" _ Or myCell.Offset(0, 2).Value Like "*Template*" Then If Not delete Is Nothing Then Set delete = Union(delete, myCell) Else Set delete = myCell End If End If Next myCell If Not delete Is Nothing Then delete.EntireRow.delete End If Set ws = Nothing Set wb = Nothing Set accountBook = Nothing Set entitlementsBk = Nothing Set groupBk = Nothing Set final = Nothing Set eSht = Nothing Set gSht = Nothing Set myRange = Nothing Set myCell = Nothing Set sortRange = Nothing Set delete = Nothing Set c = Nothing Application.ScreenUpdating = True End Sub Question Is there a better, more efficient way to loop through the large amount of data I have, and delete rows with this criteria?
Option Explicitspecified at the top of the module? \$\endgroup\$