仍然暂停代码执行的无模式表单

时间:2013-05-31 13:57:13

标签: vba modal-dialog userform modeless

是否有一个无模式的用户表单,同时仍然暂停代码执行,如模式表单?

我希望显示userform,但仍允许与父程序进行交互。模态表单阻止与父程序的交互。一个无模式的形式可以工作,但我希望代码执行在表单启动时暂停。

我通过创建一个无限循环来检查表单是否可见,但这看起来有点hacky。

Public Sub GetFormInfoAndDoStuff    
  ufForm.show vbModeless

  Do while ufForm.Visible
    DoEvents
  Loop

  ' Do other stuff dependent on form 
End Sub

已编辑以澄清.show之后存在的代码,必须在用户表单完成后执行

3 个答案:

答案 0 :(得分:4)

您应该能够将表单显示为vbModeless,并且仅在特别请求时执行代码,即来自CommandButton或其他控件。

然后,您可以通过“X”按钮或通过调用UserForm_Terminate事件的其他控件将表单显示/显示,直到它被特别关闭为止。

为了实现这一点,您可能需要将一些可执行代码移动到另一个子例程和/或模块中,并从CommandButton_Click事件中调用此子例程。

你已经有一个包含如下行的子程序:

Sub ShowTheForm()

    UserForm1.Show vbModeless
End Sub

因此,表单正确显示以允许用户输入到父应用程序。

您实际上不需要在上面的模块中添加任何其他代码。我们将其他代码放在其他modules / subs中,然后从用户控件(如命令按钮)调用它。

示例:

获取所有可执行代码,并将其放入另一个子例程(如果它适合您的组织偏好,另一个模块),例如:

Sub MyMacro(msg$)
    MsgBox msg
End Sub

在UserForm上,添加一个命令按钮并为其分配以下代码:

Sub CommandButton1_Click()
    MyMacro "hello"
End Sub

现在,表单将一直显示,直到用户单击“X”按钮。代码仅在从命令按钮调用时运行。

编辑澄清

您无需使用此方法“暂停”执行。表单无模式显示后执行结束,表单仍然存在。该对象有一些事件可用于触发进一步执行代码。

答案 1 :(得分:0)

这就是我的所作所为。

此示例适用于我称为" Find Header"的表单。代码试图找到几个列标题,但其中一些列标题可能丢失(标题文本可能已被随机覆盖),所以我可能需要暂停并要求用户定位(单击)我的一些标题:

首先,将此声明放在标准模块

Public bDlgFindHeaderIsShowingModeless As Boolean

然后,将其放入任何取消无模式对话框的按钮或其他控件的事件过程中,例如表单的“单击事件”和“取消”按钮:

bDlgFindHeaderIsShowingModeless = False

然后,将其放在代码中的任何位置,以便在暂停用户交互时显示无模式窗体:

bDlgFindHeaderIsShowingModeless = True 'init
frmFindHeader.Show vbModeless
Do
    If Not bDlgFindHeaderIsShowingModeless Then Exit Do
    DoEvents
Loop

是的,它会搅动CPU,因此如果您使用的是单核处理器,并且运行着至关重要的后台进程,您可能不想这样做。但它有效;在无模式窗体显示时,用户可以轻松,顺畅地与Excel交互。用户并不觉得他们正在无休止地对抗。

答案 2 :(得分:0)

最佳方法是使用两个不同的子。我能够解决此问题,而无需按如下方式拆分子项目:

Public Mode as Boolean

Sub Stuff()
    If Mode Then
        Goto Continue
    End If

    'Code before Userform

    Mode = True
    Userform.Show vbModeless
    Exit Sub

Continue:
    Mode = False

   'Rest of your code

End Sub

我将“模式”(Mode)设置为全局变量,因为我将此用户窗体用于多个子项。如果使用单个子,则可以在本地使用。通过在“ ThisWorkbook”选项卡下并添加以下代码,我在打开此工作簿时也将“模式”设置为false:

Private Sub Workbook_Open()
    Mode = False
End Sub

仅当您将用户表单用于多个子菜单时,才需要再次使用。 按下“继续”按钮时,最后将此代码添加到您的用户表单代码下。

Private Sub Confirm_Click()
    Userform.hide
    if Mode Then
        Call Stuff
    End If 
End Sub

如果您仅使用one子方法,请跳过if语句,仅调用该子方法。