VBA - Excel Delay and Forcestop a macro at opening - excel

I got a file in task scheduler which has a macro that triggers opening like this:
Private Sub Workbook_Open()
Call OpenRunMacroandCopy
End Sub
A bit like a house alarm, I'd like to have this macro wait before executing the Call for a set duration so I could use ctrl+Break which i believe would interrupt execution and let me read the file and close it without OpenRunMacroandCopy running at all.
I know of Application.Wait and Sleep but they don't work here and i do not know why.
I also used Application.OnTime Now + 5 / 1440, "OpenRunMacroandCopy" which does seem to make it wait but ctrl+Break gives me no notification and i've had that macro run anyway so i'm not sure interruption is working? When I use ctrl+Break on an infinite loop macro i do get an error window which is quite nice so i definitely know i have it stopped.
Got an idea, or a more purposeful way to make that happen?

Related

How can I break long running EXCEL VBA code

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!

Excel - opening file stuck on 100%, until VBA code finishes

I have Workbook_Open event, which fires a script with lots of code. It runs very long (getting data from web) and I would like Excel to open the file while it runs, this VBA also shows progress on status bar. I use loops and DoEvents has been used on each iteration with no effect. Only when macro executes successfully or I use Ctrl + Pause Break, file opens. Any ideas what can be wrong and how it could be fixed?
Edit: I didn't attach the code, as I am not the author and there are hundreds of lines in it. I had hope of finding a general cause why such situation would happen, from someone who encountered similar.
Important: it appears that the initial version of the file which I received from colleague works correctly until I save the file, so there isn't any "bug" in the code. Using VBADebugger didn't help. There are no external connections and names in the file.
I solved the problem by letting VBA excecute Workbook_Open event ASAP. I put the whole earlier content of Private Sub Workbook_Open under "scraper" procedure and now it looks like this:
Private Sub Workbook_Open
Application.OnTime Now + TimeValue("00:00:01"), "scraper"
End Sub
It must be that Excel won't (sometimes?) open the file before executing Workbook_Open event.

Why does VBA code run faster when called from a standard module (instead of a userform)?

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.

Workbook_BeforeClose not executing after using VBA editor

As the title suggests, I am having a problem with Excel's Workbook_BeforeClose event handler. I know I am using the correct method signature (shown below) because it has worked in the past, and I have correctly placed the event handler in the "ThisWorkbook" module of the VBA editor. However, I have noticed that whenever I do a significant amount of coding within the VBE (in other modules), this method is not executed. Even when I place breakpoints inside, the breakpoints are not hit before the workbook closes. Again, this only happens if I have been messing around with other modules in the VBE; if I just open the workbook and immediately close it, this method runs fine and the breakpoints get hit. Saving or not saving the workbook does not seem to make a difference, and this problem occurs in Excel 2013 and 2016 (haven't tried opening the workbook in earlier versions). This issue is really starting to impede my workflow, so if anyone has a thought on why my Workbook_BeforeClose handler is not being called, I would very much appreciate the help!
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'More code...
End Sub
After posting this question on the Mr. Excel forum, I was given the solution: Some of the other modules that I was editing contained optimization code. This included disabling Application events while the macro was running, then turning them back on after completion. However, while debugging, I would obviously occasionally stop the macro before it completed, so Application events were never being turned back on!
So now, all I have to do is execute "Application.EnableEvents = True" in the Immediate Window before I try to close the workbook, and my event handler runs fine!

Interrupt running Excel Macro through VSTO

I am running Excel as a calculation engine (no user interaction) through VSTO and would like to be able to cancel a long running macro programmatically.
My current approach is to put the blocking call to run the Macro (Application.Run("MyMacro")) on a separate thread and then attempt to interrupt it from the main thread.
There does not seem to be any in built method call for this purpose such as Application.Interrupt(), so I am trying to programmatically trigger the keyboard interrupt that occurs when CTRL+Break or ESC are pressed.
Current code looks like:
Application.CalculationInterruptKey = XlCalculationInterruptKey.xlAnyKey;
Application.EnableCancelKey = XlEnableCancelKey.xlInterrupt;
Application.SendKeys("{ESC}", false); //have tried with true as second argument
In this case the code blocks on the final line which does not execute until the macro has completed.
I have also tried obtaining the process hook for Excel, setting it as the active process / window and calling SendKeys without success.
As this needs to be a generic solution for executing any macro, I cannot modify or provide any guarantees as to the macro contents.
Any ideas?
Thanks,
PS I have also tried sending the CTRL+BREAK keyboard command as in Application.SendKeys("^{BREAK}", false); The debugger pauses on this line until the macro finishes execution, so it seems like the Application object is blocked from processing any more commands until the macro has completed.

Resources