VBA - UserForm Button (Macro) to Continue running the sub - vba

I have a sub called as sub1() which activates the userform1 through the command userform1.show()
This userform1 has a button called as continue. On clicking that button continue - A Macro called as Private Sub continuebutton() gets activated.
I want to program in such a way that it redirects to the line after userform1.show() in sub1().
Is it something that can be done?

Theoretically, what you want is possible, if you do it like this:
In the UserForm:
Private Sub btnContinue_Click()
flag = True
Debug.Print "I continue ..."
sub1
End Sub
In a module:
Public flag As Boolean
Public Sub sub1()
If flag Then
Debug.Print "sub 1 continues here..."
Else
flag = False
UserForm1.Show
Exit Sub
End If
End Sub
It will work exactly as intended, BUT it is not a good practice to work this way. (Some people may throw stones at you for using public variables at all in VBA.) Here are two articles, that give better ideas:
https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/
Disclaimer - this one is mine:
http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/

On the form properties for userform1, set its "Modal" property to true.
When the form opens, it will have exclusive focus, and the code in sub1 will not continue running until after it closes. This may be the solution you need.
In the code below, the msgbox will only appear once userform1 closes:
sub sub1()
userform1.show()
msgbox "Now continuing with sub1"
end sub

No way as long as you show the form.
If you show the form modal, the calling routine continues if (and only if) the form is closed.
If you show the form non-modal, the code continues to run directly after the show - so it's already done.
So either you have to close the form when the user clicks the "continue..." button to let the calling macro continue or you have to split your code into two routines and call the second on button-click.

You can change your Sub1 as follows:
Sub sub1(Optional Continue As Boolean)
If Continue = True Then
DoSomeStuff
Exit Sub
End If
userform1.show
End sub
And then, you can call your sub1 using:
Private Sub continuebutton()
Call sub1(True)
End Sub
Hope it helps

If you don't want to go with the 'Modal Form' solution, you could add a subroutine to your main module, and call it when required. So, in userform1, you have:
sub sub1()
userform1.show()
end sub
public sub sub2()
msgbox "Now continuing..."
end sub
And then in userform1, set some code on its onClose event:
Private Sub continuebutton()
Call sub2()
end sub

Related

Limiting user interaction with the workbook - hide workbook / show only userform

Is it possible to get the same effect using ThisWorkbook.Application.Visible = False but only for one Workbook. I mean, I'd like to limiting user interaction only to UserForm, but I need have an access to anothers workbooks. At the moment this function cause hide workbook, but after open some another excel file - all object from userform are not available.
Private Sub Workbook_Open()
ThisWorkbook.Application.Visible = False
Starter.Show modeless
End Sub
Thanks for your support.
Please, create a form, let us say "Starter", having (at least) a button ("btExit"), copy the next code in its code module and show it. If the form in discussion already has some code in Initialize and Terminate events, please add the next code lines, too:
Option Explicit
Private Sub btExit_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
ThisWorkbook.Windows(1).Visible = False
End Sub
Private Sub UserForm_Terminate()
ThisWorkbook.Windows(1).Visible = True
End Sub
So, you can simple use workbook Open event in this way:
Private Sub Workbook_Open()
Starter.Show vbModeless
End Sub

Is it possible to display a userform and executes a code bellow the .show method?

I want to display Userform2 from Userform1 then continue executing some code in Userform1 WITHOUT unloading Userform1
Private Sub CommandButton1_Click()
UserForm2.Show
x = 1
MsgBox x
End Sub
Not sure that's what you want, but this would do what you describe:
UserForm2.Show vbModeless
Note that UserForm2 isn't modal anymore, which means the user can click outside the form, and even end up hiding it behind UserForm1.
Modal forms return execution to the caller when they're hidden/closed or destroyed, modeless forms return execution to the caller immediately (Initialize and Activate handlers will run first though).
Assuming you mean without unloading Userform2...
Userform1 will wait for Userform2 to finish... however you can do something like this:
Userform1:
Private Sub CommandButton1_Click()
UserForm2.Show
End Sub
Sub uf1msgbox()
X = 1
MsgBox X
End Sub
Userform2:
Private Sub CommandButton1_Click()
UserForm1.uf1msgbox
End Sub

