Suggestions on how to speed up loop - vba

I have the following code. I was wondering if there is an easy way to rewrite it so that it takes less time to run? Currently, I have about 13,000 rows to loop through and it takes approximate 3-5 minutes to run. Thanks!
Sheets("wkly").Activate
Dim i As Long
Lastrow = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To Lastrow
If Range("S" & i) > 0.005 Then
Range("Z" & i, "AA" & i).Copy
Range("AC" & i, "AD" & i).PasteSpecial xlPasteValues
End If
Application.ScreenUpdating = False
Next i

I believe this will help make it a lot faster. No looping and no copy and paste needed.
Application.ScreenUpdating = False
Application.Calculation = xlManual
Dim wks As Worksheet, Lastrow As Long
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("S1:S" & Lastrow).AutoFilter 1, ">.005"
'Assumes you will always have values greater than .005, if not you need to error trap
Dim rngFilter As Range
Set rngFilter = .Range("S2:S" & Lastrow).SpecialCells(xlCellTypeVisible) 'assumes row 1 is header row
rngFilter.Offset(, 10).Value = rngFilter.Offset(, 7).Value
rngFilter.Offset(, 11).Value = rngFilter.Offset(, 8).Value
End With
Application.ScreenUpdating = True
UPDATE
I know you accepted the answer already, but in case you want to know how to do this by using an array to loop through, here it is below:
Dim wks As Worksheet, varStore As Variant, Lastrow As Long, i As Long
Application.ScreenUpdating = False
Application.Calculation = xlManual
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
varStore = .Range("S2:S" & Lastrow)
For i = LBound(varStore, 1) To UBound(varStore, 1)
If varStore(i, 1) > 0.005 Then .Range("AC" & i + 2 & ":AD" & i + 2).Value = .Range("Z" & i + 2 & ":AA" & i + 2).Value
Next
End With
Application.ScreenUpdating = False

