Programmatically Determining the Event Handler for an OnClick Event in VBA
我正在开发一个跟踪MS Access VBA中执行路径的应用程序。但是,我遇到了一个问题。看来您可以动态分配处理程序来控制OnClick和VBA中的其他此类事件,但是我看不到从这些控件读取事件的方法。例如:
1 2 3 4 5 | With Forms("Order Entry").Controls("OK") If .OnClick ="" Then .OnClick ="fnProcessOrder" End If End With |
这会将功能" fnProcessOrder"动态分配给"确定"按钮。但是,如果尝试获取该按钮的值,则会得到以下信息:
1 2 3 | With Forms("Order Entry").Controls("OK") Debug.Print"My Handler -->" + .OnClick EndWith |
结果:
1 | --> [Event Procedure] |
没有更多细节。这似乎是Microsoft在此处声明的行为:
https://msdn.microsoft.com/zh-cn/vba/access-vba/articles/commandbutton-onclick-property-access
但是我想知道是否还有比这更进一步的东西。
我本以为该信息将在MSysObjects和MSysQueries表中,但我在那里看不到它。我尝试使用Database Documenter提取测试数据库,并且从生成的文档中也获得了该值。
是否可以找到分配给控件的VBA功能?
这将返回事件的完整代码。如果仅在该事件中使用一个子,则它应该起作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Public Sub TestModulePrinter() Dim subName As String With Forms("Order Entry").Controls("OK") subName ="Private Sub" & .Name &"_OnClick()" End With Dim i As Long Dim IsPrinting As Boolean With Forms("Order Entry").Module For i = 1 To .CountOfLines If Not IsPrinting Then If Trim(.Lines(i, 1)) = subName Then IsPrinting = True End If Else If Trim(.Lines(i, 1)) ="End Sub" Then IsPrinting = False Else Debug.Print .Lines(i, 1) End If End If Next i End With End Sub |
实际上,该代码对我而言并不正确。如果要将VBA函数分配给事件过程,则必须使用类似于以下的语法:
作为额外的考虑,您可以拥有一个类模块(我们将其称为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Private WithEvents ctlInterest As Access.Textbox Public Sub Init(TargetControl As Access.Control) Set ctlInterest = TargetControl With ctlInterst If .OnClick ="" Then .OnClick ="[Event Procedure]" End If End With End Sub Private ctlInterest_OnClick() fnProcess() End Sub |
然后您可以按照这样的形式部署类。...
1 2 3 4 5 6 | Private objObserver As Observer Private Sub Form_Load() Set objObserver = New Observer objObserver.Init(Me.txtInterest) End Sub |
这将产生相同的结果,并且您最终得到多个事件处理程序。
有关更多信息,可能会有所帮助。
结合函数表达式是可能的事实以及可以随时动态分配函数的事实,它几乎需要代码路径分析来识别一般情况下所有事件处理程序的可能入口点。这意味着您需要为此使用Rubberduck的解析器。请注意,AIUI已计划但尚未实现静态代码路径分析。
此外,我想确定一下-如果您打算构建用于错误处理的调用堆栈跟踪,则可能需要查看第三方加载项。例如,商业产品vbWatchDog可以在VBA中提供该信息。