By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,476 Members | 1,529 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,476 IT Pros & Developers. It's quick & easy.

How to detect a Sub-Form event from the Main Form?

100+
P: 119
I have an Access form (MainForm) that has a SubForm. I would like to know if a MainForm event exists that detects a SubForm record change.

I can use the "On Current" event to detect when the MainForm record changes, but does an event such as "On SubForm On Current" exist?

Many thanks,
Nov 7 '08 #1
Share this Question
Share on Google+
13 Replies


Expert Mod 2.5K+
P: 2,545
Hi. It is the subform's On Current event that fires for each record in the subform. The main form cannot receive or handle the subform's events. If you wish to use this event you have to place the code in the subform itself.

Whilst it may technically be possible to set up custom event handlers for your subform to which the main form could listen this is not a trivial task. I have not tried this with a main form / sub form combination so I cannot say for sure that it is even possible to use this approach. Custom event handlers can work well for independent forms.

If you wish to call subroutines or functions outside of the scope of your form's code modules (which are local in scope to the form concerned and not visible to any other form, even in mainform/subform combinations) you will need to place the code concerned in a public code module (i.e. one that is shown in the Modules tab of the database window). You can then call the code as necessary from the relevant On Current event handler.

-Stewart
Nov 7 '08 #2

100+
P: 119
Thanks for your help...In trying to implement a solution, I encountered a related problem, which will involve some more explanation...

MainForm has two sub-forms, SubForm1 and SubForm2.

When the record in SubForm1 changes, I want to display different records in SubForm2.

I can almost achieve this by using the following code in the Form_Current event of SubForm1

Expand|Select|Wrap|Line Numbers
  1. ' === Code in SubForm1 ===
  2.  
  3. Private Sub Form_Current()
  4.  
  5.     If CurrentProject.AllForms("MainForm").IsLoaded Then
  6.         If CurrentProject.AllForms("SubForm2").IsLoaded Then
  7.             'If MainForm is loaded when SubForm1 record gets changed, change
  8.             ' the filter in SubForm2
  9.             Forms("MainForm").SubForm2.Form.Filter = "ChartId=" & Me.ChartID
  10.         End If
  11.     End If
  12.  
  13. End Sub

The problem here is that whilst the code recognizes that MainForm is open, the "IsLoaded" property does not get set to TRUE for sub-forms. Do you know of a way of determining whether or not a form is open as a sub-form?
Nov 7 '08 #3

Expert Mod 2.5K+
P: 2,545
Hmm, unless you have some form of automated selection of which subform is loaded as part of the main form, wouldn't it always be the case that the subform must be present if the main form is?

Anyway, there is no built-in function that checks for the subform being loaded, but the following simple custom function returns true if the named subform control is present on the main form and false otherwise. I really do think this is a redundant check, however.

Expand|Select|Wrap|Line Numbers
  1. Public Function fSubformLoaded (mainformname As String, subformname As String)
  2.   Dim Result As Boolean
  3.   On Error Resume Next
  4.   Result = Not IsNull(Forms(mainformname).Controls(subformname).Form.Name)
  5.   fSubformLoaded = Result
  6. End Function
If the subform control does not exist on the main form an error will result, which is dealt with safely by the On Error Resume Next, resulting in return of the default value False for variable Result. If the control does exist then the subform's name property is non-null and the function will return True instead.

-Stewart
Nov 7 '08 #4

100+
P: 119
Hmm, unless you have some form of automated selection of which subform is loaded as part of the main form, wouldn't it always be the case that the subform must be present if the main form is?

Anyway, there is no built-in function that checks for the subform being loaded, but the following simple custom function returns true if the named subform control is present on the main form and false otherwise. I really do think this is a redundant check, however.

Expand|Select|Wrap|Line Numbers
  1. Public Function fSubformLoaded (mainformname As String, subformname As String)
  2.   Dim Result As Boolean
  3.   On Error Resume Next
  4.   Result = Not IsNull(Forms(mainformname).Controls(subformname).Form.Name)
  5.   fSubformLoaded = Result
  6. End Function
If the subform control does not exist on the main form an error will result, which is dealt with safely by the On Error Resume Next, resulting in return of the default value False for variable Result. If the control does exist then the subform's name property is non-null and the function will return True instead.

-Stewart
You are correct in that the sub-forms are always present when the MainForm is loaded, with one key exception...When MainForm is originally loading. This is causing the problem. That's why I wanted the code in SubForm1 to check to see if SubForm2 had loaded.

