用户表单 - Return 到 public 子从私人子
Userform - Return to public sub from private sub
我有下面的代码,它是一个私有子程序,它是从 public 子程序中的 Userform3.show 初始化的,据我所知,下面的代码可以工作,但它不会 return 到 public 子完成。
请注意,当我更改 sheet8.range(I16) 的值时,会调用另一个私有 sub。但是我相信下面的代码是问题所在。
任何人都可以告诉我如何在完成后将私有子 return 转到 public 子吗?
Private Sub UserForm_Initialize()
'populate "Combo-Box with Boards
With Me.ComboBox1
.Clear ' clear previous items (not to have "doubles")
.AddItem "BISSB"
.AddItem "MORIB"
.AddItem "RMIB"
End With
End Sub
Private Sub CommandButton1_Click()
If Me.ComboBox1.ListIndex = -1 Then
UserForm3.Hide
MsgBox "No board was selected, please re-run macro and select appropriate board"
Exit Sub
Else
Sheet8.Range("I16").Value = ComboBox1.Text
End If
End Sub
Private Sub CommandButton2_Click()
UserForm3.Hide
MsgBox "No board was selected, please re-run macro and select appropriate board"
End
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
MsgBox "No board was selected, please re-run macro and select appropriate board"
End
End If
End Sub
Public 子
开始
Sub newResumeAssessment_Click()
Dim answer As Variant
Dim Proceed As Boolean
Dim Uname As String
If UCase(Sheets("Main Menu").Range("A1")) = "YES" Then
answer = 6
Else
answer = MsgBox("Click Yes to start a Business Case." & _
vbCrLf & "Click No to resume the Business Case." & vbCrLf & _
"Click Cancel to go back to the main menu." & vbNewLine & _
vbNewLine & "Please note, you will need to load the board submission " & _
"tracker before you start a new business case.", 35, "Business Case")
End If
If answer = 6 Then
UserForm3.Show
除非您以非模态方式显示表单,打开代码总是会暂停,直到表单关闭
第一件事,删除End
,到处都是。 End
是一个大大的红色 NUKE 'EM ALL 按钮, 结束 执行,然后 - 在 End
执行后,你在哪里都没有关系调用栈,因为没有调用栈了;您的代码不再 运行ning,"return" 无处可去。
第二件事,不要在表单的默认实例中保留状态。像对待对象一样对待它,并在需要时 New
创建一个新实例 - 这样您就不需要为 Unload
对它进行 and/or 重置之间的状态而烦恼调用:_Initialize
处理程序每次都会 运行,并且不需要 Clear
上一次调用的项目,因为您每次都将使用一个新实例时间。你这样做:
With New UserForm3 'UserForm_Initialize handler runs here
.Show 'UserForm_Activate handler runs here
'anything after .Show will only run after the form is closed
If Not .Cancelled Then
Sheet8.Range("I16").Value = .ComboBox1.Text
End If
End With 'UserForm_Terminate handler runs here
请注意工作表没有被表单写入 - 这不是它的工作!那么我们如何让 Cancelled
成员合法呢?
首先你 命名事物 并使 CommandButton1
成为 OkButton
并且 CommandButton2
成为 CancelButton
- 或者其他什么 - 只是不是Button1 和 Button2。
我喜欢你 隐藏 表单实例而不是用 Unload Me
对其进行核对,但是你 明确地 再次关闭 默认实例 ,这意味着上面的 New UserForm3
代码将不会隐藏显示的相同实例。当您打算使用 Me
.
时,从不 使用默认实例限定成员调用
换句话说:
UserForm3.Hide 'hides the default instance of UserForm3
Me.Hide 'hides whatever the current instance is
Hide 'same as Me.Hide
所以。添加一个Private isCancelled As Boolean
私有字段(模块级变量),然后暴露一个Public Property Get Cancelled() As Boolean
public属性getter那个returns它:
Option Explicit
Private isCancelled As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = isCancelled
End Property
接下来,让您的取消按钮设置标志:
Private Sub CancelButton_Click()
isCancelled = True
Me.Hide
End Sub
然后让 QueryClose
处理程序也设置它 - 并尽可能使用现有的命名常量:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
isCancelled = True
Me.Hide
End If
End Sub
然后在确定按钮的处理程序中实现您的 "happy-path" 逻辑:
Private Sub OkButton_Click()
Me.Hide
End Sub
我会在用户做出选择之前禁用“确定”按钮 - 这样他们就可以取消、删除或做出有效选择!
Public Property Get SelectedBoard() As String
SelectedBoard = IIf(Me.ComboBox1.ListIndex = -1, vbNullString, Me.ComboBox1.Text)
End Property
Private Sub ComboBox1_Change()
ValidateForm
End Sub
Private Sub ValidateForm()
Me.OkButton.Enabled = (SelectedBoard <> vbNullString)
End Sub
Private Sub UserForm_Activate()
ValidateForm
End Sub
现在调用者可以是这样的:
With New UserForm3
.Show
If Not .Cancelled Then
Sheet8.Range("I16").Value = .SelectedBoard
Else
MsgBox "No board was selected, please re-run macro and select appropriate board"
End If
End With
现在您的表单只不过是代码的 I/O 设备,它应该是这样的。而且您正在使用对象而不是全局状态。
长话短说:
- 删除
End
指令,无论它们在哪里。
- 不要在
UserForm3
中引用 UserForm3
(请改用 Me
)。
- 每次都使用一个新的
New
实例。
- 公开
Property Get
成员供调用代码访问,以抽象出调用者不需要关心的控件。
- 不允许表单在无效状态下被接受。
我有下面的代码,它是一个私有子程序,它是从 public 子程序中的 Userform3.show 初始化的,据我所知,下面的代码可以工作,但它不会 return 到 public 子完成。
请注意,当我更改 sheet8.range(I16) 的值时,会调用另一个私有 sub。但是我相信下面的代码是问题所在。
任何人都可以告诉我如何在完成后将私有子 return 转到 public 子吗?
Private Sub UserForm_Initialize()
'populate "Combo-Box with Boards
With Me.ComboBox1
.Clear ' clear previous items (not to have "doubles")
.AddItem "BISSB"
.AddItem "MORIB"
.AddItem "RMIB"
End With
End Sub
Private Sub CommandButton1_Click()
If Me.ComboBox1.ListIndex = -1 Then
UserForm3.Hide
MsgBox "No board was selected, please re-run macro and select appropriate board"
Exit Sub
Else
Sheet8.Range("I16").Value = ComboBox1.Text
End If
End Sub
Private Sub CommandButton2_Click()
UserForm3.Hide
MsgBox "No board was selected, please re-run macro and select appropriate board"
End
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
MsgBox "No board was selected, please re-run macro and select appropriate board"
End
End If
End Sub
Public 子
开始Sub newResumeAssessment_Click()
Dim answer As Variant
Dim Proceed As Boolean
Dim Uname As String
If UCase(Sheets("Main Menu").Range("A1")) = "YES" Then
answer = 6
Else
answer = MsgBox("Click Yes to start a Business Case." & _
vbCrLf & "Click No to resume the Business Case." & vbCrLf & _
"Click Cancel to go back to the main menu." & vbNewLine & _
vbNewLine & "Please note, you will need to load the board submission " & _
"tracker before you start a new business case.", 35, "Business Case")
End If
If answer = 6 Then
UserForm3.Show
除非您以非模态方式显示表单,打开代码总是会暂停,直到表单关闭
第一件事,删除End
,到处都是。 End
是一个大大的红色 NUKE 'EM ALL 按钮, 结束 执行,然后 - 在 End
执行后,你在哪里都没有关系调用栈,因为没有调用栈了;您的代码不再 运行ning,"return" 无处可去。
第二件事,不要在表单的默认实例中保留状态。像对待对象一样对待它,并在需要时 New
创建一个新实例 - 这样您就不需要为 Unload
对它进行 and/or 重置之间的状态而烦恼调用:_Initialize
处理程序每次都会 运行,并且不需要 Clear
上一次调用的项目,因为您每次都将使用一个新实例时间。你这样做:
With New UserForm3 'UserForm_Initialize handler runs here
.Show 'UserForm_Activate handler runs here
'anything after .Show will only run after the form is closed
If Not .Cancelled Then
Sheet8.Range("I16").Value = .ComboBox1.Text
End If
End With 'UserForm_Terminate handler runs here
请注意工作表没有被表单写入 - 这不是它的工作!那么我们如何让 Cancelled
成员合法呢?
首先你 命名事物 并使 CommandButton1
成为 OkButton
并且 CommandButton2
成为 CancelButton
- 或者其他什么 - 只是不是Button1 和 Button2。
我喜欢你 隐藏 表单实例而不是用 Unload Me
对其进行核对,但是你 明确地 再次关闭 默认实例 ,这意味着上面的 New UserForm3
代码将不会隐藏显示的相同实例。当您打算使用 Me
.
换句话说:
UserForm3.Hide 'hides the default instance of UserForm3
Me.Hide 'hides whatever the current instance is
Hide 'same as Me.Hide
所以。添加一个Private isCancelled As Boolean
私有字段(模块级变量),然后暴露一个Public Property Get Cancelled() As Boolean
public属性getter那个returns它:
Option Explicit
Private isCancelled As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = isCancelled
End Property
接下来,让您的取消按钮设置标志:
Private Sub CancelButton_Click()
isCancelled = True
Me.Hide
End Sub
然后让 QueryClose
处理程序也设置它 - 并尽可能使用现有的命名常量:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
isCancelled = True
Me.Hide
End If
End Sub
然后在确定按钮的处理程序中实现您的 "happy-path" 逻辑:
Private Sub OkButton_Click()
Me.Hide
End Sub
我会在用户做出选择之前禁用“确定”按钮 - 这样他们就可以取消、删除或做出有效选择!
Public Property Get SelectedBoard() As String
SelectedBoard = IIf(Me.ComboBox1.ListIndex = -1, vbNullString, Me.ComboBox1.Text)
End Property
Private Sub ComboBox1_Change()
ValidateForm
End Sub
Private Sub ValidateForm()
Me.OkButton.Enabled = (SelectedBoard <> vbNullString)
End Sub
Private Sub UserForm_Activate()
ValidateForm
End Sub
现在调用者可以是这样的:
With New UserForm3
.Show
If Not .Cancelled Then
Sheet8.Range("I16").Value = .SelectedBoard
Else
MsgBox "No board was selected, please re-run macro and select appropriate board"
End If
End With
现在您的表单只不过是代码的 I/O 设备,它应该是这样的。而且您正在使用对象而不是全局状态。
长话短说:
- 删除
End
指令,无论它们在哪里。 - 不要在
UserForm3
中引用UserForm3
(请改用Me
)。 - 每次都使用一个新的
New
实例。 - 公开
Property Get
成员供调用代码访问,以抽象出调用者不需要关心的控件。 - 不允许表单在无效状态下被接受。