Vba 让MS Office用户窗体检测调用它的子例程

Vba 让MS Office用户窗体检测调用它的子例程,vba,excel,userform,Vba,Excel,Userform,在我的一个VBA项目中,我正在/将要使用一系列相当复杂的用户表单,其中许多表单在视觉上是相同的,但在按钮上附加了不同的子例程。因此,为了从同一布局中获得不同的功能,我不太热衷于多次复制它们。是否可以让userform检测调用它的子例程并在流控制中使用它?我希望能够做到以下几点: Private Sub UserForm_Initialize() If [the sub that called the userform is called "foo"] then Call

在我的一个VBA项目中,我正在/将要使用一系列相当复杂的用户表单,其中许多表单在视觉上是相同的,但在按钮上附加了不同的子例程。因此,为了从同一布局中获得不同的功能,我不太热衷于多次复制它们。是否可以让userform检测调用它的子例程并在流控制中使用它?我希望能够做到以下几点:

Private Sub UserForm_Initialize()
    If [the sub that called the userform is called "foo"] then
        Call fooSub
    else
        Call barSub
    End If
End Sub
我的备份计划是让调用子例程设置一个全局变量标志,并让userform进行检查,但这似乎是一个相当粗糙和笨拙的解决方案

谢谢大家,

Louis

您可以使用表单的tag属性。加载表单,设置属性,然后显示表单:

Sub PassCallerToForm()
    Load UserForm1
    UserForm1.Tag = "foo"
    UserForm1.Show
End Sub
Private Sub UserForm_Activate()
    If Me.Tag = "foo" Then
        Call fooSub
    Else
        Call barSub
    End If
End Sub
设置属性后,您可以确定在表单中执行的操作:

Sub PassCallerToForm()
    Load UserForm1
    UserForm1.Tag = "foo"
    UserForm1.Show
End Sub
Private Sub UserForm_Activate()
    If Me.Tag = "foo" Then
        Call fooSub
    Else
        Call barSub
    End If
End Sub

您还可以使用公共变量:

' in userform

Public Caller As String

Private Sub UserForm_Click()
    MsgBox Caller
    Caller = Now()
    Me.Hide
End Sub

' in caller
Sub callUF()
    Dim frm As New UserForm1
    frm.Caller = "Test Caller"
    frm.Show
    MsgBox frm.Caller ' valid after Me.Hide
    Set frm = Nothing
End Sub

就个人而言,我不会让一个用户表单执行两个完全不同的活动。我认为代码很快就会变得难以阅读。复制用户表单的布局非常简单

复制用户表单:打开空白工作簿。在项目资源管理器中,将userform拖到新工作簿中。在新工作簿中重命名userform。现在将其拖回原始工作簿。更改用户表单副本中的代码

如果您绝对不需要单独的userforms,我建议设置userform的属性。Userforms只是类,只是它们有一个用户界面组件。在userform模块中

Private mbIsFoo As Boolean

Public Property Let IsFoo(ByVal bIsFoo As Boolean): mbIsFoo = bIsFoo: End Property
Public Property Get IsFoo() As Boolean: IsFoo = mbIsFoo: End Property

Public Sub Initialize()

    If Me.IsFoo Then
        FooSub
    Else
        BarSub
    End If

End Sub
我总是编写自己的初始化过程。在标准模块中:

Sub OpenForm()

    Dim ufFooBar As UFooBar

    Set ufFooBar = New UFooBar

    ufFooBar.IsFoo = True
    ufFooBar.Initialize

    ufFooBar.Show

End Sub

您可以在用户窗体上放置一个隐藏的
标签
表单控件,并让调用例程更改该标签的
.Caption
,然后使用
If/then
Select Case
语句来计算
.Caption
,并发送到相应的子例程。与全局变量标志相比,这有什么优势吗?可能没有,但在我看来,这似乎是一个比全局变量更整洁的解决方案。我喜欢HeadOfCatering的响应,但它给了我一个编译错误。不过,如果它对您有效,我会说使用它。有趣的解决方案,但当我尝试使用它时,我得到一个编译错误:
过程声明与同名事件或过程的描述不匹配
嘿,我错了。无法将参数传递给窗体的初始化事件。我已经修改了答案并进行了测试。这个方法行得通,呵呵!在我测试你的答案之前,我可能不该把它标为正确的。这对我来说是个教训。我最喜欢你的新解决方案,所以没关系。再次感谢。嗯,看起来应该有用。索诺法!我很高兴修订后的解决方案也能奏效请阅读我的帖子,我已经考虑了全局变量作为解决方案。示例中的公共调用方不是全局变量-它位于表单上。我同意,使用一个useform和两个函数并不理想,但这些UserForm有大量的标签、文本框等,将它们从默认值重命名为有用的东西将非常乏味。谢谢你的想法,我非常喜欢你的解决方案。拥有自己的初始化过程非常酷。