Once MainForm is loaded (and therefore the sub-forms) I don't need any checks, i.e. I can simply use:

Expand|Select|Wrap|Line Numbers
  1. Private Sub Form_Current()
  2.             Forms("frmChartSeries").frmSeries.Form.Filter = "ChartId=" & Me.ChartID
  3. End Sub
I did find a work around, which isn't particularly elegant, but it seems to do the trick...The Visible property is only visible after the form (and sub-forms) has fully loaded...I just won't apply the filter when the form loads (which doesn't matter, anyway).

Expand|Select|Wrap|Line Numbers
  1. Private Sub Form_Current()
  2.     If CurrentProject.AllForms("MainForm").IsLoaded And Forms("MainForm").Visible Then
  3.             Forms("MainForm").SubForm2.Form.Filter = "ChartId=" & Me.ChartID
  4.     End If
  5. End Sub

Your suggestions also works, so many thanks for you help!
Nov 8 '08 #5

ADezii
Expert 5K+
P: 8,597
Thanks for your help...In trying to implement a solution, I encountered a related problem, which will involve some more explanation...

MainForm has two sub-forms, SubForm1 and SubForm2.

When the record in SubForm1 changes, I want to display different records in SubForm2.

I can almost achieve this by using the following code in the Form_Current event of SubForm1

Expand|Select|Wrap|Line Numbers
  1. ' === Code in SubForm1 ===
  2.  
  3. Private Sub Form_Current()
  4.  
  5.     If CurrentProject.AllForms("MainForm").IsLoaded Then
  6.         If CurrentProject.AllForms("SubForm2").IsLoaded Then
  7.             'If MainForm is loaded when SubForm1 record gets changed, change
  8.             ' the filter in SubForm2
  9.             Forms("MainForm").SubForm2.Form.Filter = "ChartId=" & Me.ChartID
  10.         End If
  11.     End If
  12.  
  13. End Sub

The problem here is that whilst the code recognizes that MainForm is open, the "IsLoaded" property does not get set to TRUE for sub-forms. Do you know of a way of determining whether or not a form is open as a sub-form?
The method to check and see if a Form is Loaded as a Sub-Form is to check its Parent Property, as in:
Expand|Select|Wrap|Line Numbers
  1. Public Function fIsSubFormLoaded(frm As Form) As Boolean
  2. 'Is the form referenced in the Parameter currently loaded as a subform?
  3. 'We can check its Parent property to find out.
  4. Dim strName As String
  5.  
  6. On Error Resume Next
  7.  
  8. strName = frm.Parent.Name
  9. fIsSubFormLoaded = (Err.Number = 0)
  10. Err.Clear
  11. End Function
Expand|Select|Wrap|Line Numbers
  1. If fIsSubFormLoaded(Me) Then
  2.   MsgBox "It is Loaded as a Sub-Form"
  3. Else
  4.   MsgBox "It is Loaded as a Stand Alone Form"
  5. End If
Nov 8 '08 #6

ADezii
Expert 5K+
P: 8,597
I'm a little rusty on this Topic but you should be able to detect Events in a Sub-Form from a Main Form by 'Hooking' to it:
  1. In the Main Form's Declarations Section, Declare a WithEvents Reference to the Sub-Form:
    Expand|Select|Wrap|Line Numbers
    1. Private WithEvents frmSubForm As Form
  2. In the Load() Event of the Main Form, 'Hook' it to the Sub-Form:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub Form_Load()
    2. Set frmSubForm = Forms![frmSubFormDemo]![subfSubForm].Form
    3.  
    4. frmSubForm.OnCurrent = "[Event Procedure]"
    5. End Sub
  3. Haven't had time to play with it, but you should somehow be able to react to the Current() Event of the Sub-Form from the Main Form.
Nov 8 '08 #7

missinglinq
Expert 2.5K+
P: 3,532
I'm confused by this statement!
You are correct in that the sub-forms are always present when the MainForm is loaded, with one key exception...When MainForm is originally loading
The fact is by the time the MainForm is originally loading, the subforms are already loaded! Subforms always load before the main form loads, unless, of course, a tear has occurred in the time continuum of space.

Linq ;0)>
Nov 8 '08 #8

FishVal
Expert 2.5K+
P: 2,653
I'm confused by this statement!

The fact is by the time the MainForm is originally loading, the subforms are already loaded! Subforms always load before the main form loads, unless, of course, a tear has occurred in the time continuum of space.

Linq ;0)>
Though it is certainly not the case, but I'd like to point out that is not true for main form being in datasheet view - subform will not be loadad until subdatasheet expanded.

