【问题标题】:Calling a userform and returning a value调用用户窗体并返回一个值
【发布时间】:2013-09-28 18:08:27
【问题描述】:

我有一个 Auto_Open 的 vba 代码。它会进行一些检查,然后提示一个询问用户名和密码的用户表单。我用userform_name.show 调用了这个用户表单。

我的问题是如何从用户表单代码中将Boolean 返回给我的Auto_Open 子。

我将验证凭据是否正确的代码链接到表单上的“登录”按钮。这是产生布尔值的代码。我需要将它返回给 Auto_Open。​​

Private Sub loginbutton()
    Dim bool As Boolean
    Dim lrup
    Dim r As Long
    Dim pass As String

    loginbox.Hide

    'are fields empty
    Do While True
        If unBox.Text = "" Or pwBox.Text = "" Then
            MsgBox ("You must enter a Username and Password")
        Else
            Exit Do
        End If
        loginbox.Show
        Exit Sub
    Loop

    'find pw reated to username (if existant)
    lrup = UserPass.Range("A1").Offset(UserPass.Rows.Count - 1, 0).End(xlUp).Row

    If unBox = "b0541476" And pwBox = "theone" Then
        bool = True
    Else
        MsgBox ("Invalid username or password. Please try again.")
        loginbox.Show
        Exit Sub
    End If

    For r = 2 To lrup
        If unBox = Cells(r, 1) Then
            pass = Cells(r, 2).Value
            Exit For
        End If
    Next

    If pass = "" Then
        MsgBox ("Invalid username or password. Please try again.")
        loginbox.Show
        Exit Sub
    Else
        bool = True
    End If
End Sub

【问题讨论】:

  • "这是产生布尔值的代码" - 它在哪里?
  • 对不起,我添加了它。代码结束后如何将“bool”传回 Auto_Open?

标签: excel excel-2010 userform vba


【解决方案1】:

您可以在不使用公共变量的情况下做到这一点。

显示/隐藏和加载/卸载之间似乎存在差异。

如果您在表单仍在加载时隐藏它,它不会被清除,因此您可以参考表单上控件的状态。

例如,我在表单上使用日期选择器(称为 DTPicker1),我在模块中的代码如下所示:

Dim NewDay As Date

Load FrmDayPicker
FrmDayPicker.Show

NewDay = FrmDayPicker.DTPicker1.Value

Unload FrmDayPicker

Debug.Print NewDay

在您的表单上,您可以只使用Me.Hide 而不是Unload Me,这应该可以工作

【讨论】:

    【解决方案2】:

    Dim bool As Boolean从用户表单代码区中移除,并在模块中声明如下所示

    这就是你在模块中的代码的样子

    Public bool As Boolean
    
    Sub Auto_Open()
        '
        '~~> Rest of the code
        '
        UserForm1.Show
    
        If bool = True Then
            '~~> Do Something
        Else
            '~~> Do Something        
        End If
    
        '
        '~~> Rest of the code
        '
    End Sub
    

    【讨论】:

    • 可以很容易地被某人更改以覆盖。
    • 这完全是一个不同的问题:) 这基本上回答了如何声明一个布尔变量并在用户表单中使用它,然后将其传递给Auto_Open
    • 是的,你是对的。您的方法将仅针对所提出的问题进行查找。
    • 虽然这可行,但如果我需要从单独的模块定义/调用该变量怎么办?
    • @FreeSoftwareServers 感谢您的反对并发表评论。我的回答是针对 OP 的需求。当我写这个答案时,我不知道 8 年后有人会有不同的查询......
    【解决方案3】:

    用函数代替子怎么样?

    Function loginbutton()
      ' your code
    
      loginbutton = bool
    End Function
    

    现在您可以在调用代码中测试真/假

    if loginbutton() then
      'true responce
    else
      'false responce
    end if
    

    【讨论】:

    • 用户表单上没有登录按钮。用户表单必须先运行,然后登录按钮()一旦他们在表单上按下“登录”。
    • 如果我理解正确,只要您在正确的位置调用该函数,它就会以相同的方式工作。无论哪种方式,登录代码正在运行和结束,我只是检查它在运行完成时是否根据内部运行的内容返回 true 或 false。 @Siddharth 解决方案也有效,但存在更大的安全风险。
    【解决方案4】:

    更新:

    我很快就忽略了公共变量。虽然 Pub Vars 和直接访问项目这两种方法都可以工作,但有时如果说它是一个列表,直接访问项目并不理想。

    我现在有专门用于调用用户窗体的模块,它只声明公共变量并调用用户窗体。然后我可以从 UserForms 或 Modules 调用这些模块,并在用户窗体关闭后访问公共变量。

    例如:这是我现在使用的一个模块,很基础,其他的需求都可以直接调用这个模块/sub。

    Public ColSelectorDic As Object
    Public Sub Col_Picker_Sub()
     Col_Picker_UserForm.Show
    End Sub
    

    使用在调用用户窗体的模块中声明的公共变量是最简单的 IMO。但是,如果您想从单独的模块调用此用户表单,则需要注意,您将收到有关重复声明/不明确名称的错误。

    所以,如果您知道它只会被称为一个模块,那么一直是 Pub Vars。就我而言,我使用的是“列选择器”用户表单,它非常简单,我希望能够在未来不可预见的项目中再次使用它,因此我尝试解决上述警告。

    公共变量见此答案,无需重复信息 --> https://stackoverflow.com/a/18966341/5079799

    这个答案与直接访问表单变量有关--> https://stackoverflow.com/a/47919465/5079799 但我觉得它可以使用一些扩展。

    另外,这里有一篇很好的文章,深入探讨了直接访问用户表单变量 --> https://gregmaxey.com/word_tip_pages/userform_pass_data.html

    所以我的用户窗体看起来像这样,并命名为ColPicker

    Private Sub UserForm_Initialize()
    Dim i As Long
     lCol = Get_lCol(ActiveSheet)
      For i = 1 To lCol
       ColumnLetter = Col_Letter(i)
       Me.ComboBox1.AddItem ColumnLetter
      Next
    End Sub
    Private Sub CommandButton1_Click()
     Me.Hide
    End Sub
    
    Sub PassVarFromUserForm()
     ColPicker.Show
     Dim ColLetter As String
     ColLetter = ColPicker.ComboBox1.Value
     Unload ColPicker
     Debug.Print ColLetter
    End Sub
    

    注意用户窗体中的“运行”/命令按钮是如何隐藏表单的,然后我将值存储在一个变量中,然后通过使用它的名称从模块中卸载表单。 (您只能在用户表单中使用unload me)。

    然后该变量在模块内可用,并且可以在开始时声明为公共或在模块内,没关系,因为它可以在每个模块中以不同方式声明,用户表单不知道/引用什么变量信息将存储在的名称。

    【讨论】:

      猜你喜欢
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-09
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多