Here are all the possible options I could think of with an "average time" to complete the tasks:
Option Base 1
Option Explicit
Sub FixWithArraysAndDeleteRange()
Dim lngItem As Long
Dim varArray() As Variant
Dim wksItem As Worksheet
Dim rngRangeToDelete As Range
Dim dttStart As Date
Worksheets(1).Range("I25:I50000").Formula = "=RandBetween(1, 5)"
Worksheets(1).Range("I25:I50000").Value2 = Worksheets(1).Range("I25:I50000").Value2
dttStart = Now()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Set wksItem = Worksheets(1)
varArray() = wksItem.Range("I25:I50000").Value2
For lngItem = LBound(varArray) To UBound(varArray)
If IsNumeric(varArray(lngItem, 1)) Then
If Int(varArray(lngItem, 1)) = 2 Then
If rngRangeToDelete Is Nothing Then
Set rngRangeToDelete = wksItem.Rows(lngItem + 24)
Else
Set rngRangeToDelete = Intersect(rngRangeToDelete, wksItem.Rows(lngItem + 24))
End If
End If
End If
Next lngItem
rngRangeToDelete.EntireRow.Delete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Debug.Print Format(Now() - dttStart, "HH:MM:SS")
'Average time around 0 seconds
End Sub
Sub FixWithLoop()
Dim lngRow As Long
Dim lngLastRow As Long
Dim wksItem As Worksheet
Dim dttStart As Date
Worksheets(1).Range("I25:I50000").Formula = "=RandBetween(1, 5)"
Worksheets(1).Range("I25:I50000").Value2 = Worksheets(1).Range("I25:I50000").Value2
dttStart = Now()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Set wksItem = Worksheets(1)
lngLastRow = wksItem.Cells(wksItem.Rows.Count, "I").End(xlUp).Row
For lngRow = lngLastRow To 25 Step -1
If Int(wksItem.Cells(lngRow, "I").Value) = 2 Then wksItem.Rows(lngRow).Delete
Next lngRow
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Debug.Print Format(Now() - dttStart, "HH:MM:SS")
'Average time ~3 seconds
End Sub
Sub FixWithLoopInChunks()
Dim lngRow As Long
Dim lngLastRow As Long
Dim wksItem As Worksheet
Dim strRowsToDelete As String
Dim intDeleteCount As Integer
Dim dttStart As Date
Worksheets(1).Range("I25:I50000").Formula = "=RandBetween(1, 5)"
Worksheets(1).Range("I25:I50000").Value2 = Worksheets(1).Range("I25:I50000").Value2
dttStart = Now()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Set wksItem = Worksheets(1)
lngLastRow = wksItem.Cells(wksItem.Rows.Count, "I").End(xlUp).Row
For lngRow = lngLastRow To 25 Step -1
If Int(wksItem.Cells(lngRow, "I").Value) = 2 Then
intDeleteCount = intDeleteCount + 1
strRowsToDelete = strRowsToDelete & ",I" & lngRow
End If
If intDeleteCount >= 30 Then
strRowsToDelete = Mid(strRowsToDelete, 2)
wksItem.Range(strRowsToDelete).EntireRow.Delete
intDeleteCount = 0
strRowsToDelete = ""
End If
Next lngRow
If intDeleteCount > 0 Then
strRowsToDelete = Mid(strRowsToDelete, 2)
wksItem.Range(strRowsToDelete).EntireRow.Delete
End If
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Debug.Print Format(Now() - dttStart, "HH:MM:SS")
'Average time ~3 seconds
End Sub
Sub FixWithArraysAndDeleteChunks()
Dim lngItem As Long
Dim varArray() As Variant
Dim wksItem As Worksheet
Dim strRowsToDelete As String
Dim intDeleteCount As Integer
Dim dttStart As Date
Worksheets(1).Range("I25:I50000").Formula = "=RandBetween(1, 5)"
Worksheets(1).Range("I25:I50000").Value2 = Worksheets(1).Range("I25:I50000").Value2
dttStart = Now()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Set wksItem = Worksheets(1)
varArray() = wksItem.Range("I25:I50000").Value2
For lngItem = UBound(varArray) To LBound(varArray) Step -1
If IsNumeric(varArray(lngItem, 1)) Then
If Int(varArray(lngItem, 1)) = 2 Then
intDeleteCount = intDeleteCount + 1
strRowsToDelete = strRowsToDelete & ",I" & lngItem + 24
End If
If intDeleteCount >= 30 Then
strRowsToDelete = Mid(strRowsToDelete, 2)
wksItem.Range(strRowsToDelete).EntireRow.Delete
intDeleteCount = 0
strRowsToDelete = ""
End If
End If
Next lngItem
If intDeleteCount > 0 Then
strRowsToDelete = Mid(strRowsToDelete, 2)
wksItem.Range(strRowsToDelete).EntireRow.Delete
End If
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Debug.Print Format(Now() - dttStart, "HH:MM:SS")
'Average time ~2 seconds
End Sub
Based on the above tests the "fastest" route is to use an array, save the range of rows to be deleted using Intersect
and then delete all rows together.
Note, if you are using Application.Union
instead of Intersect
then the time of that approach drops significantly and the sub will run for almost 30 seconds.
Yet, the time difference is very small and negligible (for 50.000 rows).
Please do let me know if my speed-test-setup has any flaws which might bias the results or if I am missing another approach you would like to see.
Update:
Here is another approach offered by @SiddharthRout. I do not wish to plagiarise. Yet, I wanted to compare time results. Hence, here is the sub rewritten to compare to the others with the average time recorded on my system.
Sub DeleteFilteredRows_SiddharthRout()
Dim wksItem As Worksheet
Dim rngRowsToDelete As Range
Dim dttStart As Date
Worksheets(1).Range("I25:I50000").Formula = "=RandBetween(1, 5)"
Worksheets(1).Range("I25:I50000").Value2 = Worksheets(1).Range("I25:I50000").Value2
dttStart = Now()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Set wksItem = Worksheets(1)
wksItem.AutoFilterMode = False
wksItem.Range("I25:I50000").AutoFilter Field:=1, Criteria1:=2
Set rngRowsToDelete = wksItem.Range("I25:I50000").SpecialCells(xlCellTypeVisible)
wksItem.AutoFilterMode = False
wksItem.Rows.Hidden = False
rngRowsToDelete.EntireRow.Delete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Debug.Print Format(Now() - dttStart, "HH:MM:SS")
'Average time around 5 seconds
End Sub
It seems that this approach is slightly slower compared to all the others.