Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 在VBA中将变量从窗体传递到模块_Excel_Vba_Module_Userform - Fatal编程技术网

Excel 在VBA中将变量从窗体传递到模块

Excel 在VBA中将变量从窗体传递到模块,excel,vba,module,userform,Excel,Vba,Module,Userform,我在表单上有以下按钮: Private Sub CommandButton1_Click() Dim pass As String pass = UserForm1.TextBox1 Unload UserForm1 End Sub 然后我有一个名为Module1的模块: Public Sub Login() ... UserForm1.Show driver.findElementByName("PASSWORD").SendKeys pass ... End Sub

我在表单上有以下按钮:

Private Sub CommandButton1_Click()
 Dim pass As String
 pass = UserForm1.TextBox1
 Unload UserForm1
End Sub
然后我有一个名为Module1的模块:

 Public Sub Login()

 ...

 UserForm1.Show
 driver.findElementByName("PASSWORD").SendKeys pass

 ...

End Sub
其想法是,用户在输入框中输入的任何密码都将分配给变量
pass
。然而,我所遇到的问题是将
pass
从UserForm1传递到Module1的登录子模块


在卸载表单之前,我会考虑在表单中添加类似于
Module1.Login(pass)
的内容,但这似乎不会传递任何信息。任何帮助都将不胜感激。谢谢。

不要在userform中声明变量。在模块中将其声明为
Public

Public pass As String
在用户表单中

Private Sub CommandButton1_Click()
    pass = UserForm1.TextBox1
    Unload UserForm1
End Sub
模块中的

Public pass As String

Public Sub Login()
    '
    '~~> Rest of the code
    '
    UserForm1.Show
    driver.findElementByName("PASSWORD").SendKeys pass
    '
    '~~> Rest of the code
    '
End Sub
您可能还想在调用
驱动程序之前添加一个附加检查。查找…

If Len(Trim(pass)) <> 0 Then
如果Len(Trim(pass))为0,则

这将确保不传递空白字符串。

Siddharth的答案很好,但依赖于全局范围的变量。有一种更好、更友好的面向对象方法

UserForm与其他任何模块一样是一个类模块-唯一的区别是它有一个隐藏的
VB_PredeclaredId
属性设置为
True
,这使得VB创建一个以类命名的全局范围对象变量-这就是如何编写
UserForm1.Show
,而不创建类的新实例

远离这一点,将表单视为一个对象-公开
属性获取成员并抽象掉表单的控件-调用代码无论如何都不关心控件:

现在,调用代码可以这样做(假设UserForm名为
LoginPrompt
):

其中,
DoSomething
是一些需要两个字符串参数的过程:

Private Sub DoSomething(ByVal uid As String, ByVal pwd As String)
    'work with the parameter values, regardless of where they came from
End Sub

+这是一个很好的方法。或者,您可以隐藏Userform1而不是卸载它,并从模块中访问Userform1.TextBox1,然后卸载Userform1,但方法的决定取决于整个实现ah,我从未想过将变量声明为Public。这是一个非常好的提示,我将不得不开始做更多,谢谢@user2140173完成表单后,最好卸载表单。更好的内存和安全性。@TylerH只是因为您正在使用窗体的默认实例。像对待对象一样对待表单,而不是像对待全局状态用户界面一样对待表单,“内存”和“安全性”参数都不再有效。@RandomDown投票者反馈总是值得赞赏的;我总是乐于接受改进答案的新方法。现在我对避免全局状态和通过简单的抽象增强代码的表达性和健壮性有点困惑。干杯。我喜欢这种将表单与数据和方法分离的方法。我将如何以用户表单保持可见的方式实现这一点。使用上面的示例,假设ID或密码不正确,表单是否可以保持打开状态并给出一些警告?@RobertTodar在这种情况下,您将在视图/表单中声明一个事件,并在presenter中处理它(该视图/表单必须是一个类模块,具有视图/表单的
WithEvents
声明)。有点像神奇的解决方案。不过“QueryClose”上有一个错误。我正在发布下面修复程序的链接。由于我花了30分钟试图解决它,我在这里添加供将来参考,因为这是谷歌搜索将值从表单传递到模块时的第一个结果@Hend感谢大家的提醒!注意,这段代码确实调用了
Me.Hide
,我从来没有遇到过任何问题(虽然这有点简化,但实际上我将状态标志toggle+form隐藏在一个私有的
OnCancel
方法中,我从
QueryClose
和一些
CancelButton\u Click
处理程序调用该方法;链接问题中的代码似乎缺少表单的隐藏,也缺少
Cancel=True)是导致错误的原因,因为不取消它会使表单对象自毁。我正在修复它,谢谢!
With New LoginPrompt
    .Show vbModal
    If .IsCancelled Then Exit Sub
    DoSomething .UserId, .Password
End With
Private Sub DoSomething(ByVal uid As String, ByVal pwd As String)
    'work with the parameter values, regardless of where they came from
End Sub