繁体   English   中英

访问VBA:如何订阅控件/字段的更改是由其他vba代码而不是用户交互引起的

[英]Access VBA: how to subscribe to a the change of a control/field happened from other vba code and not from user interaction

我很奇怪。 我有一个带有子窗体的窗体。 当子窗体中的值更改时,在更新后,我调用

If Not IsNull(Me.Parent) Then
   Me.Parent.ParentField.Value = Me.SubformField.Value
End If

在父窗体中,我希望ParentField的更改触发另一个事件。 不幸的是,以编程方式进行更改不会触发AfterUpdateonChange事件。

由于在更多父表单中使用了相同的子表单,因此我无法直接调用afterUpdate上调用的方法

还有什么我可以“订阅”的吗?

至少在Excel中,可以通过向子用户窗体添加自定义事件,然后将子用户窗体作为对象添加到父用户窗体中来实现。

我创建了一个模型,如下所示(“父用户”窗体上的命令按钮主要用于保持初始焦点,因为在此模型中,输入文本框后会打开子窗体):

子用户和父用户表单

'SubUserForm code
Option Explicit
'Custom Events don't have to pass values, or can pass multiple values as desired
Public Event FormChange(newValue As Variant)

Private Sub TextBoxS_Change()
    'If I wanted the event to raise for various control changes,
    '    I could add it to multiple Change Events.
    RaiseEvent FormChange(TextBoxS.Value)

    'Or I could instead call a private sub such as
    '        ConditionalEvent(TextBoxS.Value)
    '    with the logic for checking if the event should
    '    be raised; especially helpful if
    '    logic depends on multiple changes or conditions
End Sub

Private Sub ConditionalEvent(vNew As Variant)
    If True Then 'More complicated checks, maybe changed private variables, etc.
        RaiseEvent FormChange(vNew)
    End If
End Sub

'This is to prevent the parent losing refernce to the sub form.
'The parent should be the one that creates an instance of this form,
'   as well as be the one to delete it.
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Cancel = True
    Me.Hide
End Sub

'Parent UserForm code
Option Explicit
'The private instance of the subform needs to be of the
'    baseform itself, not a generic object or userform.
'    Otherwise the custom event won't carry through.
'    However, this also means that the only events carried through
'    will be the custom ones (at least as far as I could tell)
Private WithEvents subForm As SubUserForm

'This is the custom event from the subform
Private Sub subForm_FormChange(newValue As Variant)
    TextBoxP.Value = newValue
End Sub

'This is important. The default value of subform is Nothing,
'    so initialization is required.
Private Sub UserForm_Initialize()
    Set subForm = New SubUserForm
End Sub

'This sub is the mock-up logic and call to show the sub form for testing.
'It is not required for using custom events.
Private Sub TextBoxP_Enter()
    subForm.Show
End Sub

Private Sub UserForm_Terminate()
    'Terminates the subform on parent closure
    Set subForm = Nothing
End Sub

为了进行测试,我使用下面的代码显示了父用户表单。 请注意,我还更改了文本框和用户窗体的名称,如下所示:

  • 子窗体: SubUserFormTextBoxS
  • ParentForm: ParentUserFromTextBoxP

如果有人想使用代码模型,则在创建用户表单后,他们将需要更改文本框和用户表单的名称,或在代码中对其的引用。

'In a generic module
Option Explicit

' Used to open the parent form for testing
Sub test()
    ' Using a with statement allows using a new instance of the form
    '    (instead of the "free instance" automatically provided)
    '    without having to assign the new instance to a variable to
    '    use, and then having to assign to variable to Nothing
    With New ParentUserForm
        .Show
    End With
End Sub

通常,控件事件在由VBA更改时不会触发。 这是有道理的,因为对该控件可能会发生很多事件,因此确定何时以及何时不运行所有这些事件将是一场噩梦。

但是,您当然可以在父窗体中调用代码并执行代码并使其运行。

因此,如果为给定控件运行按钮或某些事件代码,只需让该事件代码以父窗体形式调用公共子即可。

因此,单击按钮,或在更新后可以进行以下操作:

Call MySub

MySub只是按钮或事件代码在主窗体中调用的公共子项。

现在,在子表单中,您可以执行以下操作:

Me.Parent.ParentField.Value = me.SomeField

Call me.Parent.MySub()

我想您也可以使用功能,然后执行以下操作:

My.Parent.MyFunctionToRun()

因此,以事件代码(或按钮)调用的父形式设置一个公共例程(子例程或函数)。 然后,只需在子表单中调用与上述相同的例程即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM