如何让 VBA 代码等到 vbModeless 用户窗体关闭

Nic*_*ick 2 excel vba userform

我想使用无格式的用户表单,以便用户可以在回答用户表单上的问题之前浏览 Excel 表。我需要暂停或循环代码,直到用户窗体关闭(隐藏或卸载)。

与此类似的问题: 当表单关闭并设置为 vbModeless 时,如何等待特定代码运行? 但这里的解决方案不适用于我的应用程序;我的用户窗体在一个长子程序的中间打开,该子程序需要在用户窗体关闭后完成执行。

Dim popupActive as Boolean

popupActive = True
StartingSINT_Popup.Show vbModeless 'Open userform

'have VBA code wait until userform is closed
wait until popupActive = False 'set to false with OK button on userform

'continue code with info input inside StartingSINT_Popup userform
Run Code Online (Sandbox Code Playgroud)

Mat*_*don 7

我的用户窗体在一个长子程序的中间打开,该子程序需要在用户窗体关闭后完成执行。

您的程序做的事情太多,需要分解为更小、更专业的程序。

做到这一点的正确方法是将范式从程序转换事件驱动

而不是像这样显示表单的默认实例:

StartingSINT_Popup.Show vbModeless 'Open userform
Run Code Online (Sandbox Code Playgroud)

有一个包含WithEvent它的实例的类模块:

Private WithEvents popup As StartingSINT_Popup

Private Sub Class_Initialize()
    Set popup = New StartingSINT_Popup
End Sub

Public Sub Show()
    popup.Show vbModeless
End Sub

Private Sub popup_Closed()
    ' code to run when the form is closed
End Sub
Run Code Online (Sandbox Code Playgroud)

在表单的代码隐藏中,声明一个Closed事件:

Public Event Closed()
Run Code Online (Sandbox Code Playgroud)

然后在QueryClose处理程序中提出它:

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = 0 Then 'controlbox was clicked (the "red X button")
        Cancel = True 'would otherwise destroy the form instance
        Me.Hide 'always hide, never unload
    End If
    RaiseEvent Closed
End Sub
Run Code Online (Sandbox Code Playgroud)

现在假设您命名了该类PopupPresenter,您的过程现在可以执行以下操作:

Private presenter As PopupPresenter

Public Sub DoStuff()
    Set presenter = New PopupPresenter

    'do stuff...

    presenter.Show

    'rest of the code in this scope will run immediately AND THIS IS FINE

End Sub
Run Code Online (Sandbox Code Playgroud)

将演示者保持在模块级别,以便对象在DoStuff完成时不会超出范围,并传递任何变量/值或在表单关闭时演示者对象需要完成其工作的状态。您可以通过公开属性或公共字段/变量来做到这一点(尽管更喜欢属性,但这是另一个话题):

Private WithEvents popup As StartingSINT_Popup
Public Foo As String

Private Sub Class_Initialize()
    Set popup = New StartingSINT_Popup
End Sub

Public Sub Show()
    popup.Show vbModeless
End Sub

Private Sub popup_Closed()
    ' code to run when the form is closed
    MsgBox Foo
End Sub
Run Code Online (Sandbox Code Playgroud)
Private presenter As PopupPresenter

Public Sub DoStuff()
    Set presenter = New PopupPresenter

    'do stuff...

    presenter.Show
    presenter.Foo = "some data"

    'rest of the code in this scope will run immediately AND THIS IS FINE

End Sub
Run Code Online (Sandbox Code Playgroud)