我遇到了类似的问题并阅读了回复:仍然暂停代码执行的无模式表单
我一直试图在我自己的情况中应用大卫·泽门斯提供的建议。就我而言,我似乎无法找到一种在不利用GoTo的情况下纳入Zemen先生建议的方法。
我想知道是否有更好或更优雅的解决方案。
以下是我正在做的事情的概述:
我有一个带有命令按钮的用户窗体,该按钮开始执行代码,该代码将在多个Excel工作簿上执行多个操作。因此,有许多代码块,成功完成一个代码块允许执行后续代码块。
在某一点,根据具体情况,代码可能需要用户输入;在其他情况下,可以从Excel获取所需的数据。如果需要来自用户的输入,则会显示另一个用户窗体。
在输入输入之前,用户可能需要查看多个不同的 Excel 工作表,因此用户窗体是无模式的。因此,代码将停止,直到用户输入所需的输入并单击另一个命令按钮。
正是在这一点上,我遇到了麻烦:如何恢复程序流。"从上次中断的地方继续"的唯一方法是使用 GoTo 语句吗?或者是否有某种方法来组织模块,以便有一个一致的程序流,在一个位置定义,而不是从可能需要用户输入的点重复?
对这个问题的看法。希望我正确理解了问题。
假设:
- 有两种用户表单。
- 带有用于开始处理的按钮的用户窗体 1。
- 带有提供中间输入的按钮的用户窗体 2。
- 模块内用于启动/启动用户窗体 1 的子组件。
VBA 代码(用于子例程)
Sub LaunchUserForm1()
Dim frm As New UserForm1
'/ Launch the main userform.
frm.Show vbModeless
End Sub
VBA 代码(用于用户窗体 1)
Private Sub cmdStart_Click()
Dim i As Long
Dim linc As Long
Dim bCancel As Boolean
Dim frm As UserForm2
'/ Prints 1 to 5 plus the value returned from UserForm2.
For i = 1 To 5
If i = 2 Then
Set frm = New UserForm2
'/ Launch supplementary form.
frm.Show vbModeless
'<< This is just a PoC. If you have large number of inputs, better way will be
' to create another prop such as Waiting(Boolean Type) and then manipulate it as and when User
' supplies valid input. Then validate the same in While loop>>
'/ Wait till we get the value from UserForm2.
'/ Or the User Cancels the Form with out any input.
Do While linc < 1 And (linc < 1 And bCancel = False)
linc = frm.Prop1
bCancel = frm.Cancel
DoEvents
Loop
Set frm = Nothing
End If
Debug.Print i + linc
Next
MsgBox "User Form1's ops finished."
End Sub
VBA 代码(用于用户窗体 2)
Dim m_Cancel As Boolean
Dim m_prop1 As Long
Public Property Let Prop1(lVal As Long)
m_prop1 = lVal
End Property
Public Property Get Prop1() As Long
Prop1 = m_prop1
End Property
Public Property Let Cancel(bVal As Boolean)
m_Cancel = bVal
End Property
Public Property Get Cancel() As Boolean
Cancel = m_Cancel
End Property
Private Sub cmdlinc_Click()
'/Set the Property Value to 10
Me.Prop1 = 10
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'/ Diasble X button
Me.Cancel = True
Me.Hide
Cancel = True
End Sub
好的,这是我的想法。
您有一个用户窗体frmSelectUpdateSheet
,您希望使用该窗体,以便在无法以编程方式确定工作表时允许用户选择工作表。 问题是,如果您执行.Show vbModeless
(允许用户导航工作表),则代码将继续执行,这会导致错误或其他不需要的输出。
我认为可以调整我在上一个答案中描述的方法。但是,这是不可能的,除非您付钱给我对你所有代码进行逆向工程:P
假设您有一个此时需要分配的Worksheet
对象变量(或表示工作表名称等的字符串)(并且此变量在范围内Public
),只需使用表单上的 CommandButton 根据frmSelectUpdateSheet
列表框中的选定项分配此变量。
出于多种原因(其中最重要的是试图避免为这种边缘情况重新设计应用程序),这可能是一种更好的方法,例如:
-
这样可以保持表单
vbModal
,并防止用户在此过程中无意中篡改工作表等。 -
使用此方法,线程将保留在显示
frmSelectUpdateSheet
vbModal
中,并且您依赖于表单的事件过程来控制流程流/代码执行。 -
它应该更容易(因此更便宜)实现;无论你是自己做还是外包。
-
维护起来应该更容易(因此更便宜)。
现在,仔细检查,看起来您已经在使用 cmdbtnSelect_Click
事件处理程序执行这种方法,这让我相信存在相关/后续问题:
名称(在列表框中)不足以让用户识别正确的工作表。因此,如果用户需要能够"滚动"工作表(例如,查看不适合窗口的数据等),则添加一些微调器按钮或其他表单控件以允许他们导航工作表。