5

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

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

我通过创建一个检查表单是否可见的无限循环来解决这个问题,但这似乎有点hacky。

Public Sub GetFormInfoAndDoStuff    
  ufForm.show vbModeless

  Do while ufForm.Visible
    DoEvents
  Loop

  ' Do other stuff dependent on form 
End Sub

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

4

3 回答 3

6

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

UserForm_Terminate然后,您可以通过“X”按钮或通过另一个调用事件的控件使表单保持可见/显示,直到它被特别关闭。

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

您已经在某处有一个子例程,其中包含如下行:

Sub ShowTheForm()

    UserForm1.Show vbModeless
End Sub

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

您实际上不需要在上述模块中添加任何其他代码。我们将把其他代码放在其他模块/子程序中,然后从命令按钮等用户控件中调用它。

例子:

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

Sub MyMacro(msg$)
    MsgBox msg
End Sub

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

Sub CommandButton1_Click()
    MyMacro "hello"
End Sub

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

编辑澄清

您无需使用此方法“暂停”执行。一旦表单无模式显示,执行就会结束,并且表单仍然存在。该对象具有一些事件,您可以使用这些事件来触发代码的进一步执行。

于 2013-05-31T15:16:26.947 回答
0

这就是我所做的。

此示例适用于我称为“查找页眉”的表单。该代码尝试查找多个列标题,但其中一些的标记可能丢失(并且标题文本可能已被随机内容覆盖),因此我可能需要暂停并要求用户定位(单击)我的一些标题:

首先,将此声明放入标准模块中:

Public bDlgFindHeaderIsShowingModeless As Boolean

然后,将其放在关闭无模式对话框的任何按钮或其他控件的事件过程中,例如表单的 OK 和 Cancel 按钮的 Click 事件:

bDlgFindHeaderIsShowingModeless = False

然后,将其放在代码中您希望在暂停用户交互时显示无模式表单的任何位置:

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

是的,它会搅动 CPU,因此如果您使用的是单核处理器并且正在运行至关重要的后台进程,您可能不想这样做。但它有效;在显示无模式表单时,用户能够轻松流畅地与 Excel 交互。用户不会觉得他们在与无限循环作斗争。

于 2017-05-03T16:39:09.697 回答
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

我将“模式”设置为全局变量,因为我将此用户表单用于多个潜艇。如果您使用的是单个子,则可以在本地使用它。通过在“ThisWorkbook”选项卡下打开此工作簿并添加以下代码,我还使“模式”为假:

Private Sub Workbook_Open()
    Mode = False
End Sub

仅当您将用户表单用于多个子时,才需要再次这样做。当您按下继续按钮时,最后在您的用户表单代码下添加此代码。

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

如果您只使用一种 sub 方法,请跳过 if 语句并调用 sub。

于 2019-10-09T15:23:52.300 回答