Modeless form that still pauses code execution

21,482

You should be able display the form as vbModeless and only execute code when specifically requested, i.e., from a CommandButton or other control.

You then leave the form visible/shown until it is specifically closed, via the "X" button or via another control which calls the UserForm_Terminate event.

In order to achieve this, you may need to move some of your executable code in to another subroutine and/or module, and call this subroutine for example from a CommandButton_Click event.

You already have a subroutine somewhere that contains a line like:

Sub ShowTheForm()

    UserForm1.Show vbModeless
End Sub

So the form is displayed properly to allow user-input to the parent application.

You don't really need to put any other code in the above module. We will put the other code in other modules/subs, and then call it from user controls like command buttons.

Example:

Take all of your executable code, and put it in another subroutine (and if it suits your organizational preference, another module), like:

Sub MyMacro(msg$)
    MsgBox msg
End Sub

On the UserForm, add a command button and assign it the following code:

Sub CommandButton1_Click()
    MyMacro "hello"
End Sub

Now, the form will display until the user clicks the "X" button. Code will only run when called from the command button.

EDIT FOR CLARIFICATION

You don't need to "pause" the execution using this method. Execution ends once the form is displayed modelessly, and the form persists. The object has some events which you may use to trigger further execution of code.

Share:
21,482
lfrandom
Author by

lfrandom

Updated on October 10, 2020

Comments

  • lfrandom
    lfrandom over 3 years

    Is there anyway to have a userform that acts modeless, while still pausing code execution like a modal form?

    I'd like the userform to show, but still allow interaction with the parent program. Modal forms block interaction with the parent program. A modeless form would work, but I would like the code execution to pause while the form is up.

    I've worked around this by creating an infinite loop that checks if the form is visible, but that seems a bit hacky.

    Public Sub GetFormInfoAndDoStuff    
      ufForm.show vbModeless
    
      Do while ufForm.Visible
        DoEvents
      Loop
    
      ' Do other stuff dependent on form 
    End Sub
    

    EDITED to clarify that code after .show exists which must execute after the user form is done

  • lfrandom
    lfrandom about 11 years
    Unless I am reading you incorrectly, this works, but only in the case where the main module doesn't have anything else to do. In the main module, I am doing a lot of activities within my main module, after the form is displayed. If I just use a modeless form, the code below the .show executes right after showing the form.
  • David Zemens
    David Zemens about 11 years
    I think you need to reoganize your code. I currently have an application with about 50 code modules, several hundred subroutines and functions, 6 user forms with hundreds of form fields spread across those forms, and a class module for Events. Everything in my application is dependent on the form as inputs to execute other subroutines and functions. The philosophy is to let the form be a form, and use other subroutines and functions to perform operations on your workbook, etc.
  • David Zemens
    David Zemens about 11 years
    If I just use a modeless form, the code below the .show executes right after showing the form. This is precisely why you need to send your executable code in to other modules and subroutines, and only call those subroutines when appropriate.
  • David Zemens
    David Zemens about 11 years
    You could even call your executable code from the UserForm_Terminate event handler.
  • lfrandom
    lfrandom about 11 years
    I get what you are saying, but from an flow standpoint, I need the code in my main module. Basically the user form allows the user to choose an application, but in some cases we just give them a new application. The main looks like If not NewPerson then Set Application = GetPersonApplication where GetPersonApplication is this form.
  • David Zemens
    David Zemens about 11 years
    I'm pretty sure there is no need for the code to all be in the Main module. You can always create public variables, or pass Object variables between subroutines and modules, etc.