[英]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
的更改觸發另一個事件。 不幸的是,以編程方式進行更改不會觸發AfterUpdate
或onChange
事件。
由於在更多父表單中使用了相同的子表單,因此我無法直接調用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
為了進行測試,我使用下面的代碼顯示了父用戶表單。 請注意,我還更改了文本框和用戶窗體的名稱,如下所示:
SubUserForm
, TextBoxS
ParentUserFrom
, TextBoxP
如果有人想使用代碼模型,則在創建用戶表單后,他們將需要更改文本框和用戶表單的名稱,或在代碼中對其的引用。
'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.