Recognize which form is calling the code

E

Elizabeth

Hi -

I have a contacts form that can be used to enter a new contact into the
database. I have many forms throughout the system that may call this form at
any time. I am writing some code and I want to save the name of the form
that originally called the contacts form in a variable so I can pass control
back to the original form.

Can anyone help me with this?

Thanks,
Elizabeth
 
C

ChrisO

' Some other Form…
Private Sub cmdOpenContacts_Click()

DoCmd.OpenForm "Contacts", OpenArgs:=Me.Name

End Sub

' In Form Contacts…
Private Sub Form_Open(Cancel As Integer)

If Len(Me.OpenArgs) Then
MsgBox Forms(Me.OpenArgs).Name
End If

End Sub
 
M

Marshall Barton

ChrisO said:
' Some other Form…
Private Sub cmdOpenContacts_Click()

DoCmd.OpenForm "Contacts", OpenArgs:=Me.Name

End Sub

' In Form Contacts…
Private Sub Form_Open(Cancel As Integer)

If Len(Me.OpenArgs) Then
MsgBox Forms(Me.OpenArgs).Name
End If

End Sub


ChrisO,
Wouldn't MsgBox Me.OpenArgs work just as well?
I mean, why go to the form to get its name when you used its
name to get to the form??

While the If will work, Len(Me.OpenArgs) will be Null when
OpenArgs is not specified in the OpenForm line. I think it
is clearer to use IsNull instead of Len.
 
C

ChrisO

G'day Marshall

Certainly: -

MsgBox Forms(Me.OpenArgs).Name

Returns the Name of the passed Form but it was used as a demo in that: -

Forms(Me.OpenArgs)

Returns a pointer to the Form and can be used for other purposes.


---------------


If Len(Me.OpenArgs) Then

Handles both a Null and a ZLS, which I tend to use most of the time, but I
must confess that in this case it seems redundant. It seems that if a ZLS is
passed as OpenArgs it gets converted to a Null.

Thanks for the heads up and I will look into that further.

Regards,
Chris.
 
N

NevilleT

Here is another approach. Set a public variable called varCallingForm.
Before opening the contacts, set the value of varCallingForm. When the form
is closed, return to varCallingForm. You can then delete the value of
varCallingForm.

Remember the cat's skin can be removed in many different ways :)
 
J

Jack Leach

But what happens if the user calls the contacts for from one form, and all of
a sudden gets told to do some other task, and while varCallingForm is already
filled, gets re-filled with this new task... then you lose the reference of
the previous call, which may cause some pretty big issues depending on the
end means of the requirement to know the calling form.

Personally, I try to steer quite clear of using global variables for this
reason. Much safer, IMHO, to keep this contained in each form instance
through the use of Openargs.

People often complain about global variables losing their value if the code
is reset, but even if that were not an issue, there really isn't very many
good reasons to use a global variable...

just a thought.

happy coding!
--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)
 
J

Jack Leach

Actually, if nobody minds I'll take this thread in a little bit of a tagent
with different direction :)

I think I can safely say that I believe a public variable really should
never be used for anything other than holding application-level values that
will not change throughout that particular instance of the app. These
values, such as directories and versions, that are *almost* constants, but
not quite, should be the only thing we store in public variables, and by
route, should not be changed except when set at startup.

Any other placement of values in a public variable risks issues like the
aforementioned... in every case where I thought I would use a public variable
that doesn't follow the above rule of mine, I've been able to find a more
secure way to handle the info.

Discussion anyone? <g>
--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)
 
M

Marshall Barton

ChrisO said:
G'day Marshall

Certainly: -

MsgBox Forms(Me.OpenArgs).Name

Returns the Name of the passed Form but it was used as a demo in that: -

Forms(Me.OpenArgs)

Returns a pointer to the Form and can be used for other purposes.


Right! But, I was not suggesting using Forms(Me.OpenArgs)
OpenArgs is a string, in this case containing the name of
the form. So, if the name of the calling form is MyForm and
using the Immediate window:

?Me.OpenArgs
MyForm

?Forms(Me.OpenArgs).Name
MyForm

?Forms("MyForm").Name
MyForm

Please note that I was not implying that what you posted was
incorrect. I was just saying that it was unecessarily
roundabout.
 
M

Marshall Barton

Jack Leach said:
Actually, if nobody minds I'll take this thread in a little bit of a tagent
with different direction :)

I think I can safely say that I believe a public variable really should
never be used for anything other than holding application-level values that
will not change throughout that particular instance of the app. These
values, such as directories and versions, that are *almost* constants, but
not quite, should be the only thing we store in public variables, and by
route, should not be changed except when set at startup.

