Solved Using calling form name in VBA on called form (1 Viewer)

debsamguru

Member
Local time
Today, 08:47
Joined
Oct 24, 2010
Messages
82
Hi,

I call a FormA from several forms - e.g. Form1, Form2 and Form3. I want to code some processing in FormA dependant upon which form has called FormA. Is the only way to get the calling formname by passing it in OpenArgs? If I already pass an OpenArg, do I have to concatenate a string together to be separated in FormA? Is there an easier way to do this?
 

GPGeorge

Grover Park George
Local time
Today, 00:47
Joined
Nov 25, 2004
Messages
1,829
It may not be the only way, but it is by far the most straightforward to implement, IMO. Yes, concatenate with a nonstandard character to minimize the possibility of ambiguity in the string. I use | for example, most of the time. No, not that I know of.
 

Eugene-LS

Registered User.
Local time
Today, 10:47
Joined
Dec 7, 2018
Messages
481
Is the only way to get the calling formname by passing it in OpenArgs?
No, some use the Tag property for this purpose.
Code:
DoCmd.OpenForm "Form Name"
Forms("Form Name").Tag = Me.Name 'where return ... (call form)
DoCmd.Close acForm, Me.Name
 

theDBguy

I’m here to help
Staff member
Local time
Today, 00:47
Joined
Oct 29, 2018
Messages
21,454
Yet another way is to use TempVars.
 

debsamguru

Member
Local time
Today, 08:47
Joined
Oct 24, 2010
Messages
82
A bit more research for me then as I haven't used Tag or TempVars
 

Eugene-LS

Registered User.
Local time
Today, 10:47
Joined
Dec 7, 2018
Messages
481
A bit more research for me then as I haven't used Tag or TempVars
It's very easy!
On closing "called form" write:
Code:
DoCmd.OpenForm Me.Tag   ' Opening form called from
DoCmd.Close acForm, Me.Name   ' Closing current form
 

debsamguru

Member
Local time
Today, 08:47
Joined
Oct 24, 2010
Messages
82
Thanks Eugene-LS but I don't see how that passes the form name through.

On Form1, when I click on a button, it opens FormA. When I am in FormA, I have some code that says:
IF coming from Form1 THEN
Do something
ELSE
Do something different
END IF

The Tag doesn't pass between the two forms, from what I see.
 

Eugene-LS

Registered User.
Local time
Today, 10:47
Joined
Dec 7, 2018
Messages
481
On Form1, when I click on a button, it opens FormA. When I am in FormA, I have some code that says:
Code:
Select Case Me.Tag " Tag property - stores the name of the previous form
   Case "Form1"
      'Instructions for  Form1 ...
   Case "Form22"
      'Instructions for  Form22 ...
   Case "FormA"
      'Instructions for  FormA ...
   Case "FormB"
      'Instructions for  FormB ...
   Case Else
      'Instructions for  that case ...
End Select
 

debsamguru

Member
Local time
Today, 08:47
Joined
Oct 24, 2010
Messages
82
Sorry I'm obviously being very obtuse tonight.

In Form 1, I have the following code:
Code:
Private Sub AddNewItemBtn_Click()
    Dim CustomerInputID As Variant
    
    CustomerInputID = Me.CustomerID
    DoCmd.OpenForm "NewStockItemF", , , , acFormAdd, , CustomerInputID

End Sub

In FormA - New StockItemF - I use the Select Case or IF..THEN..END IF

But where do I pass/put the me.Tag?
 

Eugene-LS

Registered User.
Local time
Today, 10:47
Joined
Dec 7, 2018
Messages
481
Sorry I'm obviously being very obtuse tonight.
I also hold up already ... :)
Code:
Dim CustomerInputID As Long

    CustomerInputID = Nz(Me.CustomerID, 0)
        
    DoCmd.OpenForm "NewStockItemF", , , , acFormAdd, , CustomerInputID
    Forms("NewStockItemF").Tag = Me.Name 'Storing current form name
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 08:47
Joined
Jul 9, 2003
Messages
16,271
I call a FormA from several forms - e.g. Form1, Form2 and Form3. I want to code some processing.....

After form1 calls formA do you close formA before form2 calls it?

If not, you may get unexpected results...
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 08:47
Joined
Jul 9, 2003
Messages
16,271
You might find my blog on opening one form from another handy...


I prefer to pass information into a custom property in the receiving form.

You also have the opportunity to call a public function in the called form, form A, which would automatically run your code for you.

There's a written explanation and a video explanation on my blog.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 03:47
Joined
Feb 19, 2002
Messages
43,223
On Form1, when I click on a button, it opens FormA. When I am in FormA, I have some code that says:
IF coming from Form1 THEN
Do something
ELSE
Do something different
END IF
If you have to know what form called you, then the code is NOT reusable and you should create a different form.

I would use the OpenArgs with the pipe delimiter as someone already mentioned. In the form's open event split the OpenArgs and create public variables at the form level. Use those rather than the OpenArgs throughout the code.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 03:47
Joined
May 21, 2018
Messages
8,525
There is really no need to have to pass a delimited string in openargs then go throught the work of splitting it. It works, but it is kind of a lot of effort. OpenArgs is really only needed when you open the form ACDIALOG. If not opening ACDIALOG it is just easier IMO to pass the value in directly.

The reason is as @Eugene-LS points out, that if not calling it ACDIALOG then after you open the second form the code execution continues from where you left off in the Calling form. At that point you can set any property or even run methods in the called form from the calling form

