How do I reference the Text Box control Text1 on Page2 of Tab Control TabCtl1 on Form2? I don't know if I am making it more difficult than it is but I tried in many different ways but have been unsuccessful so far. It seems to be quite the 'path' to travel: Form2 > TabCtl1 > Page2 > Text1.
Things in the main working area of a tab control are still considered part of the main form. As arnelgp says, use Me.xxxx because the tab control's name is NOT a part of the path. BUT if you have a sub-form, then it is Me.sub-form-control-name.Form.control-name-on-the-subform - again omitting the tab control name from the naming path.
For visibility issues, the tab controls make a difference. For naming issues, it is like they don't even exist.
Thank you that is really good to know. However, in my case, the Text Box is actually a subform. I thought the subform was interpreted as a control that's why I thought any control would do. The Text Box is in fact a subform. I always like to strip a problem down to its simplest form and remove all the extraneous imformation that usually doesn't affect my question. In this case it, unfortunately, did. I thought if someone can show me the way to a control then I can experiment from that point forward. My apologies about my misleading question.
The actual situation is as follows:
The field on subfrmNotesDetails I am trying to read is called NoteText. Would you gents mind having another go at it?
In that case you can reference the control as if it was any subform on a form. This is because of how Access treats controls on a tab. They are also added as properties of the mainform.
Code:
me.SubformControlName.Form.ControlName
me.subfrmNotesDetails.Form.NoteText
Do not forget ".Form" which returns the form inside the subform control. Also make sure the sub form control is truly named subFrmNotesDetails. The subform control and the form inside may not have the same name.
Now to be more precise, on why you can reference a control on a tab and why it may matter.
You can reference a control on a tab directly, because Access makes it a property of both the tab and also the form. So this is an additive feature.
Things in the main working area of a tab control are still considered part of the main form.
A tab control has a Pages Collection. Each page has a Controls collection. So you can follow the natural hierarchy to reference a control on a page on a tab
Me.tabOne.pages("Page1Name").controls("textboxName")
However, Access did us a favor and doubled it up to make it easier to reference. Pages on tab controls and controls on pages are in addition added to the forms control collection and added as properties of the form. This doubling up seems strange but provides a shorter path to reference the controls. You now can go direct instead of through the pages and control collections.
Me.Page1Name
Me.TextBoxName
So where does this make a difference? The parent of a control on a Page is the Page. The parent of the Page is the tab control. The parent of the tab control on a form is the form.
So although it seems as if the control on a tab is a child of the main form, the parent of the control is not the form. For a control on a tab you have to go back through it heirarchy to reference the form.
dim ParentFrm as form
set ParentFrm = txtBoxOne.Parent.Parent.Parent
Now to be more precise, on why you can reference a control on a tab and why it may matter.
You can reference a control on a tab directly, not be cause it is not a property of the tab but because Access has in addition added it as a property of the form. So this is an additive feature.
The above statement is not completely correct and it can make a difference. More precisely
A tab control has a Pages Collection. Each page has a Controls collection. So you can follow the natural hierarchy to reference a control on a page on a tab
Me.tabOne.pages("Page1Name").controls("textboxName")
However, Access did us a favor and doubled it up to make it easier to reference. Pages on tab controls and controls on pages are in addition added to the forms control collection and added as properties of the form. Doing something like this is strange in the VBA object module (I know of no other place where this double tapping is done), but makes it a lot easier to shortcut the naming reference. You now can go direct instead of through the pages and control collections.
Me.Page1Name
Me.TextBoxName
So where does this make a difference? The parent of a control on a Page is the Page. The parent of the Page is the tab control. The parent of the tab control on a form is the form.
So although it seems as if the control on a tab is a child of the main form, the parent of the control is not the form. For a control on a tab you have to go back through it heirarchy to reference the form.
dim ParentFrm as form
set ParentFrm = txtBoxOne.Parent.Parent.Parent
I am SO pleased to know about this. I like working with Tab Controls and this information is gold! So, if I am understanding you correctly, if you're on the main form and want to address the subform (on a Tab Control page) you can do:
me.subfrmNotesDetails.Form.NoteText
But when you need to go 'the other way', i.e. need to reference a control on the main form from the subform you have to take the full hierarchy into account.
If my main form is frmForm2 and it has a control called txtTextBox2, then how do I reference that from the subform subfrmNotesDetails?
If from the main you reference a control on a subform on a tab it can be done as if the subform is simply on the form.
Me.subfrmNotesDetails.form.NoteText
However if you called code from the subform to reference a control on the main form
me.Parent.Parent returns Page2
Me.Parent.Parent returns Your Tab Control
Me.Parent.Parent.Parent returns your Form 2
If from the main you reference a control on a subform on a tab it can be done as if the subform is simply on the form.
Me.subfrmNotesDetails.form.NoteText
However if you called code from the subform to reference a control on the main form
me.Parent.Parent returns Page2
Me.Parent.Parent returns Your Tab Control
Me.Parent.Parent.Parent returns your Form 2
I believe this code will return the main form no matter how many subforms and how many tabs the control is nested.
Code:
Public Function GetMainForm(Ctl As Access.Control) As Form
On Error GoTo errlbl
Dim CurrentObject As Object
Set CurrentObject = Ctl
Do
Set CurrentObject = CurrentObject.Parent
If TypeOf CurrentObject Is Form Then
Set GetMainForm = CurrentObject
End If
Loop
Exit Function
errlbl:
If Err.Number <> 2452 Then
MsgBox Err.Number & Err.Description
End If
End Function
In other words it keeps calling the parent (form, page, tab) until the object no longer has a parent. That can only be the main form.
Inspecting the Form variable will help you learn how to reference anything from anywhere.
1. You seem to have a parent form with a tab control and a subform control on page 2 of that tab.
2. The requirement is to reference a textbox in the subform from the parent form.
If I add a little Stop in form2's open event like this:
Code:
Private Sub Form_Open(Cancel As Integer)
Stop
End Sub
I see that I get a Me variable in my locals window
If I expand that variable, I can inspect it. The first thing I can see is that I have a node called "Controls". If I expand controls I get this:
Notice how I get 1 tab control item, 2 pages items, 1 subform item as well as other items from the very same Controls node. That's only one example, but if I go to the Form node, and then the Controls node of that, I get the same. If I go to the the Module node and then Parent, then Controls, I get the same. And there are other nodes from where I can get references, there's the Application node, the Parent node, the Properties node, etc. Most notably, at the end of the tree of nodes, I get the contents of these Controls nodes. So I can use any and all of these.
I will open a few nodes and see what references I can come up with:
From Me.Controls:
Me.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Controls.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me.Form.Controls:
Me.Form.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Form.Controls.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Form.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me.Properties:
Me.Properties.Item("BorderStyle").Parent.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me:
Me.TabCtl0.Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
And any time you see .Item("Something") can be replaced with !Something, for example:
Me.Controls.Item("TabCtl0").Pages!page2.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
I could go on with other places where the reference can be made, but I hope you get the point. Check the attachment. If I wanted to reference something from outside, like a module, then instead of Me, use Application.Forms("theForm") and inspect it.
I believe this code will return the main form no matter how many subforms and how many tabs the control is nested.
Code:
Public Function GetMainForm(Ctl As Access.Control) As Form
On Error GoTo errlbl
Dim CurrentObject As Object
Set CurrentObject = Ctl
Do
Set CurrentObject = CurrentObject.Parent
If TypeOf CurrentObject Is Form Then
Set GetMainForm = CurrentObject
End If
Loop
Exit Function
errlbl:
If Err.Number <> 2452 Then
MsgBox Err.Number & Err.Description
End If
End Function
In other words it keeps calling the parent (form, page, tab) until the object no longer has a parent. That can only be the main form.
Inspecting the Form variable will help you learn how to reference anything from anywhere.
1. You seem to have a parent form with a tab control and a subform control on page 2 of that tab.
2. The requirement is to reference a textbox in the subform from the parent form.
If I add a little Stop in form2's open event like this:
Code:
Private Sub Form_Open(Cancel As Integer)
Stop
End Sub
I see that I get a Me variable in my locals window View attachment 107462
If I expand that variable, I can inspect it. The first thing I can see is that I have a node called "Controls". If I expand controls I get this: View attachment 107463
Notice how I get 1 tab control item, 2 pages items, 1 subform item as well as other items from the very same Controls node. That's only one example, but if I go to the Form node, and then the Controls node of that, I get the same. If I go to the the Module node and then Parent, then Controls, I get the same. And there are other nodes from where I can get references, there's the Application node, the Parent node, the Properties node, etc. Most notably, at the end of the tree of nodes, I get the contents of these Controls nodes. So I can use any and all of these.
I will open a few nodes and see what references I can come up with:
From Me.Controls:
Me.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Controls.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me.Form.Controls:
Me.Form.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Form.Controls.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
Me.Form.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me.Properties:
Me.Properties.Item("BorderStyle").Parent.Controls.Item("TabCtl0").Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
From Me:
Me.TabCtl0.Pages.Item("page2").Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
And any time you see .Item("Something") can be replaced with !Something, for example:
Me.Controls.Item("TabCtl0").Pages!page2.Controls.Item("child_form").Controls.Item("txtSomeTextbox").Value
I could go on with other places where the reference can be made, but I hope you get the point. Check the attachment. If I wanted to reference something from outside, like a module, then instead of Me, use Application.Forms("theForm") and inspect it.
This is fantastic. I didn't know you can do this with the Locals window. Thank you for taking the time and effort to explain this. To have a fail-safe approach to referencing, to me, is of great value. I've downloaded your database and I'm going to see if I can learn to find my way around the Locals window.
Between you and MajP I have learned the most from any forum yet! I deeply appreciate the effort. Thanks again, Thomas.
Not suggesting it is somehow wrong since I used it to explain the dilemma with the parent property, but I have never seen anyone beside you actually reference a control on a tab through the tab control and pages collection when you can go direct.
Shortcuts are taught wrong. I know it. You know it. Everyone with enough time in this knows it. Shortcuts are the reason these threads exist.
No idea what that means, and do not really think the reason these threads exists has something to do with shortcuts. In this case it is definitely not "taught wrong." The Access developers purposely made these controls direct properties of the form, for the purpose of making it easier to reference them.
Not suggesting it is somehow wrong since I used it to explain the dilemma with the parent property, but I have never seen anyone beside you actually reference a control on a tab through the tab control and pages collection when you can go direct.
No idea what that means, and do not really think the reason these threads exists has something to do with shortcuts. In this case it is definitely not "taught wrong." The Access developers purposely made these controls direct properties of the form, for the purpose of making it easier to reference them.
Inspecting the Form object will help you clear any doubts about Parent references. Several members of the Form class inherit Parent. In the example I provided, I'm using Parent to reference the same textbox from the BorderStyle property, an exercise to demonstrate that even a property can be used to reach the control. Information that is easy to understand through inspection.
Since inspection is never mentioned in threads about referencing controls, developers may get the wrong idea that there's only one way to do things, especially when they're presented with the link in post #6, when the information has always been in plain sight, not even hidden, because developers see it all the time while trying to debug the reference (if their locals window is visible). The syntax I'm using is THE exercise we should all be presented with when trying to reference something. The syntax is long, but it's consistent and you can use shortcuts if you want, like I mentioned. However, posts #2, #3, #5, #6, #7, #10 and #14 are using shortcuts, especially the link in post #6, which combines default members, bang and dot notation. How could new developers not get confused with this amount of variation?
well without any reading material about msa, he will be at lost.
a solid foundation is necessary before going deep in programming.
you don't practice anything that you are in mastery of it.
it is always true, read the manual first before operating.
post#2 is shortcut, because reference to a control in a form can have many
notation and i prefer the shorter one.
also post#2 is intended to answer post#1, a Textbox (not a subform) inside the tab control.