1

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.

enter image description here

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
stenci
  • 8,290
  • 14
  • 64
  • 104
  • Do you have any 3rd party add-ins installed? or personal add-ins? – Siddharth Rout Oct 20 '20 at 16:50
  • No 3rd party add-ins, I have 2 add-ins of mine, one is a standard library all my macros use as a reference and one is another add-in that is used by this macro to copy some sheet templates from and to run some macros (not really a reference, because it's rare that other macros use it). It's impossible to separate them, because everything depends from everything. – stenci Oct 20 '20 at 19:56
  • Tried re-installing office? https://answers.microsoft.com/en-us/msoffice/forum/msoffice_excel-mso_win10-mso_o365b/excel-slow-after-update/cbca3868-8b2d-4bfe-9ade-3b908e2cc8b0 – Siddharth Rout Oct 20 '20 at 20:19
  • 1
    Also if you search google with `excel running slow after windows update` you may come across something useful as trying to find why your Excel is slow? NOt sure what else to suggest you... – Siddharth Rout Oct 20 '20 at 20:21
  • @SiddharthRout thanks for trying, you are the best as usual... :( – stenci Oct 20 '20 at 20:25
  • 1
    re-installing office may actually work (not sure though) Give it a shot :) – Siddharth Rout Oct 20 '20 at 20:35
  • Sounds like you are using custom functions in the cell formulas. Do you also have any ActiveX controls by chance? – Profex Oct 20 '20 at 21:23
  • In case you are using Excel User-Defined-Functions (UDFs) then there is a bug that causes them to be very slow in Automatic calculation mode. If you do use UDFs then have a look at my [repo](https://github.com/cristianbuse/VBA-FastExcelUDFs) for a fix. If you do not then ignore my comment – Cristian Buse Oct 21 '20 at 12:07
  • @Profex I stay away from both ActiveX and form buttons and controls (see https://stackoverflow.com/questions/17619558/using-radio-buttons-in-an-excel-vba-script/17620806#17620806), but there are still a few old form buttons. I don't think there are any ActiveX, but there could be some old button left. Do simple ActiveX button risk to cause problems? – stenci Oct 21 '20 at 15:26
  • 1
    @stenci, I had an issue with ActiveX ComboBoxes (to select printer) that forced a recalculation on all custom functions (to display barcode) everywhere in the workbook, even though it wasn't volatile. (There was a lot going on using 'OnTime' calls and a constant loop to scan for barcodes, but the Combobox was a deal breaker, works good now). – Profex Oct 21 '20 at 17:36
  • @CristianBuse The problem reproduces also when the VBE is closed, but I don't know if it happens when the VBE has never been open in the current session. I'm investigating that part now. In my slow functions I use IsCalced (http://www.decisionmodels.com/calcsecretsj.htm), but I didn't know there was a problem with the IDE. Thanks, I will investigate in that direction too. – stenci Oct 21 '20 at 17:38
  • @Profex I don't have listboxes on sheets, but I do have them on forms. And the problem shows up very often when those forms are open, but sometimes even without form open. I will keep my eyes open and see if when it happens without form open, the form had already been used during the session. – stenci Oct 21 '20 at 17:42
  • @stenci, listboxes on forms should be OK. What version of Excel? If CristianBuse's fix doesn't help, you might want to put a static debug counter on any UDF or the Workbook_SheetChange function to see if it's doing excessive recalculations. – Profex Oct 21 '20 at 18:40
  • One thing I forgot to mention is that there is a bug with Application.CalculationState and if you are relying on it (in combination with DoEvents) then you should have a look at the ```TryFixingPendingBug``` method within the same repo I mentioned. That single bug can add lots of useless waiting time – Cristian Buse Oct 21 '20 at 19:03
  • @CristianBuse My file has about 40 calls to UDFs, most of them to the same volatile function. Usually they are fast enough that you can work in real time. I added an `Exit Function` at the beginning of all my UDFs, and the problem is still there. I added a `Debug.Print` and sometimes they are executed once, sometimes 2-3 times, but when it hangs I see no output on the Immediate window. So... I don't think your repo would help me, right? If all my functions do is exiting immediately, I can't speed them up, right? Or am I misunderstanding your solution and I should try it anyway? – stenci Oct 22 '20 at 00:40
  • 2
    I've mentioned 2 distinct bugs. You don't need to fix the UDF bug for just 40 UDF calls (although by ```Exit Function``` the bug is still there). I use the fix because I have millions of UDF calls and speed is imperative. The second bug could still affect you even if you have no UDFs. Please search your entire project for something like ```If Application.CalculationState = xlPending Then``` and if you do find it then make sure you use the ```TryFixingPendingBug``` method that I've mentioned. – Cristian Buse Oct 22 '20 at 07:45
  • Doesn't seem quite the same as I've seen before but maybe the file is just corrupted. See if you can delete all of the Forms/Modules/Classes/Sheets? If any of them give you problems, that one is probably corrupted. – Profex Oct 26 '20 at 23:46

3 Answers3

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.

stenci
  • 8,290
  • 14
  • 64
  • 104
0

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
Profex
  • 1,370
  • 8
  • 20
0

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?

Philip Swannell
  • 895
  • 7
  • 17
  • The macro with this problem is big and I can't remove DoEvents, but I can try to disable the anti virus (if I can get IT to cooperate and I find a day where the problem reproduces more reliably). Thanks for the tip. – stenci Apr 24 '22 at 12:57