Vba 如何将布尔值从UserForm传递到Sub?

Vba 如何将布尔值从UserForm传递到Sub?,vba,excel,Vba,Excel,如果有人单击右上角的红色x,我试图关闭一个用户窗体。这是到目前为止我的代码 Public Sub Worksheet_BeforeDoubleClick(ByVal target As Range, Cancel As Boolean) If target.Column = 10 Then UserForm2.Show etc... 现在,表单打开,我运行此代码 Public Sub UserForm_QueryClose(Cancel As Integer, CloseMode As In

如果有人单击右上角的红色x,我试图关闭一个用户窗体。这是到目前为止我的代码

Public Sub Worksheet_BeforeDoubleClick(ByVal target As Range, Cancel As Boolean)
If target.Column = 10 Then
UserForm2.Show

etc...
现在,表单打开,我运行此代码

Public Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = vbFormControlMenu Then
        If Not ExitAsk = vbYes Then Cancel = True
    End If
End Sub

Public Function ExitAsk() As VbMsgBoxResult
    Dim Smsg As String
    Smsg = "Are you really want to exit? Click Yes to terminate or No to Continue."
    ExitAsk = MsgBox(Smsg, vbYesNo + vbDefaultButton2 + vbQuestion, "Exit!")
End Function
然后,焦点又回到了Sub,代码继续运行,这给我带来了一些问题。我想单击红色的x并关闭UserForm并退出Sub。Sub和UserForm似乎不通信,即使它们都声明为公共。我一定错过了一些简单的东西,但我不确定是什么。有什么想法吗


谢谢

UserForm
中,您可以定义自己的
public
Get属性,例如
CloseModeInfo
,该属性将返回可在
UserForm\u QueryClose
中设置的私有成员值。然后可以稍后测试此公共属性的值。根据此属性中的值,调用代码将决定要执行的操作。嗯

用户窗体

工作表代码

看起来Sub和UserForm不通信,即使它们都被声明为公共的

可访问性与过程是否与表单通信无关。表单是一个对象,与
范围
集合
没有太大区别,只是它有一个设计器和一个默认实例:如果您不告诉它如何做,它将不会与您的过程“通信”

首先,停止使用默认实例,并像对待任何其他对象一样对待表单:
New
it up

With New UserForm2 'object instance starts existing here...
    .Show 'vbModal is implicit
End With '...and dies here
现在,如果希望调用代码知道表单是如何关闭的,那么需要公开调用代码可以访问的内容

最好是用一处房产。您也可以公开一个公共字段,但是调用代码可能会篡改它,而您不希望这样做-封装就是这样做的:

注意
Cancel=True
Me.Hide
:如果不取消关闭,对象将立即被销毁,并且您将失去其状态。因此,您希望隐藏表单,而不是卸载/销毁表单

只有表单的代码可以访问
isCancelled
,但调用代码可以读取
Cancelled
属性(但不能写入)


所以。。。不确定您想要实现什么,但您需要沿着这些思路做一些事情。

VBA代码一次运行一个命令,从上到下,逐行运行。在一些罕见的情况下,您会发出异步命令。但大多数情况下,VBA是线性的。当您告诉VBA显示表单时,
Sub
将被搁置,等待表单完成。表单不再显示后,子
的其余部分将运行。那不是虫子。这是一个特点。如果你不想在表单关闭后发生任何事情,那么
Form2.Show
应该是该子命令中的最后一个命令。如果你想在表单关闭时发生什么事情,那么你可以在表单关闭时调用一个新的子命令。嗯,这很有意义。然而,它仍然不起作用。我添加了以下内容:如果ExitAsk 6,那么如果收到的消息显示“Sub或Function Not Defined”,则调用CodeContinue End。函数和子函数都是“公共”的。子函数必须位于模块上。如果该sub位于表单或工作表上,则不能这样称呼它(即使它是公共的)。然而,这是另一个问题。一个范围问题,与原始帖子无关:VBA程序的线性连续性。@拉尔夫这基本上是正确的,只是OP的表单不是模态的,所以
UserForm2.Show
显示表单,然后在双击
之前在
工作表中继续执行,在窗体关闭之前和它的
初始化
[以及可能的
激活
]处理程序执行之后。
UserForm\u QueryClose
处理程序不必成为
公共
。当您从提供的下拉列表中添加事件处理程序时,VBE会使所有事件处理程序成为私有的-保留它们为私有的。任何地方的任何代码都没有理由显式调用任何偶数处理程序,也没有理由向调用者公开它们。我很高兴它有帮助!:)。
Private Sub Worksheet_BeforeDoubleClick(ByVal target As Range, Cancel As Boolean)
    If target.Column = 10 Then
        Dim frm As UserForm2
        Set frm = New UserForm2
        UserForm2.Show

        If frm.CloseModeInfo = vbFormControlMenu Then
            Unload frm
            '  I want to click the red x and close the UserForm and exit the Sub:   
            Exit Sub
        End If
    End If
End Sub 
With New UserForm2 'object instance starts existing here...
    .Show 'vbModal is implicit
End With '...and dies here
Private isCancelled As Boolean

Public Property Get Cancelled() As Boolean
    Cancelled = isCancelled
End Property

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = vbFormControlMenu Then
        isCancelled = True
    End If
    Cancel = True
    Me.Hide
End Sub
With New UserForm2 'object instance starts existing here...
    .Show vbModal 'execution in this procedure will resume after form is closed
    If .Cancelled Then
        'form was X'd out
    End If
End With '...and dies here