How do i perform the desired operation If one of the command button is OK and the other is CANCEL

Can anyone tell me How do i do certain task based on the command button options.
I have a Userform where user submits his data and it has 2 command buttons one is OK and the other is CANCEL. I have to exit when user clicks CANCEL and continue the Process when user clicks ok
file_name=userform1.textbox1.value
This is how we can get the data of the text box into our functions but what is the way to know which command button key is pressed ? Becuase if i press OK or CANCEL the operation is still being performed. I have tried like these
value=userform1.commandbutton1.value
value2=userform1.commandbutton2.value
not working. I even tried these
commandbutton1_click() \\ this is the OK command button
call main
end sub
commandbutton2_click() \\ this is the CANCEL command button
end sub
I have tried To call the main sub_routine from the OK sub routine But it says main routine not found becuase I have written these codes in the thisworkbook.and the commandbutton1_click routine is inside the Userform1 module
SO how do i make it work? I hope you understood where I'm Stucking up.Thank you in advance
Private Sub CommandButton1_Click() 'should be called cmdOk
main
End Sub
Private Sub CommandButton2_Click() 'should be called something like cmdCancel
Unload Me
End Sub
Private Sub main()
'DO PROCESSING
End Sub
Do you call main on Form_Load() or Form_Activate() or anything like this? When clicking Cancel, the above unloads the form. When clicking Ok, it starts the processing. There is not more to it.
If you want to keep the main method outside of your userform, you can try something like this, based on the example given by #cularis
' This way you can keep your code in ThisWorkbook
' I would recommend creating a new module.
' You can name your module whatever you'd like.
Private Sub CommandButton1_Click()
ThisWorkbook.main
End Sub
Private Sub CommandButton2_Click()
Unload Me
End Sub

