'Excel VBA macro slows down unpredictably, usually at DoEvents
What can be happening that slows down Excel to a crawl, sometimes for a minute or two, sometimes for hours, and its workload is spread across calls to DoEvents
?
Unfortunately, I can't post code because there seem to be no code causing the problem. It happens in different places without apparent pattern. Below there are details about my investigation.
Last week Excel on my computer started slowing down when running a macro that has been running without problems for years. I tested the same macro on 2 other computers, but they don't seem to have the same problem. It's difficult to test because it doesn't always slow down and it never happens on the same place. Sometimes it does it every minute, sometimes it works for 10 minutes and then it does it again. I tried two other computers for about 30 minutes and it never happened.
If I set breakpoints, it never slows down.
If I sprinkle prints it does, but never at the same place.
If I press Ctrl+Break the macro stops after a few minutes, the debugger shows the current line highlighted as usual, but Excel keeps using 25% CPU (that is 100% of two cores). At this point every click on Excel or on the VBA IDE is responsive, but very slow. It usually takes minutes before you see the cursor moving to the clicked spot. Sometimes if you wait a few minutes the control comes back and it's possible to press F8 or F5 to continue the execution, but I usually kill Excel if the CPU usage doesn't go down in 2-3 minutes.
During the investigation I created this function:
Sub DoEvents2()
Dim T As Single
T = Timer
DoEvents
Debug.Print Format(Timer - T, "0.000")
End Sub
and replaced the calls to DoEvents
with calls to DoEvents2
, and I see on the debug window that the time required for the DoEvents
is always a few thousands of a second, sometimes a few hundreds and once in a while, without apparent pattern, the time goes up. Often it goes up to ~90 seconds, sometimes less, a few times it lasted almost an hour, once it was still running the next day.
Here is an example of the output on the debug window after running the macro with the above defined DoEvents2
:
0.000
0.289
0.000
0.004
0.066
88.324
26.727
20.699
28.762
4.359
0.789
0.090
0.297
0.141
0.000
0.070
0.000
0.043
[...]
0.016
0.035
0.004
0.199
1.852
0.066
0.023
0.004
0.000
31.309
104.438
1.449
0.785
0.020
0.004
0.547
0.000
0.000
0.055
The macro is large and it's difficult to remove one piece without breaking it.
At first I thought the problem was with a form, but I removed all the forms and the problems is still there.
Then I tried working on volatile functions: I removed all the volatile functions and the problem is still there. Plus, it doesn't seem to be triggered by changes to Application.CalculationMode
or Application.EnableEvents
.
I checked if there are globals that could trigger long running garbage collection, but I didn't find anything. Plus, I don't see how garbage collection could run 12 hours (I left it running once the whole night and it was still there in the morning).
Sometimes I click on a button that runs a macro that uses JsonConverter, regular expressions, http requests, forms, volatile functions, etc., it runs for a minute or two as expected, and has no problems. Then I click on another button that runs 10 lines of code, and it's done in a few hundreds of a second. I click the same button again and again, and after a few times Excel hangs. I don't know where it hangs because it never hangs at the same line.
The problem started last week while Windows updates were going on, but I don't know if it's related. Since then I've been working full time chasing this problem without success.
I can't post any code, because the macro has 14,000 lines, and it happens every where, wherever there is a DoEvents
, even if it's a small 5 line function. But it seems to be affected by something that happened earlier.
So, my question is, what can be happening that slows down Excel to a crawl, sometimes for a minute or two, sometimes for hours, and its workload is spread across calls to DoEvents
.
Edit
It happened again about 40 minutes ago, I decided to let it vent hoping it would stop while I was working on something else. After 30 minutes I pressed Ctrl+Break to try to stop it, after a minute or two it did stop, then I did a burst of clicks on the save button of the VBA IDE, hoping that one of them would work and after a minute or two a popup showed asking if I wanted to save the file with unfinished calculation. After a few seconds, while this popup was visible, the CPU usage went to zero. I asked to save the file without completing the calculation, it did (I can see the " - Saved" on the title bar), then the CPU went on sucking 2 cores with the IDE still showing the current line highlighted. I tried with a burst of clicks on the stop button, but didn't work (yet?).
Edit 2
I found a place in the macro where if I set a breakpoint and press F5 it works consistently, but if I remove the breakpoint it works once, then it hangs.
This is the code:
T0 = Timer
Debug.Print Application.CalculationState,
DoEvents ' Here I set the breakpoint
Debug.Print Application.CalculationState, Timer - T0
This is the output on the Immediate window after running it a few times with a breakpoint (you see the time it takes me to press F5 after seeing it stopping) and twice without the breakpoint. I am pasting a snapshot because I couldn't copy from a hanging Excel ready to be killed. While that code is executed the calculation is manual and the events are disabled. I don't think it was calculating.
Tomorrow I will try to reinstall Office.
Edit 3
Uninstalling and reinstalling Office didn't help.
But I think I found one factor that seems to reliably allow Excel to work without problems or to hang: the VPN.
If I start Excel without VPN connection, then I can work without problems. If I then start the VPN connection, the first click (and the following macro) has no problems, the second click is slow, the third one hangs and Excel needs to be killed. Disconnecting the VPN after the second click doesn't help. I tested this scenario 5-6 times, always with the same result.
I can't think of any reason why Excel would be affected by the VPN connection. The only addins installed are the ones I am struggling with, they are on the local drive, no 3rd party addins installed. My macros do not access any network drive. There is one class with one member Req As New MSXML2.XMLHTTP60
which is never used during my tests.
Edit 4
Nope, nothing to do with the VPN. Today I'm in the office, without VPN, and the problem is still there.
After reinstalling Office I had the same settings as before.
Is it possible to reset everything and make a new clean Office installation that doesn't remember anything from its previous life?
Solution 1:[1]
Here is a little update. I don't know if this is the answer that allows to fix the problem, but it's the last thing I have tried before the problem disappeared.
Thinking that the file was corrupted, I started creating a new file, importing the code and the forms from the allegedly corrupted one, creating the sheets from scratch (rather than copying the old ones to avoid any risk of duplicating the corruption) and I realized that I had both one global variable and one sheet called ShNesting
. The duplicated names are not a problem because the global variable has narrower scope than the sheet object, so VBA never saw the sheet ShNesting
. I checked on the git repository and I see that it has been working for 5 years with duplicated names without problems.
I renamed the sheet to Sheet4
and the problem disappeared.
I tried to reproduce the problem with backup copies of the corrupted file, but I wasn't able to reproduce it. I don't know if I wasn't able to reproduce it because the backup copies were saved in a condition that doesn't reproduce the problem and I wasn't able to recreate it, or if my computer decided to heal itself.
I waited a few days, I never had the problem, so I thought to leave a little update here.
Solution 2:[2]
Not really a solution, but too long for comment.
I know I've seen better stack tracing procedures, but maybe modify you're DoEvents2
and add a call to TraceRoutines
at the top of all the UDF
, SheetChange
or whatever routines you think are running. Use the Timeout on the TraceRoutines
as a circuit breaker.
Public DoingEvents As Boolean
Public TraceList As String
Public LastTime As Single
Public StartTime As Single
Sub DoEvents2()
StartTime = Timer
LastTime = StartTime
If DoingEvents Then
Debug.Print "Nested DoEvents calls?"
TraceList = TraceList & "DoEvents" & " (@ " & Format(Timer - LastTime, "0.000") & "s)" & vbCrLf
Debug.Assert False
Else
TraceList = vbNullString
End If
DoingEvents = True
DoEvents
DoingEvents = False
Debug.Print Format(Timer - StartTime, "0.000") & " Doing Events"
Debug.Print TraceList
End Sub
Sub TraceRoutines(Name As String, Optional Timeout As Long = 20)
'Static LastTime As Single
Static TimeoutTriggered As Boolean
If Timeout = 0 Then TimeoutTriggered = True
If DoingEvents Then
TraceList = TraceList & Name & " (@ " & Format(Timer - LastTime, "0.000") & "s)" & vbCrLf
LastTime = Timer
If LastTime - StartTime > Timeout Then
If Not TimeoutTriggered Then
Debug.Print TraceList
MsgBox "What is going on here?"
Debug.Assert False
TimeoutTriggered = True
End If
Else
'Reset
TimeoutTriggered = False
End If
End If
End Sub
Sub MyFunction()
TraceRoutines "MyFunction"
End Sub
Solution 3:[3]
I have recently seen VBA code which exhibited very similar behaviour, that is it was code which had worked reliably for many years but then started to occasionally hang Excel. Eventually I isolated the problem to calls to Application.DoEvents
that rather than taking the expected few milliseconds to execute could take up to three minutes.
The PCs in question had Netskope anti-virus installed and I discovered that the problem went away if Netskope was de-activated. Though for me a permanent solution was to amend the code to no longer use DoEvents
.
So in answer to the question: Have you tried switching off any anti-virus?
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 | stenci |
Solution 2 | Profex |
Solution 3 | Philip Swannell |