Form tag empty every other time

K

Ken K

Hi all

Every other time I try to return a tag ("Me.Tag") from a form, the tag is
empty, and the form's IsLoaded property remains true, even though it's been
closed using DoCmd.Close. I must be doing something wrong but can't see what
it is. I've tested this in a brand new database (platform is Access2K on
Win2K):

I create a form named "Form1" with one command button "Command0" and one
module "Module1". Form1's modal property is Yes, popup is No. The entire
code in the project is below.

Can anyone help me figure out why the form's tag is being returned blank and
the form's IsLoaded property stays true every *other* time? Should I
reinstall Access (the build is "9.0.6926 SP3")?

Many thanks...

<<in Module1>>
Option Explicit
Option Compare Database

Sub x()

Dim x As String
Dim f As Form

Set f = Form_Form1

DoCmd.OpenForm f.Name, , , , , acDialog

x = f.Tag
'every FIRST time f.tag = ""
'every SECOND time f.tag = "mytag"

DoCmd.Close acForm, f.Name

If CurrentProject.AllForms("Form1").IsLoaded Then
'this code firest every FIRST time
'every SECOND time Isloaded is false
'and this code skipped
Debug.Print "is loaded"
End If

Set f = Nothing

End Sub

<<in Form1>>

Option Explicit
Option Compare Database

Private Sub Command0_Click()
On Error GoTo Err_Command0_Click

Me.Tag = "mytag"
Me.Visible = False

Exit_Command0_Click:
Exit Sub

Err_Command0_Click:
MsgBox Err.Description
Resume Exit_Command0_Click

End Sub
 
A

Albert D. Kallal

DoCmd.OpenForm f.Name, , , , , acDialog

The above opens the form. And the code waits. The only way the code will
*continue* to run is that you set the forms visible property = false, or the
user CLOSES the form. So, how is the user closing that above form? (and,
even more important, why would you leave out such important details in your
post?).

Further, are you using multiple instances of the form? Remember, the INSTANT
you go:

msgbox f.tag

The above code causes the form to load, and even the forms on-load events
will fire. So, if your users is closing the form, the code "f.tag" will
actually cause the form to re-load and OPEN AGAIN!!!!

This form instance is COMPLETE separate from the "openform" command you are
using (again, if you are using multiple instances of the form to be opened
at the same time, the you can use your syntax, but if not, the you need to
dump that coding practice IMMEDIATE).

So, as a normal coding practice, do NOT use the base instance of the forms
class as you have. (since it you can corornaite that with the use of
openform command.

Hence, ALWAYS use openform to launch a form, like:

Sub x()

Dim x As String
Dim f As string

f = "form1"

DoCmd.OpenForm f, , , , , acDialog

if isloaded(f) = true then
' you code here....
myFirstName = forms(f).FirstName

I explain the above use of isloaded, and how to return values here:

http://www.members.shaw.ca/AlbertKallal/Dialog/Index.html

So, use the forms collection *always* to ref the form as above (or
forms!ForName).

Use caution when you define variables as the "base" class of the form. Eg:

dim f1 as Form_Form1

dim f2 as Form_Form1

if you go

msgbox f1.tag , then the form is loaded, and all events fire
msgbox f2.tag, then the form is loaded, and all events fire.

So, the MERE USE OF the form variable direct will case the form to be
initialised. (the FIRST TIME you use the variable in code will cause the
form to load). Thus, use much caution with this syntax, and ONLY use the
"form_form1" class object ONLY if you need multiple instances of the form
(again, it is VERY possible that you are in fact needing multiple instances
of that form, and thus you are in little need of my harsh warning). However,
if you don't need multiple instances of the form open, then you loose
complete control of when, or even what instance of the form you are using.
In the above example of f1, and f2, you will have two copies of the form
loaded, and BOTH will run/fire their own on-open/on-load events etc. And,
even worse, is that the "docmd.openform f1.name" would open a 3rd instance
of the form!!!
 
K

Ken K

Hi Albert

Thanks for getting back to me.

The code I posted is the entirety of the code in the project so I didn't
leave anything out. There aren't supposed to be multiple instances of the
form, only one.

Thanks for the link to your website. It's very helpful. I think perhaps my
problem is that I'm coming from VB and was trying to work with an object
based on the form. Am I right in guessing that you don't have to do that (or
it's not a good idea) in an Access database?

Just for the record, the user "closes" the form using the code I posted in
the Command0_Click sub ("...Me.Visible = False") which is what I understood
to be the right way to "close" a form opened using acDialog. My
understanding was that the way to return a value from a modally opened form
is to hide it, get the information and then close it using Docmd.Close. Is
that not correct practice?

A related question: if I did need multiple instances of the form, what
would be the best practice way of handling them so that I don't lose control
of them (as you mentioned can easily happen)?

Thanks again!

Ken
 
A

Albert D. Kallal

Thanks for the link to your website. It's very helpful. I think perhaps
my
problem is that I'm coming from VB and was trying to work with an object
based on the form. Am I right in guessing that you don't have to do that
(or
it's not a good idea) in an Access database?

yes on both accounts (and, yes, coming from VB, you tend to open/use the
form's base object, but not in ms-access. (so, you are 100% right on both
accounts).
Just for the record, the user "closes" the form using the code I posted in
the Command0_Click sub ("...Me.Visible = False") which is what I
understood
to be the right way to "close" a form opened using acDialog. My
understanding was that the way to return a value from a modally opened
form
is to hide it, get the information and then close it using Docmd.Close.
Is
that not correct practice?

Again, the above is correct. (I must have missed the .visible part..but that
is *exactly* how you drop out of the dialog form, and my article says the
same idea - I missed that you are doing this (sorry), but it makes 100%
sense that you were/are doing this approach!). So, yes, your practice is
good about the visible, but you do want to avoid using the base forms
reference in teh code that follows (you loose control over which instance
you are Woking with)..

A related question: if I did need multiple instances of the form, what
would be the best practice way of handling them so that I don't lose
control
of them (as you mentioned can easily happen)?

Well, in that case, you *must* use the base class objects. And, thus *you*
must keep control!!! And, further when you use *any* of the properties of
the object (our "form" variable), if the form is not initialized/loaded,
then the form events such as load etc. will fire. So, just keep that issue
in mind. It goes without saying that if you use multiple instances of the
forms object, then you not going to be using the forms() collection, nor can
you use openform (and, the openform is *really* handy, since you can pass
sql restrictions to the form - eg: open a form to ONE invoice

docmd.Openform "frmCustomers",,,"custID = 123"

The above opens the form, and loads it to ONE record...a commend
requirement. If you use the forms base objects, then you don't use
"openform", thus you can't pass those above arguments for example.


The *usually* approach then is to build a global collection object, and each
new form you open, you add to this collection.

I don't have a example handy, but ask/post a question about how to open
multiple instances in

Microsoft.public.access.forms
 
K

Ken K

Thanks again Albert. I'll explore the collection idea and also ask in the
forms discussion.
 

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