@OP
A simple recursive procedure you could find here will help you to find a form opened in subform control.

@ADezii
Declaring form variable with events is certainly the best way to handle subform's events in main form module

Regards,
Fish.
Nov 8 '08 #9

ADezii
Expert 5K+
P: 8,597
Though it is certainly not the case, but I'd like to point out that is not true for main form being in datasheet view - subform will not be loadad until subdatasheet expanded.

@OP
A simple recursive procedure you could find here will help you to find a form opened in subform control.

@ADezii
Declaring form variable with events is certainly the best way to handle subform's events in main form module

Regards,
Fish.
Hello FishVal. It appears as though you are very proficient in the OOP approach. If you have a few minutes, can you demo exactly how you would 'Hook' a Sub-Form's Current() Event and capture it within the context of a Main Form. I realize that I have the correct concept, but I am a little rusty with OOP, and I'm not sure about the implementation of this concept. I thank you for your time and consideration in this matter.
Nov 8 '08 #10

FishVal
Expert 2.5K+
P: 2,653
Hello FishVal. It appears as though you are very proficient in the OOP approach. If you have a few minutes, can you demo exactly how you would 'Hook' a Sub-Form's Current() Event and capture it within the context of a Main Form. I realize that I have the correct concept, but I am a little rusty with OOP, and I'm not sure about the implementation of this concept. I thank you for your time and consideration in this matter.
Hello, ADezii.

Below is a code for subform Current event hooking.
It doesn't differ much from that you've already posted. ;)

Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. 'declare global object variable with events
  3. Private WithEvents frmSubform As Access.Form
  4.  
  5. Private Sub Form_Load()
  6.     'set reference to subform control form object
  7.     Set frmSubform = Me.sbf.Form
  8.     'set "OnCurrent" property so that a sub with special name -
  9.     '<object name>_<event name> will be called to handle event
  10.     frmSubform.OnCurrent = "[Event Procedure]"
  11. End Sub
  12.  
  13. 'event handling code - sets value of main form unbound control
  14. 'to a value obtained from subform control
  15. Private Sub frmSubform_Current()
  16.     Me.txbSubformEvent = Me.sbf.Form!txt
  17. End Sub
  18.  
  • Subform control form "HasModule" property has to be set to True
  • As soon as subform "Current" event occurs before mainform "Load" event it will be not handled when form has been opened, so the first "Current" event should be handled in mainform "Load" event handler.

Regards,
Fish
Nov 8 '08 #11

missinglinq
Expert 2.5K+
P: 3,532
that is not true for main form being in datasheet view - subform will not be loadad until subdatasheet expanded.
Thanks, Fish! Never knew that! Actually, never contemplated doing that or saw anyone else do it, but as always, it's better to know than not to know!

;0)>
Nov 8 '08 #12

ADezii
Expert 5K+
P: 8,597
Hello, ADezii.

Below is a code for subform Current event hooking.
It doesn't differ much from that you've already posted. ;)

Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. 'declare global object variable with events
  3. Private WithEvents frmSubform As Access.Form
  4.  
  5. Private Sub Form_Load()
  6.     'set reference to subform control form object
  7.     Set frmSubform = Me.sbf.Form
  8.     'set "OnCurrent" property so that a sub with special name -
  9.     '<object name>_<event name> will be called to handle event
  10.     frmSubform.OnCurrent = "[Event Procedure]"
  11. End Sub
  12.  
  13. 'event handling code - sets value of main form unbound control
  14. 'to a value obtained from subform control
  15. Private Sub frmSubform_Current()
  16.     Me.txbSubformEvent = Me.sbf.Form!txt
  17. End Sub
  18.  
  • Subform control form "HasModule" property has to be set to True
  • As soon as subform "Current" event occurs before mainform "Load" event it will be not handled when form has been opened, so the first "Current" event should be handled in mainform "Load" event handler.

Regards,
Fish
Thanks for taking the time and providing us with an explanation.
Nov 8 '08 #13

P: 1
Hi there,
Thanks for the explanation

However, this doesnt seem to work when the subform objectsource points to a table (allocated on the go by the main form)

ex: same as above, but the subformcontrol.sourceobject = "Table.foobar"

Would you know if there a trick or another way to detect oncurrent event, and even better, detect which field of the subform has focus ?

The idea is to display contextual information from many other tables, the model is fairly complex ... i'd need to show things when usefull.
May 27 '10 #14

Post your reply

Sign in to post your reply or Sign up for a free account.