If you do operations on a large number of cells, copying them into an array and writing them back after the processing is usually the fastest. The following code runs in 0.04s on my machine (based on Scott's answer, but using arrays also for the writing):
Dim wks As Worksheet
Dim varCompare As Variant, varSource As Variant, varTarget As Variant
Dim Lastrow As Long, i As Long
Application.ScreenUpdating = False
Application.Calculation = xlManual
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
varCompare = .Range("S2:S" & Lastrow)
varSource = .Range("Z2:AD" & Lastrow)
varTarget = .Range("AC2:AD" & Lastrow)
For i = LBound(varCompare, 1) To UBound(varCompare, 1)
If varCompare(i, 1) > 0.005 Then
varTarget(i, 1) = varSource(i, 1)
varTarget(i, 2) = varSource(i, 2)
End If
Next
.Range("AC2:AD" & Lastrow).Value = varTarget
End With
Application.ScreenUpdating = False

Given all the good tips, and include the following too. Please give a try and see how much performance boost you could achieve.
Application.Calculation = xlCalculationManual
lastrow = Range("S" & Rows.Count).End(xlUp).Rows
For i = 1 To lastrow
If Range("S1").Offset(i) > 0.005 Then
Range("AC").Offset(i).Resize(1, 2).Value = Range("Z").Offset(i).Resize(1, 2).Value
End If
Next i

Related

optimize find duplicate values for data set in excess of 200,000

I am new to coding and need help with a code that won't complete. I suspect it is due to the size of the data set. I tested the code using a reduced data set and it processes fine. However, my actual data set is over 210,000 rows and is expected to grow.
Is there a way to speed this up? Thank you for your assistance
Sub DupValidation()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim i As Long
Dim lastrow As Long
Dim lastrow2 As Long
Set wb = ActiveWorkbook
Set ws1 = wb.Worksheets("Tickets")
lastrow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
ws1.Range("g2:g" & lastrow).ClearContents
i = 2
Do While i <= lastrow
If Application.CountIf(ws1.Range(ws1.Cells(2, 2), ws1.Cells(lastrow, 2)), ws1.Cells(i, 2)) > 1 Then
ws1.Cells(i, 7).Value = True
End If
i = i + 1
Loop
End Sub
May be better
Sub Check_Duplicates_Using_Evaluate()
With Range("B2", Range("B" & Rows.Count).End(xlUp))
.Offset(, 5).Value = .Parent.Evaluate("IF(COUNTIF(" & .Address & "," & .Address & ")>1,""True"","""")")
End With
End Sub

VBA - Hide rows macro limit

I have the code below to hide all blank cells on my sheet. How do I set the hide range to 100 so after cell 100 if the remaining ones are blank it doesn't hide them. Only cells within the 1-100 limit get hidden if blank.
Sub HideRow()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Projects Dashboard")
Dim LRowC, LRowD, LRowF, LRowH, LRow As Long
LRowC = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
LRowD = ws.Range("D" & ws.Rows.Count).End(xlUp).Row
LRowF = ws.Range("F" & ws.Rows.Count).End(xlUp).Row
LRowH = ws.Range("H" & ws.Rows.Count).End(xlUp).Row
LRow = Application.WorksheetFunction.Max(LRowC, LRowD, LRowF, LRowH)
Dim I As Long
Application.ScreenUpdating = False
ws.Rows.Hidden = False
For I = LRow To 7 Step -1
If ws.Range("C" & I).Text = "" And ws.Range("D" & I).Text = "" And ws.Range("F" & I).Text = "" And ws.Range("I" & I).Text = "" Then
ws.Rows(I).EntireRow.Hidden = True
End If
Next I
Application.ScreenUpdating = True
End Sub
If I understand your question and code, it seems that you would want limit your LRow value to be a max of 100.
Should be as simple as adding one line of code:
...
LRow = Application.WorksheetFunction.Max(LRowC, LRowD, LRowF, LRowH)
If LRow > 100 Then LRow = 100
Dim I As Long
...

Ignore empty cells in for each VBA

I am having a problem with my loop(i go throu columns in every worksheet and copy them common column ) in VBA. And I wan't to ignore empty cells... any ideas? Bellow is my code
Application.ScreenUpdating = False
lastRowMaster = 1
For Each Ws In Sheets(Array("1L", "5L"))
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
Ws.Range("A1:A" & lastRow).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
lastRowMaster = Worksheets("Podatki plana").Range("A" & Rows.Count).End(xlUp).row + 1
Next
Application.ScreenUpdating = True
MsgBox "Done!"
I altered this line of code:
Ws.Range("A1:A" & lastRow).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
To this:
Ws.Range("A1:A" & lastRow).SpecialCells(xlCellTypeConstants).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
Using the .SpecialCells(xlCellTypeConstants) qualifier selects only cells that have a value in them. You could change xlCellTypeConstants to xlCellTypeFormulas or any of the options listed on this MSDN article.
The benefit with this is that you don't have to loop through each cell, which is a perfectly good solution but comes with a performance penalty.
Tested in Excel 2013.
Maybe just set each of the destination cells to the origin cell when the cell is not empty, like so
Application.ScreenUpdating = False
lastRowMaster = 1
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
nextRow = 1
For Each Ws In Sheets(Array("1L", "5L"))
for i = 1 to lastRow
if Not IsEmpty(Ws.Cells(i, 1)) then
Worksheets("Podatkiplana").cells(nextRow, 1) = Ws.cells(i,1)
nextRow = nextRow + 1
end if
next i
Next
Application.ScreenUpdating = True
MsgBox "Done!"
Application.ScreenUpdating = False
lastRowMaster = 1
For Each Ws In Sheets(Array("1L", "5L"))
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
For i = 1 to lastrow
lastRowMaster = Worksheets("Podatki plana").Range("A" & rows.Count).End(xlUp).row + 1
If ws.cells(i, 1)<> "" Then Worksheets("Podatki plana").Cells(lastRowMaster, 1) = ws.cells(i,1)
next i
Next
Application.ScreenUpdating = True
MsgBox "Done!"

VBA Excel AutoFilter Error

I am getting following error when trying to auto filter in vba:
The object invoked has disconnected from its clients.
So what i am trying to do is auto filter, search for empty spaces and delete the rows. Can anyone please help?
I have tried the standard solutions provided online e.g. option explicit etc but to no avail.
Data:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Worksheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
Set ws = Worksheets(1)
Set Rng = Worksheets(1).Range("A2:A" & lngLastRowD)
With Rng
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ws.AutoFilterMode = False
Application.ScreenUpdating = True
ThisWorkbook.Sheets(1).Range("A2").Select
End Sub
Since Worksheets() want the name of the sheet, like "Sheet1", use sheets(1).
Why are you creating the variable ws and rng when you only use them once
I ran this and it deleted rows with no data in column A.
Private Sub Worksheet_Change()
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
sheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
With sheets(1).Range("A2:A" & lngLastRowD)
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
sheets(1).AutoFilterMode = False
Application.ScreenUpdating = True
Sheets(1).Range("A2").Select
End Sub
In the end i restored in approaching the issue from another angle:
Dim i As Integer, counter As Integer
i = 2
For counter = 1 To lngLastRowD
If Worksheets(1).Range("A2:A" & lngLastRowD).Cells(i) = "" And Worksheets(1).Range("D2:D" & lngLastRowD).Cells(i) <> "" Then
Worksheets(1).Range("A2:A" & lngLastRowD).Range("A" & i & ":D" & lngLastRowD).Select
Selection.Delete
GoTo TheEND
Else
i = i + 1
Debug.Print "i is " & i
End If
Next

Pasting value only, Excel VBA

I have this script that I had help with already, but now comes an issue. I am attempting to paste only the value, not the formula that is inside the cell to another cell.
I thought placing the .Value at the end of formula would tell the script to paste only the value... it seems not to be. Can someone give me a suggestion on how to make this work?
Option Explicit
Sub ONJL()
Dim lastrow As Long
Dim wsPAR As Worksheet 'PAERTO
Dim wsRD As Worksheet 'Raw Data
Dim wsTEM As Worksheet 'Archive
Set wsPAR = Sheets("PAERTO")
Set wsRD = Sheets("Raw Data")
Set wsTEM = Sheets("Template")
With wsRD
Application.ScreenUpdating = False
lastrow = .Range("J" & .Rows.Count).End(xlUp).Row
wsRD.Range("J" & lastrow + 1).Formula = Date
wsRD.Range("B2").Copy wsRD.Range("K" & lastrow + 1).Value
wsRD.Range("B3").Copy wsRD.Range("L" & lastrow + 1).Value
wsRD.Range("E2").Copy wsRD.Range("M" & lastrow + 1).Value
wsRD.Range("E3").Copy wsRD.Range("N" & lastrow + 1).Value
wsRD.Range("H2").Copy wsRD.Range("O" & lastrow + 1).Value
wsRD.Range("H3").Copy wsRD.Range("P" & lastrow + 1).Value
wsRD.Range("Q1:T1").Copy wsRD.Range("Q" & lastrow + 1)
Application.ScreenUpdating = False
End With
End Sub
You can "copy" without actually using .Copy like this:
Sub CopyWithoutCopying()
Dim wsRD As Worksheet
Dim lastrow As Long
Set wsRD = Sheets("Raw Data")
With wsRD
lastrow = .Range("J" & .Rows.Count).End(xlUp).Row
.Range("K" & lastrow + 1).Value = .Range("B2").Value
.Range("L" & lastrow + 1).Value = .Range("B3").Value
' etc...
End With
End Sub
This approach doesn't use your clipboard, performs better, and doesn't select anything. And as Jimmy points out, you don't need the wsRD prefix inside the With block.