How to stop VBA code running?

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.
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
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
Or, if you want to avoid the use of a global variable you could use the rarely used .Tag property of the userform:
Private Sub CommandButton1_Click()
Me.CommandButton1.Enabled = False 'Disabling button so user cannot push it
'multiple times
Me.CommandButton1.caption = "Wait..." 'Jamie's suggestion
Me.Tag = "Cancel"
End Sub
Private Sub SomeVBASub
If LCase(UserForm1.Tag) = "cancel" Then
GoTo StopProcess
Else
'DoStuff
End If
Exit Sub
StopProcess:
'Here you can do some steps to be able to cancel process adequately
'i.e. setting collections to "Nothing" deleting some files...
End Sub
what jamietre said, but
Private Sub SomeVBASub
Cancel=False
DoStuff
If not Cancel Then DoAnotherStuff
If not Cancel Then AndFinallyDothis
End Sub
I do this a lot. A lot. :-)
I have got used to using "DoEvents" more often, but still tend to set things running without really double checking a sure stop method.
Then, today, having done it again, I thought, "Well just wait for the end in 3 hours", and started paddling around in the ribbon. Earlier, I had noticed in the "View" section of the Ribbon a "Macros" pull down, and thought I have a look to see if I could see my interminable Macro running....
I now realise you can also get this up using Alt-F8.
Then I thought, well what if I "Step into" a different Macro, would that rescue me? It did :-)
It also works if you step into your running Macro (but you still lose where you're upto), unless you are a very lazy programmer like me and declare lots of "Global" variables, in which case the Global data is retained :-)
K
~ For those using custom input box
Private Sub CommandButton1_Click()
DoCmd.Close acForm, Me.Name
End
End Sub
This is an old post, but given the title of this question, the END option should be described in more detail. This can be used to stop ALL PROCEDURES (not just the subroutine running). It can also be used within a function to stop other Subroutines (which I find useful for some add-ins I work with).
As Microsoft states:
Terminates execution immediately. Never required by itself but may be placed anywhere in a procedure to end code execution, close files opened with the Open statement, and to clear variables*. I noticed that the END method is not described in much detail. This can be used to stop ALL PROCEDURES (not just the subroutine running).
Here is an illustrative example:
Sub RunSomeMacros()
Call FirstPart
Call SecondPart
'the below code will not be executed if user clicks yes during SecondPart.
Call ThirdPart
MsgBox "All of the macros have been run."
End Sub
Private Sub FirstPart()
MsgBox "This is the first macro"
End Sub
Private Sub SecondPart()
Dim answer As Long
answer = MsgBox("Do you want to stop the macros?", vbYesNo)
If answer = vbYes Then
'Stops All macros!
End
End If
MsgBox "You clicked ""NO"" so the macros are still rolling..."
End Sub
Private Sub ThirdPart()
MsgBox "Final Macro was run."
End Sub

Why does Showing a UserForm as Modal Stop Code Execution?

The following VBA code stops at Me.Show. From my tests, it seems that Me.Show stops all code execution, even if the code is inside the UserForm.
This part is outside the UserForm:
Public Sub TestProgress()
Dim objProgress As New UserForm1
objProgress.ShowProgress
Unload objProgress
End Sub
This part is inside the UserForm:
Private Sub ShowProgress()
Me.Show vbModal
Dim intSecond As Integer
For intSecond = 1 To 5
Application.Wait Now + TimeValue("0:00:01")
Me.ProgressBar1.Value = intSecond / 5 * 100
Next intSecond
Me.Hide
End Sub
The code stops at Me.Show, after the UserForm is displayed. There is no error, it just discontinues executing code. It seems that the only way to execute code inside a modal UserForm in VBA is to include it in the UserForm_Activate procedure like this:
This part is outside the UserForm:
Public Sub TestProgress()
Dim objProgress As New UserForm1
Load objProgress
Unload objProgress
End Sub
This part is inside the UserForm:
Private Sub UserForm_Initialize()
Me.Show vbModal
End Sub
Private Sub UserForm_Activate()
Dim intSecond As Integer
For intSecond = 1 To 5
Application.Wait Now + TimeValue("0:00:01")
Me.ProgressBar1.Value = intSecond / 5 * 100
Next intSecond
Me.Hide
End Sub
Of course, I can't put Me.Show inside UserForm_Activate because that procedure only fires after the UserForm Show event.
The documentation for UserForm.ShowModal says "When a UserForm is modal, the user must supply information or close the UserForm before using any other part of the application. No subsequent code is executed until the UserForm is hidden or unloaded."
I am trying to use a modal UseForm as a progress bar to prevent the user from interacting with the application while a process runs. But this will be difficult to accomplish if all my code has to be within the UserForm_Activate procedure.
Am I missing something here? Why does all code execution stop at Me.Show?
When the form is displayed with vbModal, the code will suspend execution and wait for user interaction with the form. For example clicking a button or using a dropdown.
If you update the form property
ShowModal = False
and remove vbModal from your code. This will allow code execution to continue when the form is displayed.
I was searching for an answer to why I was getting the following error:
Run time error '5': Invalid procedure call or argument
when running this line of code:
UserForm1.Show True
even though this line works:
UserForm1.Show False
Of course. True is not the same as vbModal! So the simple answer is to use the correct enumerations:
UserForm1.Show vbModal
UserForm1.Show vbModeless
I think I figured this out.
After Me.Show the UserForm_Activate event fires. If there is no code in the UserForm_Activate procedure nothing will happen because VBA is waiting for Me.Hide.
So the order of events is: Me.Show > UserForm_Activate > Me.Hide
Any code that I want to run must be in the UserForm_Activate procedure and must be before Me.Hide.
The structure is very strict, but I may be able to use that structure to my advantage.