I have a very simple VBA code running in workbook A that is rather slow when another specific workbook B is open. I don't have access to any macros inside workbook B, so I can't know for sure if anything wierd is happening there.
I've looked around and came with this minimal code condensing the typical solutions I've found in stackoverflow and many Excel specific sites, but it still takes a long time to run.
' Code in workbook A
Sub slow_simple_macro()
With Application
.Calculation = xlCalculationManual
.EnableEvents = False
.ScreenUpdating = False
.DisplayStatusBar = False
End with
Workbooks("workbookA.xlsm").Sheets("Sheet1").Range("A1") = "Slow" ' This line takes about half a second to run when workbook B is open
With Application
.Calculation = xlCalculationAutomatic
.EnableEvents = True
.ScreenUpdating = True
.DisplayStatusBar = True
End with
End Sub
I'm guessing that disabling events is not enough to prevent something inside workbook B from running. Are there any other Application flags I can setup to make it run faster? Any other ideas?
You can see while disabling some functions of excel like calculation mode, screenupdates,status bar would impact on application of Excel because "Excel is the one of The object model that is a large hierarchy of all the objects used in VBA" (Source:www.globaliconnect.com).
So if you want run by turn off application functions , you should be wait till you set back to its original or else same problem would happen.
Better simplify code as possible unless if its required
Sub slow_simple_macro()
Workbooks("workbookA.xlsm").Sheets("Sheet1").Range("A1") = "Slow"
End Sub
Hope you find it as helpful. Have a good day.
Related
I used to have this formula below copied into multiple cells, but at some point it wasn't pulling the data properly so I had to modify it to the formula below it. The SUMPRODUCT formula finds data from another spreadsheet based off the part number and pulls it over to the new spreadsheet.
=IFERROR(VLOOKUP($B14,'G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDCPIV'!$A:$W,13,FALSE),0)
=IFERROR(SUMPRODUCT(('G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDC SD'!$F$4:$AT$10000)*('G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDC SD'!$A$4:$A$10000=$B14)*('G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDC SD'!$F$3:$AT$3=$AD$13)),0)
I run a macro that someone else made which, besides doing other things, fills down this formula a couple hundred rows. Now when I run it with the new formula it takes ages compared to how long it used to take. Is there a better way I can go about this to speed it up?
I would recommend these three basic things, that will help you without modifying much your code.
First: Change VLOOKUP or SUMPRODUCT to "XLOOKUP". This is a faster new formula
it will be something like this
=IFERROR(XLOOKUP(R14C12, _
'G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDCPIV'!$A:$A, _
'G:\Locations_NA\TUS\LO\[DMSU MACRO DATA.xlsm]DDCPIV'!$W:$W,_
"Error",0),0)
Second: Try to set the formula by a bunch of cells, not one by one (I'm assuming this, if you share more of your code we can check.
one by one is:
Range("A1").FormulaR1C1 =IFERROR(XLOOKUP(R14C12 ...
Range("A2").FormulaR1C1 =IFERROR(XLOOKUP(R15C12 ...
Bunch of cell is:
Range("A1:A5").FormulaR1C1 =IFERROR(XLOOKUP(R14C12 ...
Third: as ENIAC just said, disable UpdatingScreen and other Automatic Updates that Excel has. This will be like this:
Sub Example()
'Beginning Code
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
.DisplayAlerts = False
End With
'Your code Here
'End Code
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
.DisplayAlerts = True
End With
End sub
Now, the best way, in my opinion, is to work with Arrays and Dictionaries, that system is much faster, very much.
I am developing an add in for excel using vba. Upon opening the spreadsheet, all the values are recalculated and this slows down the opening. I've tried creating a Workbook_Open event that changes the application calculation from automatic to manual, but this event handler is executed after the calculations are done. I also tried setting the calculation to manual before the spreadsheet closes, so that upon opening it next time it will be faster. My problem with this though is that I feel it is invasive to the client.
Ideally what I would like to do is:
When the spreadsheet opens get the user's current calculation setting and save it
Change the calculation setting to manual so that the spreadsheet can open quickly
Change the calculation setting back to the user's original setting
How can I go about doing this?
I created 2 subs that I call when I need to do this, Updates_Off and Updates_On. You will need to declare the variables CalcMode, IterationMode, and Iterations as public in your calling sub and this will only work if you turn updates back on before you exit. If you can't do that, you will need to have some helper cells that store the values.
I have the if CalcMode=xlCalculationManual statements to warn me during development that I'm starting or ending in manual mode and I uncomment them when needed.
Public Sub Updates_Off()
' Turn off Screen updating
Application.ScreenUpdating = False
' Check what calculation mode is in effect and set current to manual
CalcMode = Application.Calculation
' If CalcMode = xlCalculationManual Then _
' MsgBox "Starting mode is manual"
IterationMode = Application.Iteration
Iterations = Application.MaxIterations
Application.Calculation = xlCalculationManual
End Sub
Public Sub Updates_On()
' Turn on Screen updating
Application.ScreenUpdating = True
' Reset Calculation mode
Application.Calculation = CalcMode
Application.Iteration = IterationMode
Application.MaxIterations = Iterations
' If CalcMode = xlCalculationManual Then _
' MsgBox "Reset to manual mode"
End Sub
I want to hide some of the Rows in a worksheet if the Cell in column A contains 0. This is calculated using a formula.
E.g. If A1 contains value "0", row#1 should get hidden.
I know I can write this code on Sheet's Activate Event but it is slowing down the file's performance.
Is there a good way to achieve the same without compromising file's performance?
you could always use filter to achieve this. I think that would be much more efficient.
Edit:
To improve performance of your code, you could do the following:
Turn off the Events
Turn off the Calculations
Before running the loop to hide rows
With Excel.Application
.ScreenUpdating = False
.EnableEvents = False
.Calculation = xlCalculationManual
.Cursor = xlWait
End With
After the loop is over
With Excel.Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = xlCalculationAutomatic
.Cursor = xlDefault
End With
Hope this helps. Also explicitly using variables could give a boost to performance
and Calculation. Although explicitly declaring your variables should help too.
In Excel 2010 the method described below, the ScreenUpdating works correctly. But in 2007, it doesnt flip and the worksheet operations are visually being seen.
VBA Usage:
Dim scrup As Boolean: scrup = DisableScreenUpdating(Application.ScreenUpdating)
Method Declaration:
Function DisableScreenUpdating(val As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''
' Disable ScreenUpdating, for seemless operation
If val Then
Application.ScreenUpdating = False
End If
'''''''''''''''''''''''''''''''''''''''''''''''''
DisableScreenUpdating = val
End Function
Question:
What am i missing in 2007 that 2010 is either assuming or is working correctly?
Still tracking down the bug cause it is still happening on 1 version of the file but other two versions it will not. The Versions all have the same code-base but based on various settings change representation to the end-user(s).
NOTE:
Please DO NOT focus on the "Why i am doing this", and more of what situations would cause the ScreenUpdating method to NOT be changed from True to False.
You could try eliminating the conditional and see if the problems is still there. That ways you'd know if it has something to do with conditional or not or 'val'.
Function DisableScreenUpdating() As Boolean
Application.ScreenUpdating = False
DisableScreenUpdating = True
End Function
Assuming this makes your bug go away, I'd then focus on the call....
DisableScreenUpdating(Application.ScreenUpdating)
Perhaps the bug something to do with reading the ScreenUpdating property, followed shortly by write. That's just a guess though.
Also, I'd search your project for any other usage of Application.ScreenUpdating. There may be some other code causing the updating to return to True.
For one thing, is there a function to enable ScreenUpdating? Your code only disables it. Here is your code modified with code that I use:
Dim scrup As Boolean: scrup = DisableScreenUpdating(Not Application.ScreenUpdating)
'Disable ScreenUpdating, for seemless operation
Function DisableScreenUpdating(val As Boolean) As Boolean
With Application
If .ScreenUpdating = val Then 'Gets rid of flashes for changing it to the same
.ScreenUpdating = Not val
End If
'Doesn't matter what happens above, this is based on what Excel would send back
DisableScreenUpdating = Not .ScreenUpdating
End With
End Function
I have seen the bug...yet the statement works, only the VBA-editor doesnt see changes.
However you can see the change by assigning a variable and then read it in the VBA-editor.
>Sub testing()
>Dim i As Long
>
>Application.ScreenUpdating = False
>i = Application.ScreenUpdating
>MsgBox "Assigned to i...real value = " & CBool(i)
>
>Application.ScreenUpdating = True
>i = Application.ScreenUpdating
>MsgBox "Value of Application.ScreenUpdating = " & CBool(i)
>End Sub
I have a COM (C++) API that listens for data updates from a server and writes these updates to a sheet. These updates are handled in VBA code and can arrive multiple times a second. In order to write these updates to the sheet in the most efficient manner, I use the following premise:
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
<UPDATE CODE>
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
In fact, I schedule a procedure to do this regular intervals where ScreenUpdating = False for about 20 seconds, then it is set to true so the data can update and then I set it to false again. i have found that this is a better option than setting ScreenUpdates + Calculation explicitly simply because of the highfrequency of the updates I receive.
The Problem:
I have read here that excel sets ScreenUpdating = True at the end of each method that disables it which is not what I need.
The Question:
Is there some way to force Excel to not automatically enable ScreenUpdating?
See if these help with your APIs
http://msdn.microsoft.com/en-us/library/ff818516%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee461765%28v=vs.85%29.aspx
I just searched google for "list of apis microsoft"