我想使用无格式的用户表单,以便用户在回答用户表单上的问题之前可以浏览excel工作表。我需要暂停或循环执行代码,直到关闭用户窗体(隐藏或卸载)。
与此类似的问题: How can I wait for a specific code to run while when form is closed and is set to 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
答案 0 :(得分:4)
我的用户窗体在一个长子例程的中间打开,该例程需要在用户窗体关闭后完成执行。
您的过程执行了太多操作,需要分解为更小,更专业的过程。
正确的方法是将范例从过程转换为事件驱动 。
与其像这样显示表单的默认实例:
StartingSINT_Popup.Show vbModeless 'Open userform
具有一个包含其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
在表单的代码背后,声明一个Closed
事件:
Public Event Closed()
然后在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
现在说您将类命名为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
将演示者保持在模块级别,以使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
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
答案 1 :(得分:2)
我没有编写以下函数,但是已经使用了很长时间了,并且可以正常工作。
Private Function IsLoaded(ByVal formName As String) As Boolean
Dim frm As Object
For Each frm In VBA.UserForms
If frm.Name = formName Then
IsLoaded = True
Exit Function
End If
Next frm
IsLoaded = False
End Function
您将需要对字符串名称进行硬编码,而不要使用表单的.Name
属性,因为表单可能尚未加载且不包含此属性。
以下是如何使用此功能的小片段:
Do While IsLoaded("StartingSINT_Popup")
Debug.Print Time; " StartingSINT_Popup Is Loaded!"
Loop
答案 2 :(得分:0)
这是另一种选择...
1。在原始的[public]模块(调用用户表单1的模块)中,声明一个公共布尔变量。
Public done As Boolean
2。在用户表格1中,
a。为布尔变量分配默认值
b。致电用户表格2
c。做一个do while循环...
代码
Private Sub event_click()
done = False
Dim userform2 As New userform
userform2.Show Modeless
'This will loop through until userform2 changes done variable to "True"
Do While done = False
DoEvents
Loop
'Code after done with userform2
dataSource.Refresh
End Sub
3。在用户窗体2 中,将布尔值更改为中断循环
代码
Private Sub submit_Click()
'Userform submit code
Dim name As String
name = TextBox.Value
sql = "INSERT INTO table (field) VALUES ('" & name & "')"
Call query(sql)
'IMPORTANT: change Boolean variable to break loop before exiting userform
done = True
Unload Me
End Sub