Access VBA:如何订阅从其他VBA代码而不是用户交互中发生的控件/字段更改

Access VBA:如何订阅从其他VBA代码而不是用户交互中发生的控件/字段更改,vba,ms-access,Vba,Ms Access,我的处境很奇怪。 我有一个带有子窗体的窗体。 当子窗体中的值更改时,在更新后我调用 If Not IsNull(Me.Parent) Then Me.Parent.ParentField.Value = Me.SubformField.Value End If 在父窗体中,我希望ParentField中的更改触发另一个事件。 太糟糕了,以编程方式更改既不会触发AfterUpdate事件,也不会触发onChange事件 由于同一子表单在更多父表单中使用,因此我无法直接调用在afterUpd

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

If Not IsNull(Me.Parent) Then
   Me.Parent.ParentField.Value = Me.SubformField.Value
End If
在父窗体中,我希望
ParentField
中的更改触发另一个事件。 太糟糕了,以编程方式更改既不会触发
AfterUpdate
事件,也不会触发
onChange
事件

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


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

一般来说,当VBA更改时,控制事件不会触发。这是有意义的,因为该控件可能会发生很多事件,因此确定何时以及何时不运行所有这些事件将是一场噩梦

但是,您可以在父窗体中调用代码并执行代码,然后让它运行

因此,如果某个按钮或某个事件代码为给定控件运行,只需让该事件代码调用父窗体中的公共子项即可

因此,单击按钮或在更新后可以:

Call MySub
MySub只是按钮或事件代码以主窗体调用的一个公共sub

现在,在子表单中,您可以:

Me.Parent.ParentField.Value = me.SomeField

Call me.Parent.MySub()
我想你也可以使用一个函数,然后:

My.Parent.MyFunctionToRun()

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

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

我创建了一个模型,如下所示(父用户表单上的命令按钮主要用于保持初始焦点,在这个模型中,当输入文本框时,子表单将打开):



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

  • 子表单:
    SubUserForm
    TextBoxS
  • 父窗体:
    ParentUserFrom
    TextBoxP
如果任何人想要使用代码模型,在创建userforms之后,他们要么需要更改文本框和userforms的名称,要么需要更改它们在代码中的引用

'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

基于Excel用户表单的经验(不确定这是否转化为Access;因此不作为答案添加)。可能使用子窗体创建一个类。值更改时引发自定义事件。在父窗体上,添加withevents子窗体类的实例应允许在自定义事件下的父窗体代码中添加自定义代码;类似于为dropdop/textbox更改、按钮单击等添加代码。您的Answare似乎正是我想要的,但不幸的是,我不太了解如何实现它。我使用了一个“愚蠢”的解决方案,它检查父函数是否具有正确的函数,并仅在存在匹配项时调用该函数。不太理想,但考虑到我的时间限制,这是最快的解决方案。很公平。我将添加一个更详细的答案,并为可能在Excel中处理此问题的任何人创建一个模型。我担心在从VBA更改代码时不会触发任何事件。我希望避免直接调用父函数,因为我有更多的父函数使用相同的子窗体,并且不是所有的父函数都使用该方法。最后,我只是在父
FormName
属性上运行了一个检查,并且仅当该方法与正确的名称匹配时才调用该方法。我希望子窗体不知道父窗体,但我想这是不可能的。
'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
'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