我正在开发一个在MS Access VBA中跟踪执行路径的应用程序。然而,我遇到了一个问题。似乎您可以动态分配处理程序来控制OnClick和其他类似的事件,但我看不到从这些控件中读取事件的方法。例如:
With Forms("Order Entry").Controls("OK")
If .OnClick = "" Then
.OnClick = "fnProcessOrder"
End If
End With
这会动态地将函数"fnProcessOrder“分配给"OK”按钮。但是,如果您尝试获取该按钮的值,则会得到以下结果:
With Forms("Order Entry").Controls("OK")
Debug.Print "My Handler -->" + .OnClick
EndWith
结果如下:
--> [Event Procedure]
没有更多细节。这似乎是微软在这里陈述的行为:https://msdn.microsoft.com/en-us/vba/access-vba/articles/commandbutton-onclick-property-access
但我想知道有没有比这更进一步的方法。
我本以为这些信息会出现在MSysObjects和MSysQueries表中,但我没有看到。我已经尝试使用database Documenter提取我的测试数据库,我也从生成的文档中获得该值。
有没有办法找到分配给控件的VBA函数?
发布于 2017-09-20 19:03:41
实际上,代码在我看来并不正确。如果要将VBA函数赋给事件过程,则必须使用类似以下语法:.OnClick = "=fnProcess()"
请注意文字=
和()
--它们是使Access识别您要调用的函数所必需的。
作为额外的考虑,您可以有一个类模块(让我们称它为Observer
),它的代码类似于:
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
然后您可以像这样以这样的形式部署类。
Private objObserver As Observer
Private Sub Form_Load()
Set objObserver = New Observer
objObserver.Init(Me.txtInterest)
End Sub
这将产生相同的结果,并最终得到多个事件处理程序。
有关更多信息,this可能会有所帮助。
由于函数表达式是可能的,并且可以在任何时候动态赋值,因此通常需要代码路径分析来确定所有事件处理程序的可能入口点。这意味着你需要Rubberduck的解析器,注意静态代码路径分析已经计划好了,但还没有实现,AIUI。
此外,我希望确保--如果您的意图是构建用于错误处理的调用堆栈跟踪,则可能需要查看第三方插件。例如,商业产品vbWatchDog可以在VBA语言中提供这些信息。
发布于 2017-09-20 19:48:13
这将返回事件的完整代码。如果你只在事件中使用一个sub,它应该可以工作。
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
https://stackoverflow.com/questions/46328853
复制