Code:
    Dim CustomerInputID As Long

    CustomerInputID = Nz(Me.CustomerID, 0)
    DoCmd.OpenForm "NewStockItemF", , , , acFormAdd, , CustomerInputID
    
    'Code execution continues here after the called forms
    'completes it all the events associated with opening (open, load, current ...)
    
    'so since the code keeps running you can set any property of any object in the called form
    Forms("NewStockItemF").Tag = Me.Name 'Storing current form name

If you do not want to use the tag property you can add your own property. In "NewStockItemF" at the top of the module before the first procedure you can add

Code:
Public CallingFormName as String
Then you can do something like
Code:
    DoCmd.OpenForm "NewStockItemF", , , , acFormAdd, , CustomerInputID
     Forms("NewStockItemF").CallingFormName = Me.Name

Then in your select case or if then instead of
Select Case Me.Tag
it would be
Select Case CallingFormName
or
If CallingFormName = "..."
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 03:47
Joined
May 21, 2018
Messages
8,525
BTW the description here of ACDIALOG in the Windowmode is very poor
It is not just that it opens modal, and dialog, but that code execution stops in the calling form until the called form is closed.
And that is why you would have to use openargs, because the calling form never gets control back while the called form is open.
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 15:47
Joined
May 7, 2009
Messages
19,232
you don't even need a function or sub or tag in FormA.
you will know which Form (the caller) opens FormA using
FormA's Open Event:

Option Explicit
Dim CallerForm As String

Private Sub Form_Open(Cancel As Integer)
CallerForm = Screen.ActiveForm.Name
End Sub

'______________
the on the click of a button on FormA:

private sub button1_click()
select Case CallerForm
Case "Form1"
'do something
Case "Form2"
'do something
End Select
end sub
 

debsamguru

Member
Local time
Today, 08:47
Joined
Oct 24, 2010
Messages
82
Thank you all.

Eugene, The me.Name worked perfectly. On to the next conundrum!
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 03:47
Joined
Feb 19, 2002
Messages
43,223
There are two issues with the method suggested by @MajP
1. It dirties the new record on the form. Most of the time this won't cause a particular problem because most of the time, the user will just complete the data entry. However, in the situation where the user fails to complete the data entry, you have two potential problems.
a. you create a record that is empty except for the FK. This is clutter at best but may cause other problems.
b. Assuming you have proper validation code to keep a user from saving an "empty" record, the user gets an error message when he closes the form complaining about missing data. The user KNOWS he didn't type anything so this tends to be very confusing to him.
2. If the process is such that you will need to enter multiple records, only the FIRST record created by the form will have the correct foreign key. Subsequent records will be created as orphans (if the FK is not defined as required) or the user will get an error that he won't be able to resolve because he can't enter the FK manually.

This method is called "push". I prefer to use the "pull" method.
In this case I pass the name of the form in the OpenArgs. Then in the BeforeInsert event of the called form, the called program gets the FK value and any other values it needs by directly referencing the calling form's controls. Using the BeforeInsert event means that your code never dirties the form. The BeforeInsert event runs when a user types the first character in a control and it runs once for EACH new record so it solves both of the above problems. The user already dirtied the record so he won't be confused by data validation error messages and the code runs for each new record so the called form can create multiple records with the same FK.

The downside of "pull" is that ALL forms that call this one, assuming the form can be called from multiple other forms, MUST all use the same names for the controls the called form will need to access.

An alternate to the "push" method is instead of populating a control with the pushed value, your code sets a default value for a control. That doesn't dirty the record. The record is not dirtied until the user types something. And, since you have provided a default, every record created will have the correct value populated for a hidden field like the foreign key/
 
Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 03:47
Joined
May 21, 2018
Messages
8,525
There are two issues with the method suggested by @MajP
1. It dirties the new record on the form. Most of the time this won't cause a particular problem because most of the time, the user will just complete the data entry. However, in the situation where the user fails to complete the data entry, you have two potential problems.
a. you create a record that is empty except for the FK. This is clutter at best but may cause other problems.
b. Assuming you have proper validation code to keep a user from saving an "empty" record, the user gets an error message when he closes the form

@PatHartman,
I assume you are not familiar with how the dirty event works so I will explain it for you. The dirty property is set to true when the event fires. The .dirty event happens as described below.

The Dirty event occurs when the contents of the specified control changes.
Examples of this event include entering a character directly in the text box or combo box or changing the control's Text property setting by using a macro or Visual Basic.
Modifying a record within a form by using a macro or Visual Basic doesn't trigger this event. You must type the data directly into the record or set the control's Text property.
This event applies only to bound forms, not an unbound form or report.

Setting other properties of a form such as the Tag property or a custom property ("CallingFormName"), most certainly do not cause the dirty event to fire and make the form dirty. So your statement is completely incorrect. Nothing is made dirty, and no record is created. I have provided a demo to prove this to you.

As per the below, not even sure how at all this relates to anything discussed here. I guess in some unrelated example this could be true, but not really of relevance here. Not even sure where we are getting foreign keys and child records, there is no mention of that.
2. If the process is such that you will need to enter multiple records, only the FIRST record created by the form will have the correct foreign key. Subsequent records will be created as orphans (if the FK is not defined as required) or the user will get an error that he won't be able to resolve because he can't enter the FK manually.
However the statement is definitely not true. What you are proposing can be just as easily done with the tag property or a custom property instead of OpenArgs. Nothing special about openargs.
I do not know, maybe you are on the wrong thread or like usual you could not be bothered to read what was actually written.

In the demo you can see that changing these properties does not make the form dirty.
Dirty.jpg
 

Attachments

  • DemoDirty.accdb
    1.2 MB · Views: 251

Users who are viewing this thread

Top Bottom