Sharing code between 2 forms

  • Thread starter Thread starter JNLSeb
  • Start date Start date
J

JNLSeb

I have 2 Forms with the same field fields but each actually reference their
own table and data (there is a reason for this format).

I generated code under the General Module as well created a Class to house
code that is needed for both form.
Placing a copy of this code within each Form works great but am trying to
place it in one location so that changes only have to be done once.

Within the FORM_LOAD and FORM_OPEN it references this global code and even
tested it with the Class code, but it fails. When using the ActiveForm
reference, an error is returned to say the Form is not active.

The ME reference works when the code in within the Form but not as a class
or globally.

What reference should I be using?
How I create one piece code that references a given field name on two
different forms?

Thanks for any help.
 
when/how/where is the code triggered?

Just pass the current form to the code...


Call myCodeInAModule(me)

The above passes the current form ref tot he code....


Public Sub MyCodeInAModeule( frm as form)

we now can su the form

frm.Requery

frm!LastName = bla bal bla...


you can thus use "frm" in place of me in the code....


If you want, you can even pass the form + field name as a string.....


Call myCodeInAModule("frmCustomers","LastName")

your module code would look like


Public Sub MyCodeInAModeule(strForm as string, strField as string)


msgbox "the value of form = " & strForm & _
" and that of field = " & strField & _
" is currenlty = " & forms(strForm)(strField)


So, you can even pass control ref if you want.....like


Call myCodeInAModule(me.LastName)


Public Sub MyCodeInAModeule(ctrlLast as contorl)


msgbox "value of last name = " & ctrLast.Value

ctrLast.Requery

I mean, I could type on for a long time here...there is MANY ways to pass
a ref, be it the form, a simple string value, or even the contorl....

I also do have a lot of custom menu code..and in that case, I do pick up the
activeform. But, as a general rule you need to pick it up RIGHT
AWASY...since any kind of focus change..or even code that launches another
form will then change the ref.. Here is a exmaple of some custom menu
code..and not how it picks upt he form RIGHT away (so, if you use
activeForm..then grab it right away..and then your ref will no change if the
current form focus is changed due to somthing as semimply as bumping the
mouse).

I would say that 90% of my custom menu bars call, and run my VBA code.

All you need to do is make the code (a function) public, and then simply
place the function name in the buttons on-action event code.

Further, likely often you will have specific code to a particular form, and
once again, you simply declare those functions (in that form) as public.

The syntax to call the code then is:

=YourFunctionName()

Often, (if not most of the time), you code you call will need to pick up
some information about he current screen etc. So, my code most of the time
starts out, and grabs the current screen name. I use:

Public Function AskInvoicePrint()

Dim tblgroupid As Long
Dim frmActive As Form

Set frmActive = Screen.ActiveForm

tblgroupid = frmActive.frmMainClientB.Form!ID

If frmActive.InvoiceNumber = 0 Then
frmActive.InvoiceNumber = nextinvoice
frmActive.Refresh
End If

DoCmd.OpenForm "guiInvoicePrint", , , "id = " & tblgroupid

End Function

The above is code that the invoice print button runs. note how I right away
pick up the active form. After that, I can easily ref the forms object as if
the code was running much like the code would if put behind a button on the
form. In the above example, I also check if a invoice number has been
generated before printing. And, the Refresh forces a disk write if in fact I
do change the invoice number. And, in addition the above clip also passes
the currently selected sub-form item that the invoice print form needs.

Also, if the code you write is for the particular form, then as mentioned,
you can simply place the code into the forms module code. There is no need
to pick up the active screen...and you can use me. as you
always used.

If you want to see some sample menu bars, and why I use them, you can read
the following:

http://www.members.shaw.ca/AlbertKallal/Articles/UseAbility/UserFriendly.htm


--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
(e-mail address removed)
http://www.members.shaw.ca/AlbertKallal
 
