cancel message while sub running

T

tracktraining

Hi All,

I would like to create a cancel message that appears while a sub is running.
So, when the user hit the cancel button on the message box (or userform),
then the sub will exit and start the program from the beginning. And if the
user doens't hit the cancel button, then the sub will continue to work as is.

Any help is much appreciated.

thanks,
tracktraining
 
S

smartin

tracktraining said:
Hi All,

I would like to create a cancel message that appears while a sub is running.
So, when the user hit the cancel button on the message box (or userform),
then the sub will exit and start the program from the beginning. And if the
user doens't hit the cancel button, then the sub will continue to work as is.

Any help is much appreciated.

thanks,
tracktraining

Consider this approach.

Here is code for a form that contains a command button and a text box:

Option Explicit
Private Sub CommandButton1_Click()
IsCancel = True
End Sub


And here is module code that would contain your sub:

Option Explicit
Public IsCancel As Boolean
Sub endlessloop()
Dim i As Long
IsCancel = False
UserForm1.Show vbModeless
Do Until IsCancel
UserForm1.TextBox1.Value = i
i = i + 1
DoEvents
Loop
MsgBox "you canceled"
UserForm1.Hide
End Sub


The keys to make this work are
- the global variable in the module, which the form can set
- the use of vbModeless when showing the form
- checking the state of the global flag "IsCancel" that signals when to
stop the loop

You need to be careful with this though. In real life it is typically
more difficult to know when to check the flag. By the same token it is
more difficult to know what to do when the flag is tripped. Variables
usually need to be reset, etc.

Also, unless you are very careful, you /do not/ want to call the sub
again from within itself, especially if there is more code after the
call. Why? Because the self-referential call will push the old instance
on the stack, and that will be waiting to resume execution later when
the new instance completes its uninterrupted mission. (Just imagine if
the user click cancel a dozen times... a dozen incomplete versions of
the sub will be stacked up, waiting to finish).
 
P

Patrick Molloy

I thought application.ONKEY would work, but my test failed.

alternatively, with my test code, run it and the put 1 into cell A1

Option Explicit
Sub cancelled()
Dim i As Long
Dim bCancel As Boolean
bCancel = False
Do
Application.StatusBar = i
i = i + 1
If Range("A1") = 1 Then bCancel = True
DoEvents ' releases control back to PC - ie user can enter data into
the spreadsheet
Loop Until bCancel Or i >= 1000000
if bCancel then msgbox "User interrupted!"
End Sub
 
T

tracktraining

Can you tell me where I am supposed to put that code?

I have a userform and the code is outline as below:

Private Sub Graph_button_Click()
' obtains data and creates graphs base on user inputs
end sub

Private Sub Userform_Initialize()
' initialize the starting userform (making everything blank)
end sub


When the user hit the graph button, that's when i want the "Please wait
while report is being generated. If you want to cancel is transaction, please
click on the cancel button below." vbcancel , to appear.

if the user doesn't hit the cancel button after the report is generated,
then the message (or userform) will close.

But if the user hit the cancel button, then i want to stop the code from
running.

thanks again for helping.
 
T

tracktraining

I tried your code and incorporate it into my code and it didn't work. when
userform2 appears, i can unable to click cancel - my code runs as is.

2)
Option Explicit
Private Sub CommandButton1_Click()
UserForm2.Show vbModeless
Dim i As Long
For i = 1 To 100000
UserForm2.Label2.Caption = i
' DoEvents - is there where i add in my code - obtain data,
calculation, create graphs (call other functions/subs)?
If UserForm2.bCancelled Then Exit For
Next
If UserForm2.bCancelled Then
MsgBox "user cancelled"
else
MsgBox "finished normally"
End If
Unload UserForm2
End Sub
 
S

smartin

' DoEvents - is there where i add in my code - obtain data,

DoEvents is a one word instruction that tells VBA to pause execution and
process Events -- such as a user clicking a "Cancel" button or redrawing
a label caption. Once events are processed, execution resumes. As such,
DoEvents is important here and you should uncomment it. Without it your
loop will fly around at the speed of light and not give Windows a chance
to process the Click event.

In practice you will not notice the "pause", but your program should be
more responsive to the clicks you intend to handle.
 
T

tracktraining

sorry, i guess i didnt' make my question/comment clear.

When i pasted the code (with the DoEvents uncomment) in my graph_click sub,
then run the program. The userform2 appears but i am unable to click the
Cancel button. When i click on the cancel button, the program still runs
though my sub and at the end then it will show "user cancelled", but the
program already completed so the point of having the cancel button is lost
=(.

so i created a userform2 and pasted the form code as in Patrick's response.

then i pasted the code form userform 1 into my Graph_button_click sub (but
was unable to hit the cancel button on the userform2, explained above) . My
sub Graph_button_click is pretty long so i won't paste it into this message.
Below is an idea of what i have in the sub. I guess i don't know how to use
the code from step 2 (see Patrick Molloy message) with my graph_button_click
code. Please advise.

sub Graph_button_click
obtain data
do calculation
create graphs
end sub

2)
Option Explicit
Private Sub CommandButton1_Click()
UserForm2.Show vbModeless
Dim i As Long
For i = 1 To 100000
UserForm2.Label2.Caption = i
DoEvents
If UserForm2.bCancelled Then Exit For
Next
If UserForm2.bCancelled Then
MsgBox "user cancelled"
else
MsgBox "finished normally"
End If
Unload UserForm2
End Sub


thanks for your help!
 
S

smartin

You need to figure out what parts of your code will run long and hard,
and judiciously insert DoEvents there, especially where it can break an
intense loop. Possibly, this is in the graph_click sub?

That you say 'the program still runs though my sub and at the end then
it will show "user cancelled" ' suggests to me that DoEvents is not
firing until /after/ the CPU-intensive part is already over. Does this
make sense?
 
T

tracktraining

yes, it makes sense. But I still can't get the cancel function to work (i.e.
cancel program when the cnacel button is pushed).
 
S

smartin

Ok, I have not been able to follow your code, but here's something you
can try.

Somewhere in a vicious loop, try simulating the button click by manually
calling the button click event. Put a breakpoint in there so you can
step through what happens next. Does your code act as expected?
 
T

tracktraining

code for the cancel message is not working as expected. I will need to find a
different approach. Thanks for helping.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top