'Excel VBA Optimize Cycle
I apologize if already exist a similar question, but if yes, I not found.
I'm new to programming in VBA and still do not know much of it, now I'm trying to run a function that will verify if in a column "B" are repeated velores and if exist will check in a column "C" where the highest value, copying the lowest to another table and deleting it.
The code already does all this however need to run in tables of 65 000 lines and it takes a long time, never got for running these tables, because even when I run in tables with 5000 or 10000 lines takes approximately 6 to 15 minutes.
My question is if there is any way to optimize the cycle that I'm using, it will be better to use a For Each or maintain the Do While Loop?
Here is the code I am using:
Function Copy()
Worksheets("Sheet1").Range("A1:AQ1").Copy _
Destination:=Worksheets("Sheet2").Range("A1")
Dim lRow As Long
Dim lRow2 As Long
Dim Row As Long
Dim countA As Long
Dim countB As Long
Dim t As Double
lRow = 5000
Row = 2
countA = 0
countB = 0
Application.ScreenUpdating = False
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
Application.EnableEvents = False
Application.DisplayStatusBar = False
ActiveSheet.DisplayPageBreaks = False
lRow2 = lRow - 1
t = Timer
Do While lRow > 2
If (Cells.Item(lRow, "B") <> Cells.Item(lRow2, "B")) Then
lRow = lRow - 1
lRow2 = lRow - 1
Else
If (Cells.Item(lRow, "C") > Cells.Item(lRow2, "C")) Then
Sheets("Sheet1").Rows(lRow2).Copy Sheets("Sheet2").Rows(Row)
Rows(lRow2).Delete
lRow = lRow - 1
Row = Row + 1
countA = countA + 1
Else
Sheets("Sheet1").Rows(lRow).Copy Sheets("Sheet2").Rows(Row)
Rows(lRow).Delete
lRow = lRow - 1
Row = Row + 1
countB = countB + 1
End If
lRow2 = lRow2 - 1
End If
Loop
Application.DisplayStatusBar = True
ActiveWindow.View = ViewMode
Application.ScreenUpdating = False
MsgBox "A = " & countA & " B = " & countB & "Time (minutes): " & (Timer - t) / 60
End Function
Solution 1:[1]
Everything i could think of has already been mentioned above, however this code snippet might help someone out, it's the least you could do to make a macro faster (in case no interaction is required during runtime of the macro)
Run Optimize(True) at the start of your code, Optimize(False) at the end.
'Toggles unnecessary excel features
Sub Optimize(start As Boolean)
On Error Resume Next
With Application
.ScreenUpdating = Not (start)
.DisplayStatusBar = Not (start)
.EnableEvents = Not (start)
If start Then
.Calculation = xlCalculationManual
Else
.Calculation = xlCalculationAutomatic
End If
End With
On Error GoTo 0
End Sub
Solution 2:[2]
Typically it's faster to perform a single delete at the end of the loop.
Untested:
Function Copy()
Dim shtSrc As Worksheet, shtDest As Worksheet
Dim lRow As Long, Row As Long, viewmode
Dim countA As Long, countB As Long
Dim t As Double, rw As Range, rngDel As Range
lRow = 5000
Row = 2
countA = 0
countB = 0
Set shtSrc = Worksheets("Sheet1")
Set shtDest = Worksheets("Sheet2")
shtSrc.Range("A1:AQ1").Copy Destination:=shtDest.Range("A1")
Application.ScreenUpdating = False
viewmode = ActiveWindow.View
ActiveWindow.View = xlNormalView
Application.EnableEvents = False
Application.DisplayStatusBar = False
ActiveSheet.DisplayPageBreaks = False
t = Timer
Do While lRow > 2
Set rw = shtSrc.Rows(lRow)
If (rw.Cells(2) = rw.Cells(2).Offset(-1, 0)) Then
If (rw.Cells(3) > rw.Cells(3).Offset(-1, 0)) Then
rw.Offset(-1, 0).Copy shtDest.Rows(Row)
AddToRange rngDel, rw.Offset(-1, 0)
countA = countA + 1
Else
rw.Copy shtDest.Rows(Row)
AddToRange rngDel, rw
countB = countB + 1
End If
Row = Row + 1
End If
lRow = lRow - 1
Loop
'anything to delete?
If Not rngDel Is Nothing Then
rngDel.Delete
End If
Application.DisplayStatusBar = True
ActiveWindow.View = viewmode
Application.ScreenUpdating = False
MsgBox "A = " & countA & " B = " & countB & "Time (minutes): " & (Timer - t) / 60
End Function
'utility sub for building up a range
Sub AddToRange(rngTot, rng)
If rngTot Is Nothing Then
Set rngTot = rng
Else
Set rngTot = Application.Union(rng, rngTot)
End If
End Sub
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Richard Kraus |
| Solution 2 | Tim Williams |
