0% found this document useful (0 votes)
30 views

Excel - How To Improve The Speed of VBA Macro Code - Stack Overflow

The document discusses how to improve the speed of a VBA macro that copies values from one worksheet to another. It provides the code for the macro, which is copying values but running slowly. Suggestions to speed it up include turning off screen updating and calculation during the macro, directly assigning values instead of using copy/paste, and avoiding accessing the spreadsheet repeatedly by storing frequently used ranges in variables.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views

Excel - How To Improve The Speed of VBA Macro Code - Stack Overflow

The document discusses how to improve the speed of a VBA macro that copies values from one worksheet to another. It provides the code for the macro, which is copying values but running slowly. Suggestions to speed it up include turning off screen updating and calculation during the macro, directly assigning values instead of using copy/paste, and avoiding accessing the spreadsheet repeatedly by storing frequently used ranges in variables.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

How to improve the speed of VBA macro code?

Asked 11 years ago Modified 7 years, 1 month ago Viewed 39k times

I do not have much experience with writing macros, and therefore need the help of this
community for the following issue encountered:
9
My macro copies a range of values entered in a vertical range in one worksheet and then
pastes the values horizontally (transpose) in another worksheet. It would in theory paste the
values from the first sheet to first row of the second worksheet which does not have content.
Since the first five rows have contents, it thus pastes the values to the sixth row. The problem
I have with the running of the macro is that I feel like it is too slow and I would therefore like it
to run faster.

I have the same macro doing the same thing but that instead pastes the values to another
worksheet to the first row, and it runs perfect.

My best guess is therefore that the second macro is running slow because it has to start
pasting on the sixth row and there may be some contents on the first 5 rows that take a lot of
time for the macro to go through (there a lot of cell references to other workbooks) to
determine where the next row for pasting should be. That is my best guess though and since I
hardly know anything about macros, I cannot say for sure what the problem is.

I hereby provide you with the code of my macro and sincerely hope that somebody can tell
me what is making my macro slow and provide me with a solution as to how to make it run
faster. I am thinking that a solution might potentially be that the macro should not consider
the first five rows of data and start pasting immediately on row 6 for the first entry. Then on
row 7 the next time, and etc. This might be a solution but I do not know how to write the code
in a way that it would do that.

Thank you for taking time and helping me to find a solution, here is the code:

Sub Macro1()
Application.ScreenUpdating = False

Dim historyWks As Worksheet


Dim inputWks As Worksheet

Dim nextRow As Long


Dim oCol As Long

Dim myCopy As Range


Dim myTest As Range

Dim lRsp As Long

Set inputWks = wksPartsDataEntry


Set historyWks = Sheet11

'cells to copy from Input sheet - some contain formulas


Set myCopy = inputWks.Range("OrderEntry2")
With historyWks
nextRow = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Row
End With

With inputWks
Set myTest = myCopy.Offset(0, 2)

If Application.Count(myTest) > 0 Then


MsgBox "Please fill in all the cells!"
Exit Sub
End If
End With

With historyWks
With .Cells(nextRow, "A")
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
End With
.Cells(nextRow, "B").Value = Application.UserName
oCol = 3
myCopy.Copy
.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True
Application.CutCopyMode = False
End With

'clear input cells that contain constants


With inputWks
On Error Resume Next
With myCopy.Cells.SpecialCells(xlCellTypeConstants)
.ClearContents
Application.GoTo .Cells(1) ', Scroll:=True
End With
On Error GoTo 0
End With

Application.ScreenUpdating = True
End Sub

vba excel

Share Edit Follow edited Feb 16, 2015 at 20:59 asked Oct 22, 2012 at 17:06
RubberDuck Miles
12k 5 50 95 159 2 6 12

10 That macro looks like it should go fast enough. I'd drop the Application.GoTo .Cells(1) and add
application.calculation= xlCalculationManual / application.Calculation =
xlCalculationAutomatic – nutsch Oct 22, 2012 at 17:16

