簡體   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