views:

784

answers:

3

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?

Thanks!

+2  A: 

That is what modal is for. As you say:

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.

It is not suitable for a progress bar. You could use a pop-up form.

Have you considered: ACC2000: How to Use the Status Bar Progress Meter ?

Remou
I did try using the status bar, but I am in Excel, and I need a cancel button. Thanks!
Kuyenda
A: 

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.

Thanks!

Kuyenda
+1  A: 

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.

Robert Mearns
Yup, vbModeless UserForms are easy, but I need to lock out user interaction with the application until the process finishes. It was just a matter of figuring out how to structure the code in a vbModal UserForm. Too bad the documentation doesn't just say "if you use vbModal make sure to put any code you want executed in UserForm_Activate and _before_ Me.Hide. Thanks!
Kuyenda