【问题标题】:Treat Userform as a Function将 Userform 视为函数
【发布时间】:2017-07-04 10:14:33
【问题描述】:

我创建了一个 VBA 用户窗体,它本质上是一个美化的输入框

就像输入框可以这样使用

Dim returnVal As String
returnVal = InputBox("Write some string")

我希望我的用户表单像这样运行

Dim returnVal As customClass
Set returnVal = MyUserForm([some arguments])

即。 MyUserForm() 代码将一些参数传递给用户窗体,当用户窗体关闭时,它会返回一些参数(以自定义类的形式而不是纯字符串的形式)

构建用户表单以实现此功能的最佳方式是什么?


目前,我只是公开声明一些变量和自定义类。我正在捕捉命令按钮点击和Query_close() 事件来隐藏表单,然后我读取了 outputVal 并完全关闭了表单。我不喜欢这样,因为我希望我的表单完全独立,而且我认为事件的捕获很混乱。

在简化代码中(读取/返回字符串):

Function myUf(inVal As String) As String
Dim frm As New frmTest
frm.inputval = inVal
frm.Init 'sets caption. We cannot rely on userform initialize as this runs before inputval is set
         'We could pass a variable here to save writing to the public variable
frm.Show
myUf = frm.outputVal
Set frm = Nothing
End Function

在我名为frmTest 的用户表单中,带有一个名为tb1 的文本框

Public inputval As String
Public outputVal As String

Public Sub Init()
Me.Caption = inputval 'setting caption, but could pass this anywhere
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode <> 1 Then Cancel = 1
outputVal = tb1 'reading value from textbox, but could return anything here
Me.Hide
End Sub

【问题讨论】:

    标签: vba excel userform


    【解决方案1】:

    您需要找到一种从 ClassObject 启动 UserForm 的方法。然后,您可以使用simple factory pattern 完全按照您想要的方式创建用户窗体。


    总的来说,我在 StackOverflow 的某处复制了一些 Mat's Mug 的代码,并写了一篇关于用户表单的文章。如果您看一下这里 (http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/),您会找到一种使用 Public Sub ShowMainForm() 初始化表单的方法。可以将参数添加到 ShowMainForm,然后将其传递给类的初始化程序。

    一般来说,从文章中获取代码,确保它可以工作,然后将 ShowMainForm 初始化器更改为以下内容:

    Public Sub ShowMainForm(strText As String, strText2 As String)
    
        If (objPresenter Is Nothing) Then
            Set objPresenter = New clsSummaryPresenter
        End If
    
        objPresenter.Show
        Call objPresenter.ChangeLabelAndCaption(strText, strText2)
    
    End Sub
    

    那么,如果你在即时窗口中这样调用:

    call ShowMainForm("Just","testing")
    

    你会得到这个:

    这正是您所需要的。 :)

    【讨论】:

    • 感谢您的文章+。看看我最近发布的问题如何“正确销毁 modeless 用户窗体实例”可能会很有趣,因为我也提到了 Mat's Mug 的 MVP 概念(参见 stackoverflow.com/questions/47357708/…)。
    【解决方案2】:

    基本思路是:

    在你将参数组合成一个字符串时创建一个函数,例如:

    strOpenArg = "param1:=value1;param2:=value2;"
    

    比使用 OpenArgs 打开表单

    DoCmd.OpenForm "UserForm", acNormal, , , , acDialog, strOpenArgs
    

    获取您的价值并关闭表单

    Value= Form_UserForm.Value
    
    DoCmd.Close acForm, "UserForm", acSaveNo
    

    在UserForm 中设置Form_open。在这里你可以得到你的参数。你可以通过字符串拆分来划分它。 还设置一个确定按钮,您可以在其中使表单不可见并设置返回值

    Private Sub Form_Open(Cancel As Integer)
         Dim strParameter as String
         strParameter = Me.OpenArgs 'Here are your parmeters
    End Sub
    
    Private Sub ok_Click()
        m_Value = "Your ReturnValue"
        Me.Visible = False
    End Sub
    
    Private m_Value As String
    Public Property Get Value() As String
        Value = m_msgBoxResult
    End Property
    

    【讨论】:

    • 这是 MSAccess 表单的代码,不是 VBA 用户表单的代码。
    【解决方案3】:

    不幸的是,没有办法像您想要的那样单行代码。如果您的所有用户表单代码都是独立的,那么它传递值的唯一方法是更改​​公共变量的值。 Mat's Mug's answer here 是我在尝试模拟诸如“InputBox”之类的函数时通常使用的布局,但如果不编写单独的函数,您仍然无法将其放在一行中。使用用户表单属性允许您在表单本身中包含更多代码。

    【讨论】:

      猜你喜欢
      • 2019-12-25
      • 1970-01-01
      • 2015-07-11
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多