Yea it runs in under a second for me. How long is it taking for you? – Stepan1010 Oct 22, 2012 at
18:34

I second that. I see nothing glaringly obvious with this code that would cause me to edit it down from
a programming standpoint. I think the issue is with 1) the size of the range being copied and 2) the
fact that the workbook being copied too has many cells linked to other workbooks. Also, the size of
the workbook itself could cause performance to be slower. Definitely, turn on / off calcs as @nutsch
as recommended and check the size of the workbook. Oh yeah, I can confirm that having to find the
6th row is NOT an issue here, as it's actually coded quite nicely to do that in a jiff! – Scott Holtzman
Oct 22, 2012 at 18:34
6 Because you turned calculation off, you'll need to set it to automatic again – SWa Oct 23, 2012 at 8:14

1 Also, some macros also run faster if you turn off Application.ScreenUpdating. However, don't forget to
turn it back on when you're done, and make especially sure to turn it back on even when your macro
gets errors (use appropriate error handling & recovery), because if you leave ScreenUpdating off it
leaves the app and user in a bad situation! As with Calculation, turning it off trades off ongoing
recalculations (or screen redraws) for one at the end. (Also note that restoring screen updating may
make the screen blink briefly.) (Also, Application.EnableEvents is another to look at.) – Erik Eidt Nov 7,
2012 at 1:46

Report this ad

Sorted by:
7 Answers
Highest score (default)

Just reiterating what has already been said:

7 Option Explicit

Sub Macro1()

'turn off as much background processes as possible


With Excel.Application
.ScreenUpdating = False
.Calculation = Excel.xlCalculationManual
.EnableEvents = False
End With

Dim historyWks As Excel.Worksheet


Dim inputWks As Excel.Worksheet

Dim nextRow As Long


Dim oCol As Long

Dim myCopy As Excel.Range


Dim myTest As Excel.Range

Dim lRsp As Long

Set inputWks = wksPartsDataEntry


Set historyWks = Sheet11

'cells to copy from Input sheet - some contain formulas


Set myCopy = inputWks.Range("OrderEntry2")

With historyWks
nextRow = .Cells(.Rows.Count, 1).End(Excel.xlUp).Offset(1, 0).Row
End With

With inputWks
Set myTest = myCopy.Offset(0, 2)

If Excel.Application.Count(myTest) > 0 Then


MsgBox "Please fill in all the cells!"
GoTo QuickExit
End If
End With

With historyWks
With .Cells(nextRow, 1)
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
End With
.Cells(nextRow, 2).Value = Excel.Application.UserName
oCol = 3
myCopy.Copy
.Cells(nextRow, 3).PasteSpecial Paste:=Excel.xlPasteValues,
Transpose:=True
Excel.Application.CutCopyMode = False
End With

'clear input cells that contain constants


With inputWks
On Error Resume Next
With myCopy.Cells.SpecialCells(Excel.xlCellTypeConstants)
.ClearContents
Excel.Application.Goto .Cells(1) ', Scroll:=True
End With
On Error GoTo 0
End With

Calculate

QuickExit

With Excel.Application
.ScreenUpdating = True
.Calculation = Excel.xlAutomatic
.EnableEvents = True
End With

End Sub

Get
I'd step through the updates
macro line-by-line to try to locate which line is slow.
on
questions
Another alternative -and
although not sure if it'll speed things up - is to avoid the clipboard and
lose the copy/pasteanswers
so you'd apply a method like the following to move the data:

Option Explicit

Sub WithoutPastespecial()

'WORKING EXAMPLE

Dim firstRange As Range


Dim secondRange As Range
Set firstRange = ThisWorkbook.Worksheets("Cut Sheet").Range("S4:S2000")
With ThisWorkbook.Worksheets("Cutsheets")
Set secondRange = .Range("A" & .Rows.Count).End(Excel.xlUp).Offset(1)
End With