Any other placement of values in a public variable risks issues like the
aforementioned... in every case where I thought I would use a public variable
that doesn't follow the above rule of mine, I've been able to find a more
secure way to handle the info.


I agree, but I also like David Fenton's often posted
approach that takes it to yet another level by making it
read only and self healing after a reset.

Public Function MyVar()
Static X As Variant
If IsNull(X) Then X = {something}
MyVar = X
End Function
 
J

Jack Leach

Marshall Barton said:
[...] I also like David Fenton's often posted
approach that takes it to yet another level by making it
read only and self healing after a reset.

Public Function MyVar()
Static X As Variant
If IsNull(X) Then X = {something}
MyVar = X
End Function

Yes, this is good. I tend to do something similar using a public Property
Get with a private Let. But with David's method the static can be declared
at procedure level rather than module level, and the work can be condensed
into a single procedure. A bit more elegant, I think.

If one will go through the trouble to make sure to only use public values
for app-level data, then it would make sense to take this further step to
secure them a little better.

At that point, we can say that "public variables" are pretty much useless in
VBA...

--
Jack Leach
www.tristatemachine.com

"I haven''t failed, I''ve found ten thousand ways that don''t work."
-Thomas Edison (1847-1931)
 
V

vanderghast

A global variable can be useful, as example, a Collection where each entry
can hold a collection of parameters you need to send to DoCmd.OpenForm which
accepts only one string 'user defined argument' trough OpenArgs.


Public gDic As Collection ' The public variable


and then, to call a DoCmd.OpenForm with more than one parameter:
---------------
....
Dim x As New Collection ' create a collection
x.Add 1, "param1"
x.Add "easy", "param2"
x.Add #1/1/2011#, "param3" ' add all the parameter to the collection

If (gDic Is Nothing) Then Set gDic = New Collection

gDic.Add x, "myParams" ' add the collection to the global variable
' with a 'case-by-case' available 'key', here, I
used
' myParams as key


DoCmd.OpenForm "toto", openArgs:= "myparams" ' and send the 'key' to
be used
...
----------------

Then, the form can reach the collection of parameters quite easily:

----------------
Dim y As Collection
Set y= gDic.Items(openArgs) ' get the appropriate bunch of data
' from the public variable, using the key
' string value I sent

' then read each parameter, as required, or explicitly, like

Dim ij As Long
ij = y.Item("param1")

Dim str As String
str=y.Item("param2")
...
----------------

Note that nowhere the parameters have to be encoded and concatenated into a
string, losing precision or otherwise, and next have to be decoded. Sure,
you have to synch. the "keys" you intend to use form the various parts of
the program (while defining an interface would definitively be more robust,
and that is what I would strongly suggest to do, that is not what I want
illustrate, and would not help much to understand the actual point).



Vanderghast, Access MVP
 
C

ChrisO

G'day Marshall

We are probably talking at cross purposes here but I used

MsgBox Forms(Me.OpenArgs).Name

to demonstrate that Forms(Me.OpenArgs) can be used to retrieve properties of
the Form. That also includes Public variables behind the Form, running Public
procedures in the Forms Class module and such like. It was not meant to be
used solely for displaying the Form name.

Just a little value adding that Elizabeth may want to use.

-------------

Also, I think: -
If IsNull(X) Then X = "{something}"

should be...

If IsEmpty(X) Then X = "{something}"

Regards,
Chris.
 
M

Marshall Barton

ChrisO said:
G'day Marshall

We are probably talking at cross purposes here but I used

MsgBox Forms(Me.OpenArgs).Name

to demonstrate that Forms(Me.OpenArgs) can be used to retrieve properties of
the Form. That also includes Public variables behind the Form, running Public
procedures in the Forms Class module and such like. It was not meant to be
used solely for displaying the Form name.

Just a little value adding that Elizabeth may want to use.

Ahhh, I see. I guess that idea went over my head because I
felt that it may confuse Elizabeth and other readers.
-------------
Also, I think: -
If IsNull(X) Then X = "{something}"

should be...

If IsEmpty(X) Then X = "{something}"

Good point for the self healing subthread.

But it's different for the original thread re OpenArgs.
 
S

Stuart McCall

Jack Leach said:
Marshall Barton said:
[...] I also like David Fenton's often posted
approach that takes it to yet another level by making it
read only and self healing after a reset.

Public Function MyVar()
Static X As Variant
If IsNull(X) Then X = {something}
MyVar = X
End Function

Yes, this is good. I tend to do something similar using a public Property
Get with a private Let. But with David's method the static can be
declared
at procedure level rather than module level, and the work can be condensed
into a single procedure. A bit more elegant, I think.

If one will go through the trouble to make sure to only use public values
for app-level data, then it would make sense to take this further step to
secure them a little better.

