调用用户窗体并返回一个值

11

我有一个在Auto_Open中运行的VBA代码。它进行了一些检查,然后提示一个用户窗体要求输入用户名和密码。我使用 userform_name.show调用了这个用户窗体。

我的问题是如何从用户窗体代码向Auto_Open子程序返回一个Boolean值。

我将验证凭据是否正确的代码链接到了表单上的“登录”按钮。这是生成布尔值的代码。我需要将它返回给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

1
这是产生布尔值的代码 - 它在哪里? - Automate This
抱歉,我添加了它。当代码结束时,如何将“bool”传回Auto_Open? - user2385809
4个回答

7

您可以不使用公共变量来完成此操作。

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

如果在加载状态下隐藏表单,则不会清除表单,因此可以引用表单上的控件状态。

例如,我在一个表单上使用了日期选择器(称为DTPicker1),我的模块代码大致如下:

Dim NewDay As Date

Load FrmDayPicker
FrmDayPicker.Show

NewDay = FrmDayPicker.DTPicker1.Value

Unload FrmDayPicker

Debug.Print NewDay

在您的表单上,您可以使用Me.Hide代替Unload Me,这样就可以正常工作了。

4

请把用户窗体代码区域中的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

可以很容易地被某人更改以覆盖。 - Automate This
2
那是完全不同的问题 :) 这基本上回答了如何声明布尔变量并在用户窗体中使用它,然后将其传递给 Auto_Open - Siddharth Rout
是的,你说得对。就所提出的问题而言,你的方法可以完全正常地工作。 - Automate This
VBA 在多年间并没有太多变化,最佳实践应该始终是答案。必须有一种方法不会有这个“警告”。 - FreeSoftwareServers
如果您添加有关警告或解决方案的注释,我会切换回点赞? - FreeSoftwareServers
显示剩余3条评论

2
使用函数而不是子程序如何?
Function loginbutton()
  ' your code

  loginbutton = bool
End Function

现在您可以在调用代码中测试真/假。
if loginbutton() then
  'true responce
else
  'false responce
end if

不,登录按钮在用户窗体上。用户窗体必须先运行,然后在他们按下窗体上的“登录”按钮后再运行loginbutton()函数。 - user2385809
如果我理解正确,只要在正确的位置调用函数,它将以相同的方式工作。无论哪种方式都会运行登录代码并结束,我只是检查当它完成运行后,根据内部运行的内容返回true或false。 @Siddharth的解决方案也可以,但存在较大的安全风险。 - Automate This

0

更新:

我过于草率地否定了公共变量。虽然两种方法都可以工作,即使用Pub Vars和直接访问项目,但有时如果要访问列表等内容,则直接访问项目并不理想。

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

例如:这是我现在使用的一个非常基本的模块,我的所有其他需求都可以调用此模块/子程序。

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

在我看来,最简单的方法是在调用用户窗体的模块中使用公共变量声明。但是,这样做有一个警告:如果您想从不同的模块调用此用户窗体,则会出现重复声明/名称不明确的错误。

因此,如果您知道它只会被一个模块调用,那么公共变量就是最好的选择。在我的情况下,我正在使用一个“列选择器”用户窗体,它非常简单,我希望能够在未来的项目中再次利用它,因此我尝试解决上述问题。

请参阅此答案以了解公共变量,无需重复信息--> https://dev59.com/q2Mk5IYBdhLWcg3wyw0U#18966341

以及与直接访问表单变量相关的此答案--> https://dev59.com/q2Mk5IYBdhLWcg3wyw0U#47919465,但我觉得它需要一些扩展。

另外,这里有一篇深入讲解如何直接访问用户表单变量的好文章——> 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)。
然后,在模块内部可以使用该变量,并且可以在开头声明为公共变量或在模块内部声明,因为它可以在每个模块中以不同的方式声明,用户窗体不知道/参考将存储信息的变量名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接