With firstRange
Set secondRange = secondRange.Resize(.Rows.Count, .Columns.Count)
End With
secondRange.Value = firstRange.Value

End Sub

Share Edit Follow answered Jan 2, 2013 at 17:27


whytheq
34.6k 66 172 269

Best way to improve performance based on my experience is to work on variables in code


rather than accessing the spreadsheet every time you want to lookup a value. Save any range
7 you want to work with in a variable(variant) and then iterate through it as if it was the sheet.

dim maxRows as double


dim maxCols as integer.
dim data as variant
with someSheet
maxRows = .Cells(rows.count, 1).end(xlUp).row 'Max rows in
sheet
maxCols = .Cells(1, columns.count).end(xlToLeft).column 'max columns in
sheet
data = .Range(.Cells(1,1), .Cells(maxRows, maxCols)) 'copy range in a
variable
end with

From here you can access the data variable as if it was the spreadsheet like - data(row,
column) with MUCH MUCH faster read speed.

Share Edit Follow answered Mar 8, 2013 at 11:18


Potter Rafed
472 4 14

Please take a look at this article as well. How to speed up calculation and improve
performance...
5
By all means, Application.calculation= xlCalculationManual is usually the culprit. But we can
notice that volatile Excel sheet functions can mostly kill your application on large scale of
data processing and functional aspect.

Also, for your current code following post might not be directly relevant. I find it useful for tips
on over-all Excel/VBA performance optimization.

75 Excel speeding up tips


PS: I don't have enough reputation to comment on your post. So added as an answer..

Share Edit Follow answered Nov 7, 2012 at 6:06


bonCodigo
14.3k 1 48 91

2 "I don't have enough reputation to comment" now has over 10k rep... lol – Chrismas007 Aug 15, 2016
at 20:26

2 @Chrismas007 that happens :) not that active anymore – bonCodigo Aug 24, 2016 at 21:11

Just a few suggestions (would have posted as a comment but I guess I don't have the rep):

1. Try refering to cell addresses instead of named ranges (doubt this would be the cause
2
but may be causing some hit to performance)

2. Do your workbook formulas contain links to other workbooks? Try testing the code on a
file with broken links to see if it improves performance.

3. If neither of these are the issue, my guess is that if the formulas are overly complex,
there is probably some processing overhead being added. Try the code on a file
containing only values to see if there is any improved performance.

Share Edit Follow edited Jan 3, 2013 at 12:56 answered Jan 2, 2013 at 17:53
UberNubIsTrue
632 6 17

As suggested by a few others in the comments, you should definitely change


Application.Calculation to xlCalculationManual and rememeber to set it back to
1 xlcalculationAutomatic at the end. Also try setting Application.Screenupdating = False (and
turning that back on again too). Also, bear in mind that .Copy is a very inefficient way to copy
cell values - if you really just want the values, loop through the range setting .Value to the
.Values in the old range. If you need all the formatting, you're probably stuck with .Copy.

When you turn off the calc/screen refresh flags, please remember to turn them back on in all
circumstances (even when your program exits at a different point, or causes a runtime error).
Otherwise all sorts of bad things will happen. :)

Share Edit Follow answered Nov 30, 2012 at 1:20


Chris Rae
5,637 2 36 51

You can improve the speed by stopping calculation during changing cell value and after that
you can enable it. please follow the link. http://webtech-training.blogspot.in/2013/10/how-to-
0 stop-heavy-formula-calculation.html

Share Edit Follow answered Dec 20, 2013 at 16:51


Mohanlal Prajapati
336 2 12

.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True


Application.CutCopyMode = False
0
I wouldn't do that. Cut,copy & Paste operations are the costliest operations, in terms of
processor utilization, in an operating system.

Instead, you could just assign the value from one cell / range to an another cell / range, as in

Cells(1,1) = Cells(1,2) or Range("A1") = Range("B1")

Hope you got my point..

Share Edit Follow answered Sep 9, 2016 at 10:31


Karthikeyan Natarajan
105 1 1 7

You might also like