我正在开发跟踪MS Access VBA中执行路径的应用程序。但是,我遇到了一个问题。您似乎可以动态分配处理程序来控制OnClick和VBA中的其他此类事件,但我没有看到从这些控件中读取事件的方法。例如:
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函数?
答案 0 :(得分:1)
实际上,代码对我来说并不合适。如果要将VBA函数分配给事件过程,则必须使用与此类似的语法:.OnClick = "=fnProcess()"
注意文字=
和()
- 这些是进行访问的必需条件认识到你想要调用一个函数。
作为额外的考虑,你可以有一个类模块(我们称之为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中提供该信息。
答案 1 :(得分:1)
这将返回事件的完整代码。如果您只在该事件中使用一个子,它应该可以工作。
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