关于ms访问权限:以编程方式确定VBA中OnClick事件的事件处理程序

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函数分配给事件过程,则必须使用类似于以下的语法:.OnClick ="=fnProcess()"请注意文字=()-这些是使Access识别您要调用的必需项。功能。

作为额外的考虑,您可以拥有一个类模块(我们将其称为Observer),其代码类似于以下内容:

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中提供该信息。