Vba 将参数传递给事件处理程序过程
我正在使用userform上的一个按钮生成脚本字典,使用它填充列表框,然后需要使用表单上的第二个按钮使用同一个字典。我已声明我的词典使用早期绑定,如下所示:Vba 将参数传递给事件处理程序过程,vba,excel,Vba,Excel,我正在使用userform上的一个按钮生成脚本字典,使用它填充列表框,然后需要使用表单上的第二个按钮使用同一个字典。我已声明我的词典使用早期绑定,如下所示: Dim ISINDict As New Scripting.Dictionary 还是迟订 Dim ISINDict as Object ... Set ISINDict = CreateObject("Scripting.Dictionary") 当我尝试将字典传递到另一个按钮时,如下所示: Private Sub OKButton_
Dim ISINDict As New Scripting.Dictionary
还是迟订
Dim ISINDict as Object
...
Set ISINDict = CreateObject("Scripting.Dictionary")
当我尝试将字典传递到另一个按钮时,如下所示:
Private Sub OKButton_Click(ISINDict as Scripting.Dictionary) 'if early binding
Private Sub OKButton_Click(ISINDict as Object) 'if late binding
我得到以下错误:“过程声明与该行中事件或同名过程的描述不匹配”
知道我做错了什么吗?事件处理程序有一个特定的签名,由特定接口拥有:您不能更改签名,否则成员将与接口定义的签名不匹配,并且无法编译—正如您所观察到的 为什么呢 假设您有一个
CommandButton
类,该类处理本机Win32消息并对其进行分派-可能如下所示:
Public Event Click()
Private Sub HandleNativeWin32Click()
RaiseEvent Click
End Sub
现在,在代码的其他地方,您希望使用该类并处理其单击事件:
Private WithEvents MyButton As CommandButton
Private Sub MyButton_Click()
'button was clicked
End Sub
请注意,处理程序方法的名称为[EventSource].[EventName]
——这在VBA中是硬连接的,您无法更改它。如果您试图与名称中带有下划线的公共成员建立接口,您将遇到问题。这就是为什么无论您在标准库中的哪个位置查看,所有内容都是PascalCase
(没有下划线)
因此编译器知道您正在处理MyButton.Click
事件,因为有一个名为MyButton\u Click
的方法。然后查看参数-如果存在不匹配,则说明有问题:该参数不在接口上,那么事件提供程序将如何提供该参数?。因此,它会抛出一个编译时错误,告诉您需要使签名匹配,或者重命名过程,使其看起来不像是在处理MyButton。再单击
当你把一个控件放到一个窗体上时,你基本上得到了一个Public with events Button1作为CommandButton
模块级变量,这是免费的:这就是你可以在代码中使用Button1
来引用那个特定按钮的方式,以及它的Click
处理程序是如何命名的Button1\u Click
。请注意,如果重命名按钮而不是处理程序,则过程将不再处理按钮的单击事件。您可以在表单设计器上使用的重构/重命名工具在不破坏代码的情况下正确重命名控件
VBA中的变量可以位于三个范围之一:全局、模块或过程级别
当您这样做时:
Sub DoSomething()
Dim foo
End Sub
您正在声明一个局部范围变量
每个模块的顶部都有一个声明部分,您可以在其中声明模块范围变量(以及其他内容)
这里的foo
是一个模块范围变量:该模块中的每个过程都可以访问它-读和写
因此,如果您有要在过程之间传递的数据,并且无法更改它们的签名,那么下一个最佳选择就是声明一个模块范围变量
[故意忽略全局范围]
关于<代码>作为新的< /代码> -考虑这一点:
Public Sub Test()
Dim foo As Collection
Set foo = New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
Public Sub Test()
Dim foo As New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
此代码出现运行时错误91“未设置对象变量”,因为当执行foo.Add
时,foo
的引用是Nothing
,这意味着没有有效的对象指针。现在考虑这个问题:
Public Sub Test()
Dim foo As Collection
Set foo = New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
Public Sub Test()
Dim foo As New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
此代码输出1,因为作为新的以一种奇怪、不直观和混乱的方式保持对象的活动状态。尽可能避免将作为新的。在模块级别声明字典,并将其填入button-1-click事件处理程序。然后,它可以简单地在button-2-click事件处理程序中重复使用。因此,不需要将字典传递给事件处理程序,这也是不可能的。嗯
表单模块
不能将参数添加到单击事件中。您需要找到其他方法来执行您正在尝试执行的操作,例如将字典声明为表单级变量,然后您可以从单击事件中访问它。^他说的。还有,究竟为什么要延迟绑定脚本运行时??您的任何用户是否正在运行IE5.5或Windows XP?FWIW您不应该将局部变量声明为新的
Dim foo作为新集合
/Set foo=Nothing
/Debug.Print foo.Count
->您希望得到什么?运行时错误91?如果是这样的话,你已经被新的的非直觉行为咬了一口。谢谢大家!我会考虑这一点@braX如何将字典声明为表单级变量?这似乎是最好的选择!@Mat的杯子我这样做只是为了测试它,因为我在早期绑定时遇到了错误,我想确保它不相关-我对VBA非常陌生,所以如果不可能的话,请原谅我的无知!你的第二句话把我弄糊涂了。你能详细说明一下吗?在所有子程序之外对其进行尺寸标注。