Class 创建一个类来处理访问表单控制事件

Class 创建一个类来处理访问表单控制事件,class,vba,events,ms-access,commandbutton,Class,Vba,Events,Ms Access,Commandbutton,我正在尝试创建一个类来处理Access中的多个控件事件。这是为了避免重复键入多行相同代码 我遵循了下一页上的答案,但做了一些调整,使其能够访问rahter而不是Excel 我的班级代码如下: Option Compare Database Public WithEvents ct As Access.CommandButton 'Changed object type to something recognised by Access Public Sub ct_Click() M

我正在尝试创建一个类来处理Access中的多个控件事件。这是为了避免重复键入多行相同代码

我遵循了下一页上的答案,但做了一些调整,使其能够访问rahter而不是Excel

我的班级代码如下:

Option Compare Database

Public WithEvents ct As Access.CommandButton 'Changed object type to something recognised by Access

Public Sub ct_Click()
    MsgBox ct.Name & " clicked!"
End Sub
Option Compare Database
Private listenerCollection As New Collection
Private Sub Form_Load()
Dim ctItem
Dim listener As clListener

For Each ctItem In Me.Controls
    If ctItem.ControlType = acCommandButton Then 'Changed to test whether control is a Command Button
        Set listener = New clListener
        Set listener.ct = ctItem
        listenerCollection.Add listener
    End If
Next

End Sub
我的表格代码如下:

Option Compare Database

Public WithEvents ct As Access.CommandButton 'Changed object type to something recognised by Access

Public Sub ct_Click()
    MsgBox ct.Name & " clicked!"
End Sub
Option Compare Database
Private listenerCollection As New Collection
Private Sub Form_Load()
Dim ctItem
Dim listener As clListener

For Each ctItem In Me.Controls
    If ctItem.ControlType = acCommandButton Then 'Changed to test whether control is a Command Button
        Set listener = New clListener
        Set listener.ct = ctItem
        listenerCollection.Add listener
    End If
Next

End Sub
我已经注意到了我对(工作)Excel代码所做的更改。我认为问题在于类中的对象声明。注意:此过程中不会引发任何错误;它根本不会触发事件

提前谢谢

编辑:


此后,我将问题缩小到“点击”事件中没有“[Event Procedure]”。如果我手动添加,该类将按预期工作。显然,我不想手动添加这些,因为它会破坏对象。你知道我该怎么做吗?

在你的OnLoad事件中,你可以添加这一行

Dim ctItem
Dim listener As clListener

For Each ctItem In Me.Controls
    If ctItem.ControlType = acCommandButton Then 'Changed to test whether control is a Command Button
        Set listener = New clListener
        Set listener.ct = ctItem
        listener.ct.OnClick = "[Event Procedure]"  '<------- Assigned the event handler
        listenerCollection.Add listener
    End If
Next
然后在你的表格中,你可以像这样添加一个ct

Public WithEvents ct As Access.CommandButton 'Changed object type to something recognised by Access

Public Function AddControl(ctrl as Access.CommandButton) as Access.CommandButton
    set ct = ctrl
    ct.OnClick = "[Event Procedure]"
    Set AddControl = ct
End Function

Public Sub ct_Click()
    MsgBox ct.Name & " clicked!"
End Sub
For Each ctItem In Me.Controls
    If ctItem.ControlType = acCommandButton Then 'Changed to test whether control is a Command Button
        Set listener = New clListener
        listener.AddControl ctItem
        listenerCollection.Add listener
    End If
Next

现在在类中添加了事件处理程序

使用类模块处理访问表单控件输入的通用方法:

此代码是为处理在弹出窗口中编写的应用程序而精心编制的。主窗体包含一个选项卡控件,其中每个选项卡都包含链接子表或独立表的子窗体。使用或不使用选项卡控件不应对类模块处理产生任何影响

可以对代码进行裁剪以满足应用程序的需要。例如,可以从类模块中删除未使用的控件。同样,控件集合子例程也可以通过使用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
GetCollection Me
在主模板的加载事件中,放置以下代码

Public collControls As Collection
Public cMultipleControls As clsMultipleControls
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_更改事件,您可以在select语句中使用m_PassedControl.name属性来指示将在传递的控件上执行哪些代码

如果有多个控件将接收相同的输入后处理,则select事件非常有用

我使用主窗体加载事件而不是激活事件,因为弹出窗体(及其子窗体)不会触发激活或停用事件

如果有一些长时间的处理需要适应,还可以将m_PassedControl传递给常规模块中的子例程

不幸的是,除非您在VBA模块中实际设置了事件,否则Access不会自动触发VBA事件。因此,如果要使用textbox更改事件,必须确保在适用的vba模块中实际设置了textbox更改事件。您不需要向事件添加任何代码,但空事件必须存在,否则事件及其类模块等价物将不会触发。如果有人知道这方面的工作,我很高兴听到

我在的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

不久前我也做过类似的事情,所以不记得所有的细节。下面的链接很有帮助。您的类需要一个属性“Form”。在属性集中,添加代码“[Event Procedure]”在表单私有mclass的模块级声明类,如表单_openevent Set mclass=New mclass.form=MeThanks Brad所示,我实际上已经走了这条路线,但我更愿意在类中设置属性-我将尝试上面AVG的建议+1提供一个有效的解决方案。@JiminyCricket我做了一个编辑,可以让你在类中进行所有的属性设置。这非常有帮助!我一直在努力在课堂上获得一个属性,我甚至从来没有考虑过取消函数。虽然在加载过程中添加属性可以正常工作,但这要好得多,因为它都是自包含的。于是我的课堂冒险开始了。。。这是我很久以来一直想做的事!