Thanks for the update.
I actually tried many of the suggestions you offered, but when used within
the Form_Open or Form_Load event the error is returned.
Calling it the same way via a Button on the form works great.

Once the form is loaded this code works fine but during the Form_load and
Form_open it complains.

If I try the ActiveForm keyword it will come back with an error saying there
is no Active Form when used during the Form_OPEN or Form_LOAD events.

There appears to be some timing issue as the form does not really exist
during the Form_Open or Form_Load events.
 
If I try the ActiveForm keyword it will come back with an error saying
there
is no Active Form when used during the Form_OPEN or Form_LOAD events.

There appears to be some timing issue as the form does not really exist
during the Form_Open or Form_Load events.

in the form open, or later event of form load...you can use "me"

The above shows that you can pick up the previous form..and
do so as late as the on-load event.

Note that the form does not finish loading until BOTH of those events are
COMPLETE finished. So, in fact after the forms activate event, then the open
event, and even as LATE as the forms on-load event..the active form is STILL
THE PREVIOUS form......

in fact, a TON of my code uses


Option Compare Database
Option Explicit

Dim frmPrevious as form

The above code is in the forms module defs...

Now, in my on-open event (or, even as late as the on-load event), we can go

set frmPrevious = screen.ActiveForm


For the rest of the code, anywhere...anytime in the form...I can now go

frmPrevous!LastName = bla bla bla...

or, use any forms methods

frmPrevious.Requery

So, my point in the above shows that you can pick up the previous form..and
do so as late as the on-load event. If you are opening other forms in the
on-open/load events..then those other forms will appear on top..since as
mentioned the form does not finish loading until BOTH of those events are
COMPLETE finished.


If you need the current form in the on-open/load....just use "me"
 
Yes, using "MsbBox(Me.fieldname.Value)" works great as expected within the
Form_Open or Form_Load, but trying doing:

"MyRoutine (Me)" within Form_Open and Form_Load

Then have MyRoutine defined as:

Public Sub MyRoutine (x as Form)
MsgBox (x.fieldname.Value)
End Sub

This will result in a Type Mismatch error.
 
JNLSeb said:
Yes, using "MsbBox(Me.fieldname.Value)" works great as expected within the
Form_Open or Form_Load, but trying doing:

"MyRoutine (Me)" within Form_Open and Form_Load

Then have MyRoutine defined as:

Public Sub MyRoutine (x as Form)
MsgBox (x.fieldname.Value)
End Sub

This will result in a Type Mismatch error.


Your call of

MyRoutine (me)

is wrong.

You need to dump the brackets....

Use

MyRoutine me

To avoid your above problem, when you use a subroutine call....use the
following syntax

Call MyRouinte(me)

By placing brackets around the expression, you, forcing a evaluation of the
expression BEFORE it is passed to the calling routine. To simulate what you
are doing, you could go

Call MyRouinte( (me) )

note the above set of brackets above.....

This forces the me expression to be evaluated before it is passed. It turns
out the default expression for a form is the controls collection.

Given the above information, then I suppose you could use

MyRoutine (me)

And, in the calling you could use

Public Sub MyRoutine (f as contorls)

or

Public Sub MyRoutine (f as Varient)

Your code example fails...because you have () around the expression.

You best start the habit of using

Call MyRoutine(par1, par2, par3)....

Or, in your case, you are using

Call MyRoutine(me)


I can go

msgbox "hello"

or

msgbox "hello",vbExclamation,"my title"

if I go

msgbox ("hello",vbExclamation,"my title")

I will receive a compile error...as that syntax is wrong. With ONE param, it
works because you are not using () for parameters..but using the () to force
a evaluation of the expressions....eg

msgbox ("hello"),(vbExclamation),("my title")

From a coding point of view...placing () around everything means you want
the expression to be evaluated..and THEN passed on to the calling routine...

To avoid the above, adopt the standard of NOT using brackets, or even
better...ALWAYS use the call syntax..and thus always brackets, and you never
will have a expresison evalauted by accident....
 
Back
Top