使用类模块处理访问表单控件输入的通用方法:
此代码旨在处理在弹出窗口中编写的应用程序。主窗体包含一个选项卡控件,其中每个选项卡都包含其自己的子窗体,指向链接的子表或独立表。使用或不使用选项卡控件不应对类模块处理产生任何影响。
可以修剪代码以满足您的应用程序的需要。例如,可以从类模块中删除不使用的控件。同样,控件集合子例程可以通过使用 TypeName(Ctl) 语句来筛选添加到集合中的控件来进行选择。
在名为 clsMultipleControls 的类模块中放入以下代码。
Option Compare Database
Option Explicit
Private m_PassedControl As Control
Private WithEvents atch As Attachment
Private WithEvents bfrm As BoundObjectFrame
Private WithEvents chk As CheckBox
Private WithEvents cbo As ComboBox
Private WithEvents btn As CommandButton
Private WithEvents cctl As CustomControl
Private WithEvents img As Image
Private WithEvents lbl As Label
Private WithEvents lin As Line
Private WithEvents Lst As ListBox
Private WithEvents frm As ObjectFrame
Private WithEvents optb As OptionButton
Private WithEvents optg As OptionGroup
Private WithEvents pg As Page
Private WithEvents pgb As PageBreak
Private WithEvents Rec As Rectangle
Private WithEvents sfm As SubForm
Private WithEvents tctl As TabControl
Private WithEvents txt As TextBox
Private WithEvents tgl As ToggleButton
Property Set ctl(PassedControl As Control)
Set m_PassedControl = PassedControl
Select Case TypeName(PassedControl)
Case "Attachment"
Set atch = PassedControl
Case "BoundObjectFrame"
Set bfrm = PassedControl
Case "CheckBox"
Set chk = PassedControl
Case "ComboBox"
Set cbo = PassedControl
Case "CommandButton"
Set btn = PassedControl
Case "CustomControl"
Set cctl = PassedControl
Case "Image"
Set img = PassedControl
Case "Label"
Set lbl = PassedControl
Case "Line"
Set lin = PassedControl
Case "ListBox"
Set Lst = PassedControl
Case "ObjectFrame"
Set frm = PassedControl
Case "OptionButton"
Set optb = PassedControl
Case "OptionGroup"
Set optg = PassedControl
Case "Page"
Set pg = PassedControl
Case "PageBreak"
Set pgb = PassedControl
Case "Rectangle"
Set Rec = PassedControl
Case "SubForm"
Set sfm = PassedControl
Case "TabControl"
Set tctl = PassedControl
Case "TextBox"
Set txt = PassedControl
Case "ToggleButton"
Set tgl = PassedControl
End Select
End Property
在主窗体模块的顶部放置以下代码。
Public collControls As Collection
Public cMultipleControls As clsMultipleControls
在主窗体的 Load 事件中放置以下代码。
GetCollection Me
在主窗体代码的底部放置以下递归公共子例程:
Public Sub GetCollection(frm As Form)
Dim ctl As Control
On Error Resume Next
Set collControls = collControls
On Error GoTo 0
If collControls Is Nothing Then
Set collControls = New Collection
End If
For Each ctl In frm.Controls
If ctl.ControlType = acSubform Then
GetCollection ctl.Form
Else
Set cMultipleControls = New clsMultipleControls
Set cMultipleControls.ctl = ctl
collControls.Add cMultipleControls
End If
Next ctl
end sub
我建议给表单及其子表单中的每个控件一个唯一的名称,以便您可以轻松地利用基于控件名称的 Select 语句来实现每个类模块事件中的处理控制。例如,每个文本框更改事件都将发送到类模块中的 txt_change 事件,您可以在其中使用 select 语句中的 m_PassedControl.name 属性来指示将在传递的控件上执行哪些代码。
如果您有多个控件将接收相同的 post entry 处理,则 select 事件非常有用。
我使用 Main Form Load 事件而不是 Activate 事件,因为弹出式表单(及其子表单)不会触发 Activate 或 Deactivate 事件。
如果您需要处理一些冗长的处理,也可以将 m_PassedControl 传递给常规模块中的子例程。
不幸的是,除非您在 VBA 模块中实际设置了事件,否则 Access 不会自动触发 VBA 事件。因此,如果您想使用文本框更改事件,您必须确保在适用的 vba 模块中实际设置了文本框更改事件。您不需要向事件添加任何代码,但空事件必须存在,否则事件及其等效类模块将不会触发。如果有人知道解决此问题的方法,我会很高兴听到。
我在http://yoursumbuddy.com/userform-event-class-multiple-control-types/ 的 Excel 用户表单代码示例中找到了这个基本的类模块结构。这是一个灵活的结构。我已经创建了适用于 Excel 用户表单、带有 activex 控件的 Excel 工作表以及现在适用于 Access 表单的版本。
后续注意:上面的代码在 64 位 Windows 10 上与 64 位 Access 2013 一起工作正常。但是当您尝试关闭主窗体时,它在 64 位 Windows 7 上的 64 位 Access 2013 上失败。解决方案是将以下代码从主窗体移动到 VBA 模块。
Public collControls As Collection
Public cMultipleControls As clsMultipleControls