At that point, we can say that "public variables" are pretty much useless
in
VBA...

I agree, but twas not always like that. VB Classic (vb6) didn't suffer with
global variable frailty like VBA, yet VBA evolved from vb6. Interesting that
the move from compileable code to just p-code interpretation seems to be at
the heart of the issue. Running VBA code is like running vb6 code in the
debug environment (p-code), but even then vb6 didn't break globals when an
unhandled error occurred. MS *must* have received complaints about this over
the years, yet they've never fixed it. That leads me to suspect that they
*can't* fix it for some reason. Maybe MichKa could tell us if he were still
around on here.

One method I use to circumvent this bug (yes it is a bug IMO) is to use ini
files. "Oh but that's doing a disk fetch" you might say, but once an ini
file has been accessed for the first time, it resides in the file system's
cache, so subsequent values are in fact read from RAM and are just as quick
and efficient as globals, but without the frailty. And their values survive
an application (or even a computer) reset.
 
J

Jack Leach

Thats a great idea. I've never even considered the possibility that one
might be able to transfer data like this. Vanderghast, every time you post
it really sheds a brand new light on things and gives a refreshing new
perspective. Thanks.

Using a method like this, one could add a collection of values to the
collection for each form that they have (probably even for each instance of
each form given some way to identify them through these 'keys'), and get away
from the 'useless overhead' that makes for inelegant code when people attempt
to make a bunch of public variables just for a purpose like this.

Interesting...

--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
J

Jack Leach

I agree, but twas not always like that. VB Classic (vb6) didn't suffer with
global variable frailty like VBA, yet VBA evolved from vb6. Interesting that
the move from compileable code to just p-code interpretation seems to be at
the heart of the issue. Running VBA code is like running vb6 code in the
debug environment (p-code), but even then vb6 didn't break globals when an
unhandled error occurred. MS *must* have received complaints about this over
the years, yet they've never fixed it. That leads me to suspect that they
*can't* fix it for some reason. Maybe MichKa could tell us if he were still
around on here.

I've always been curious about how other languages might handle similar
situations. VBA being the only language I know, I've always been curious
what would change if I knew something else... what standard practices I've
developed would be useful or not with a different language structure.
Unfortuntely that won't happen though... even VBA was learned at slightly
above hobby status, and that's a relatively easy language to pick up on your
own (and of course with your guys' help over the years).


One method I use to circumvent this bug (yes it is a bug IMO) is to use ini
files. "Oh but that's doing a disk fetch" you might say, but once an ini
file has been accessed for the first time, it resides in the file system's
cache, so subsequent values are in fact read from RAM and are just as quick
and efficient as globals, but without the frailty. And their values survive
an application (or even a computer) reset.

I currently employ the use of an ini file (using the functions from your
site Stuart... thanks), and load them directly into the public properties at
startup, with the self healing method applied. At some point I'll get around
to changing these to functions rather than properties... I like that idea a
lot better. But yes, an ini file works quite well for a good amount of this
information. Other values, such as current computer, user, display settings,
etc, are pulled from the relevant APIs.

Good discussion... sorry to have hijacked the thread...

--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)



Stuart McCall said:
Jack Leach said:
Marshall Barton said:
[...] I also like David Fenton's often posted
approach that takes it to yet another level by making it
read only and self healing after a reset.

Public Function MyVar()
Static X As Variant
If IsNull(X) Then X = {something}
MyVar = X
End Function

Yes, this is good. I tend to do something similar using a public Property
Get with a private Let. But with David's method the static can be
declared
at procedure level rather than module level, and the work can be condensed
into a single procedure. A bit more elegant, I think.

If one will go through the trouble to make sure to only use public values
for app-level data, then it would make sense to take this further step to
secure them a little better.

At that point, we can say that "public variables" are pretty much useless
in
VBA...

I agree, but twas not always like that. VB Classic (vb6) didn't suffer with
global variable frailty like VBA, yet VBA evolved from vb6. Interesting that
the move from compileable code to just p-code interpretation seems to be at
the heart of the issue. Running VBA code is like running vb6 code in the
debug environment (p-code), but even then vb6 didn't break globals when an
unhandled error occurred. MS *must* have received complaints about this over
the years, yet they've never fixed it. That leads me to suspect that they
*can't* fix it for some reason. Maybe MichKa could tell us if he were still
around on here.

One method I use to circumvent this bug (yes it is a bug IMO) is to use ini
files. "Oh but that's doing a disk fetch" you might say, but once an ini
file has been accessed for the first time, it resides in the file system's
cache, so subsequent values are in fact read from RAM and are just as quick
and efficient as globals, but without the frailty. And their values survive
an application (or even a computer) reset.


.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top