用户表单 - 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 Booleanpublic属性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 成员供调用代码访问,以抽象出调用者不需要关心的控件。
  • 不允许表单在无效状态下被接受。