Up until a few years ago (don't remember which version of Office/EXCEL it was) I was able to break long-running (or in infinite loop) VBA code by pressing CTRL-BREAK, if the code was performing Input/output. But this is no longer working in EXCEL 2016. Running the following code:
Public Sub doit()
While 1 = 1
Debug.Print Now()
Wend
End Sub
Runs for a while, printing (I/O) the current date-time on the immediate window (it can be interrupted at this point), but after a few seconds EXCEL goes into 'Not Responding' mode, and never recovers (the only option is to End the program; loosing data/coding to last Autorecover point).
Does anyone know why? and if there is a way to break the code while in that Not Responding mode?
Is sprinkling DoEvents all over the code the only way to guarantee that we can break?
This is 32 bit EXCEL.
The answer in this Linked question:
Control Break out of Infinite Loop In 2010 (2013) Excel VBA
Alt-Esc (even though it switches through all open windows) eventually breaks it, allowing us to save the work.
Somehow I missed that thread when I searched; apologies!
Related
Alternate Title: Why does pressing Esc make my MS-Word macro run faster
While waiting for some code to run I stumbled across something interesting.
Code runs slow... press Esc code runs fast. Example:
press Esc immediately after execution - 2 sec to complete
don't press Esc at all - up to 30 sec to complete
To me this makes no sense. It turns out other people have noticed similar behavior, for example:
Pausing VBA and re-running it causes faster execution
http://www.vbforums.com/showthread.php?490446-ESC-key-while-running-macros
https://www.excelforum.com/excel-programming-vba-macros/617300-vba-code-runs-slow-until-i-push-esc.html
And they have found various solutions or workarounds. However, these posts are for MS-Excel; which it seems has different behavior for the Esc key.
In MS-Excel pressing the Esc key can (depending on the setting of Application.EnableCancleKey) interrupt code or raise an error (Err 18), or do nothing. On the other hand in MS Word no such thing happens, instead Application.EnableCancleKey alters the behavior of Ctrl + Pause. Yet despite this, pressing the Esc speeds up the code execution dramatically.
That difference aside, my question relates more to the placement of code in a userform. For example in my Userform:
Private Sub Cmd_Click()
Module1.Macro1
Module1.Macro2
Module1.Macro3
End Sub
Tested on a 64 bit version of Word 2010, using the structure above is significantly slower than this:
Userform:
Private Sub Cmd_Click()
Module1.RunMacro123
End Sub
Standard Module:
Private Sub RunMacro123()
Module1.Macro1
Module1.Macro2
Module1.Macro3
End Sub
I should note the following:
This is most apparent in the 64 bit version of MS Word, the 32 bit version seems to run quite fast with the original code (I'm yet to test with the revised code)
Like the author in the first link I am not using the selection object etc.
I'm more interested any insights as to why the speed of code execution is so influenced by:
pressing Esc
moving the calls from the userform to a standard module
Macro1, Macro2 & Macro3 create and edit document styles and (FWIW) involve reading INI files many times
On a side note, in a hair-brained attempt at being clever I tried using sendKeys to send the Esc key but it has no affect.
Edit - Results of timing the code:
I ended up using the timer function to time the code, I had already implemented a stack class which was adapted from here: http://www.tek-tips.com/viewthread.cfm?qid=1468970
I added an 'absolute' timer (debug.print timer - startTime) to the call stack such that the time between each push was recorded and the timer was reset (startTime = timer) at each pop. Doing this made comparing times easier in NotePad++
This allowed me to determine that a sub that applies styles to a document was taking ~0.04 seconds to apply the style (NB value returned by the timer = seconds past midnight).
The image below shows an example of the code timing results. Basically, as far as I can tell, the delay in code execution comes from many incremental delays all associated with the same basic task.
Because of the way the timer works with the call stack I had to test the code getStyleElement to make sure it was not contributing significantly to the extra time. I did this by timing the code directly and was able to confirm that it was consistently fast to run.
Examining the rest of the code confirmed that the issue was with applyStyleFormat (which calls getStyleElement).
The styles are applied to the document - the code structure includes a With block and For Loop; something like this:
For i = 1 to Styles.Count
With aDocument.Styles(i)
.Font.??? = Something
' or .Paragraph.??? = Something
End With
Next i
I'm no clearer as to why the code runs faster from outside of the userform, or after pressing Esc but it does and it seems to have something to do with modifying styles...
Just pulling the thread on #Florent Bs comment, have you tried seeing what you can disable prior to running the macros in the click event? Things like
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'code
Module1.Macro1
Module1.Macro2
Module1.Macro3
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Just to see if things are any quicker? There might be other commands to cancel other things that people can add.
I can't get the name of the workbook when I use a add-in.
I'm trying to develop a add-in that runs each time you open Excel and reads the filename of the open file.
If the file name is XCFIL.SKV then do something...
This code should do it, but it doesn't. What am I missing?
The code stops and if I debug and press F8 it works fine, but it won't run on it's own.
Private Sub Workbook_Open()
If ThisWorkbook.Name = "XCFIL.SKV" Then
MsgBox "y"
End If
End Sub
Background:
Based in this statement The code stops and if I debug and press F8 it works fine, but it won't run on it's own. I assume the problem relies on the speed of the processor that is not sync with the code (own experience).
Solution:
Since it is Excel and the problem seems to rely only in the opening of the instance itself, you may use Application wait or any of the other functions for this matter.
Further thoughts:
Life cycle comes to my mind in these kind of scenarios. This web page has a neat Lifecycle diagram of excel instance (attached since I will try to explain the scenario)
As you may see "Application" is the first cycle of the Excel application, followed by "Open" and after that "Workbook" object, it may happen that in this life cycle "worbook" has not been created when "Open" comes to play,hence, you need to wait until excel solves this.
I have been chasing my tail for weeks, with more hours "Googling around than I want to admit.
I have a large, complex analytical app within an Excel 2016 spreadsheet that captures SQL table data, queries email data and does a lot of stuff that I think is pretty cool. Users see sales force automation performance metrics and charts. All is well except for one thing. I cannot stop the "save data?" dialog box from appearing no matter what I do.
As a workaround I've put the spreadsheet on on a network ride and given users a shortcut that runs a VBscript to copy this spreadsheet to a hidden drive on the local PC and runs it. So if they save it, there's no worries as they aren't working with the original data. But as one would easily imagine, the load time is necessarily longer than it need be and users are confused by a message when I am telling them they can't save the data.
Net of a lot of different experiments, it seems like I've uncovered a bug in Excel (yeah, I know, this sounds lame even to me) as I cannot make the Application.DisplayAlerts = False. It just will not take.
See image here:
enter image description here
The image above (or at the above link as I haven't submitted enough question yet to embed images) is obviously taken from the Immediate Window when I was running the app. I entered the steps in the exact order shown. Note that I set Application.DisplayAlerts = False and then checked the value immediately afterwords and it was True.
Very weird. Is this a bug?
One last aside that is probably irrelevant; I was using .XLSB format because of the smaller footprint, much shorter load time and to get around PC setup issues with macros. But I've switched back to .XLSX to simplify the experiment.
To clarify: the code temporarily halts after each single-step in the debugger, resulting in Excel setting it back to True while idle. Here’s a way to verify this behavior:
In the VBE code-development window, open the Immediate window (Ctrl-G).
Temporarily insert the following code somewhere in your routine:
Debug.Print "..."
Application.DisplayAlerts = False
Debug.Print "Application.DisplayAlerts: " & Application.DisplayAlerts
Stop
Using the “Set Next Statement” tool (or Ctrl-F9), set the Debug.Print "..." statement to be the next one to execute.
Run the code form there by pressing F5 (Continue).
You should see this displayed on the Immediate window:
...
Application.DisplayAlerts: False
Now, with the code stopped at the Stop statement, type “?Application.DisplayAlerts” in the Immediate window, and press the [Enter] key. You will get:
?Application.DisplayAlerts
True
because Excel has reset it to True while the code is suspended.
Remove the experimental code.
If I write code creating an infinite loop, with my new Excel, the Ctrl + Break no longer works. Neither does the Esc key, etc.
I've looked all over the web and it appears that Microsoft has a bug and doesn't care to fix it.
Is there a way to re-introduce the Ctrl + Break function to VBA so if this happens in the future I don't lose work / force close?
Alt + Esc. Hold down the keys until it breaks.
From Windows 7 on, this will cycle through all open windows. Pay no mind, just keep squeezing it.
On Office 2013, at least, Ctrl+Scroll Lock does it. I didn't need to change any settings or enable anything.
(Blatant plug: my blog post linking to the original source of this info :) )
One way to mitigate this very annoying behaviour is to include
DoEvents
In the loop. It doesn't have to be executed every iteration, so long as it is called periodically, Ctrl Break will still work.
Note: I usually remove this after the code is debugged, to avoid any performance impact
For those who tried the previously proposed solutions to no avail, try this. It worked for me (windows8, Excel 2016)
On the VBA code window, left-click and hold (as though you are going to drag that window) while holding down the Alt+ESC keys. It broke the execution and asked me if I wanted to continue, or debug... I of course chose debug.
If it can help anyone, pressing Ctrl+break when the macro is not running only works if you do it outside of the developer.
An alternative will be introduce error intentionally in the loop. Say for e.g. your loop should not be running more than 1000 times:
Function XYZ()
do while(..)
errcnt = errcnt + 1
if errcnt > 1000 then
cells.find(what:="Chunk Norris").activate
exit function
endif
loop
end function
it will produce an error and 'break' the code
Break (Ctrl + Break) is also not available in the VBA editor if you are in design mode. In that case you can press the Design Mode icon which is to the right of the square stop icon. This brings the editor back in regular mode and the break option then becomes available.
There is no "Break" button on my poor keyboard. My only alternative is to hit the X to close the program or alt+F4. I'll have to code something as well.
From answers.microsoft.com, simply press ESC a few seconds when the focus is on your Excel window. At least, it works for me on Excel 2016.
I have a VBA form that when I click on it, performs some long calculations (a few seconds to several seconds long) and then displays the results on frames in the form. However, once every so often, the form hides on me and I need to click around to the VBA editor and back to the sheet to make it display again
I have
Me.Repaint
at the end of the calculations on the form
but it still doesn't help
I also tried disabling the "EnableCalculation" attribute of the main sheet, but still no use
Anyone ever run into something like this? Do I need to load the form in some special way?
I have had the same problem. When saving an Excel workbook by clicking on a command button on a modeless Userform, the form disappears as the code completes.
I read that the problem was due to some inter-compatible changes that Microsoft has made and found some very elaborate solutions involving a lot of complex code that I was unable to integrate into my project. However, I did find a very quick workaround.
In my case the Userform only disappeared when the code executed the End Sub command of the command button's code. I simply added an Exit Sub immediately before it and the Userform no longer disappears.
Have you tried turning off and on screen updating so Excel is not redrawing the screen with each change.
sub doSomthing()
Application.ScreenUpdating = False
'do something
Application.ScreenUpdating = True
end sub
The form disappears because Microsoft has changed the model by which forms are owned by a 'superior' process (Excel in your case). I have the same problem and also cannot overcome it.
Just sit tight until Microsoft decides that it is worth their effort to fix yet another introduced and untested problem by making changes to something that already worked.
The problem is a side effect of the SDI (Single Document Interface) that was introduced with Excel 2013. The various suggestions that invoke DoEvents, ScreenUpdating, etc. may help in certain scenarios, but they do not cure the behavior.
There is a full solution posted here: Keeping Userforms on top of SDI windows in Excel 2013 and up
If that is too involved for your needs, a quick-and-dirty solution is to minimize and restore the active window, which forces the userform back on top of the stack.
'Do long-winded process first, then:
Application.ScreenUpdating = False
ActiveWindow.WindowState = xlMinimized
ActiveWindow.WindowState = xlNormal
Application.ScreenUpdating = True
This doesn't prevent the form from disappearing, but it makes it reappear the end of the process.
Try experimenting with the following two lines of code instead of the repaint.
Me.Show
And/Or:
Me.SetFocus
Hopefully, one of these will work for you!
In my case I had to use all these to make it happen. (frmGUI is my form)
DoEvents
frmGUI.Repaint
frmGUI.Show
With Office 2013 and Windows 7, simply adding DoEvents right before the end of the sub (where the form disappeared) kept the form open. Nothing else needed....for my situation.