views:

116

answers:

3

Hi, guys.

Say I have a button embedded into my spreadsheet that launches some VBA function.

Private Sub CommandButton1_Click()
    SomeVBASub
End Sub

Private Sub SomeVBASub
    DoStuff
    DoAnotherStuff
    AndFinallyDothis
End Sub

I'd like to have an opportunity to have some sort of a "cancel" button that would stop SomeVBASub execution at an arbitrary moment, and I'm not into involving Ctrl+Break here, 'cause I'd like to do it silently.

I guess this should be quite common issue, any ideas?

Thanks.

+6  A: 

Add another button called "CancelButton" that sets a flag, and then check for that flag.

If you have long loops in the "stuff" then check for it there too and exit if it's set. Use DoEvents inside long loops to ensure that the UI works.

Bool Cancel
Private Sub CancelButton_OnClick()
    Cancel=True
End Sub
...
Private Sub SomeVBASub
    Cancel=False
    DoStuff
    If Cancel Then Exit Sub
    DoAnotherStuff
    If Cancel Then Exit Sub
    AndFinallyDothis
End Sub
jamietre
I had an idea to implement this sort of logic but it quite embarasses me to put `DoEvents-Check flag` chain in EVERY possible procedure's exit point (literally, after nearly each string).
be here now
The method @Faheemitian describes below avoids that, but that works pretty much the same as Ctrl+Break. It depends on how much control you want over the user interface (e.g. a button) and where you can allow your code to exit. If UI isn't important and the code exits can be arbitrary (e.g. no issues with dependencies, rollbacks, etc) then that would be easiest. Usually adding traps for a cancel flag isn't too burdensome since most of the execution time would be spent in loops, but perhaps that is not the case in your situation.
jamietre
Let me also add that if you're concerned about the procedure not stopping immediately when they click "cancel" (hence the need for you to add so many checks), what I usually do is disable the Cancel button and change the text to "Wait..." or something in the Click procedure, so the user is aware that the application is actually considering their request.
jamietre
A: 

what jamietre said, but

Private Sub SomeVBASub
    Cancel=False
    DoStuff
    If not Cancel Then DoAnotherStuff
    If not Cancel Then AndFinallyDothis
End Sub
Beth
+4  A: 

How about Application.EnableCancelKey - Use the Esc button

On Error GoTo handleCancel
Application.EnableCancelKey = xlErrorHandler
MsgBox "This may take a long time: press ESC to cancel"
For x = 1 To 1000000    ' Do something 1,000,000 times (long!)
    ' do something here
Next x

handleCancel:
If Err = 18 Then
    MsgBox "You cancelled"
End If

Snippet from http://msdn.microsoft.com/en-us/library/aa214566(office.11).aspx

Faheem