By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,780 Members | 1,549 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,780 IT Pros & Developers. It's quick & easy.

Can I prevent the loss of the values assigned to global variables after an untrapped run-time error?

P: n/a
MLH
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.

During development, I'm constantly running tests on imperfect code.
On of the cumbersome jobs encountered is reassigning global vars
their values after a close encounter with an untrapped runtime error.

Rather than writing a procedure to simply reassign them all with a
single bttn-clik, the way I've been doing it ever since Access 2.0 is
by closing and then reopening the app. That gets cumbersome.
But its the only way I've ever known. Just wondering.
Nov 13 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a

MLH wrote:
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I think not.
During development, I'm constantly running tests on imperfect code.

I think so.

Nov 13 '05 #2

P: n/a
MLH
On 11 Oct 2005 11:25:37 -0700, "lylefair" <ly***********@aim.com>
wrote: You should know - You've helped me fix enough of it.
During development, I'm constantly running tests on imperfect code.

I think so.


Nov 13 '05 #3

P: n/a
On Tue, 11 Oct 2005 14:12:26 -0400, MLH <CR**@NorthState.net> wrote:
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.

During development, I'm constantly running tests on imperfect code.
On of the cumbersome jobs encountered is reassigning global vars
their values after a close encounter with an untrapped runtime error.

Rather than writing a procedure to simply reassign them all with a
single bttn-clik, the way I've been doing it ever since Access 2.0 is
by closing and then reopening the app. That gets cumbersome.
But its the only way I've ever known. Just wondering.


One method is, instead of global variables, at least the key ones you want to keep,
use controls on an invisible form.

Nov 13 '05 #4

P: n/a
MLH
Now there's an idea. Thx.

One method is, instead of global variables, at least the key ones you want to keep,
use controls on an invisible form.


Nov 13 '05 #5

P: n/a
MLH wrote:
single bttn-clik, the way I've been doing it ever since Access 2.0 is
by closing and then reopening the app. That gets cumbersome.


Then:

1) don't use global variables.

Or

2) Include proper error handling.

Or

3) Store values on a hidden form

My preference is to do all three.
--
Tim http://www.ucs.mun.ca/~tmarshal/
^o<
/#) "Burp-beep, burp-beep, burp-beep?" - Quaker Jake
/^^ "Whatcha doin?" - Ditto "TIM-MAY!!" - Me
Nov 13 '05 #6

P: n/a
MLH <CR**@NorthState.net> wrote in
news:ta********************************@4ax.com:
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.

During development, I'm constantly running tests on imperfect
code. On of the cumbersome jobs encountered is reassigning global
vars their values after a close encounter with an untrapped
runtime error.

Rather than writing a procedure to simply reassign them all with a
single bttn-clik, the way I've been doing it ever since Access 2.0
is by closing and then reopening the app. That gets cumbersome.
But its the only way I've ever known. Just wondering.


First off, if your app uses lots of global variables, then there's
probably something wrong with it.

Global constants are a different thing -- those are fine, but they
also don't get lost on reset because they are hardwired into the
compiled p-code.

You need to re-evaluate all the cases where you are using global
variables and figure out if you can replace them with self-healing
objets.

For years, I used a global variable to store a reference to the
current database for use in place of every declaration of Set db =
CurrentDB(). But that wouldn't survive a code reset during
development, so I started doing this:

If dbGlobal Is Nothing Then Set dbGlobal = CurrentDB()
Set rs = dbGlobal.OpenRecordset([SQL])

If you replace the global variable with a function that returns the
data type of the global variable, that function can "heal" itself:

Function dbGlobal() As DAO.Database
Static db As Database

If db Is Nothing Then Set db = CurrentDB()
dbGlobal = db
End Function

The way this works is that, with a STATIC variable, the first time
it's called, it initializes the internal STATIC variable, and as
long as there's not a code reset, just returns the value of the
STATIC variable. If there's a code reset, the STATIC variable gets
cleared and when the function is called it will be re-initialized.

This principle can be applied to any number of global variables that
are used to store application-wide data (such as form colors or any
other application-specific data).

Now, the problem is: where do you store the persistent data?

Well, you can have a table or you can use custom properties of the
MDB file. Why, then, not just look them up each time you use them?
Because it's much slower to do a table lookup up or to find the
value of a database custom property than it is to check a global
variable or get the value from a public function.

Now, as you can see, I'm limiting this to global variables that are
used for storing global values that are permanent throughout a
working session, and have only one value that is not changed after
the variable is initialized.

All global variables that change values at runtime SHOULD BE
ENTIRELY ELIMINATED FROM AN APPLICATION.

For passing data between forms, it's much better to *not* use global
variables. I tend to use class modules for this, as simple data
storage structures, because class modules can be self-initializing,
and because they provide a single intermediate structure for
mediating between runtime objects. That is, if you want form1 to get
data from form2, a class module makes it much easier to manage.
Form2 sets up the class module, and then form1 gets its data from
the class module. This makes it much easier to get the same data
from different forms, because the receiving form needs to know only
about the class module -- it doesn't need to know anything at all
about the source form.

That's the idea behind using global variables for that purpose, but
that has the downside of:

1. losing values on a code reset with no way to automatically
re-initialize them.

2. values don't clear themselves when they are obsolete, so you
could accidentally use data that was a different context.

With a class module-based structure you initialize an instance of
the class for the immediate purpose, populate its values, use the
values in a different context, then when done, destroy the instance,
thus clearing stored values.

The key issue here is that you just need to get away from using
global variables as much as possible. If you do that, you end up
with better code and less annoyance during coding.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #7

P: n/a
MLH
Thx David, for the thorough reply. I certainly have
a handful on my plate now. Yes, I used lots of them
and can see not that it was not a wise decision.
Nov 13 '05 #8

P: n/a
One of my forms has a great deal of internal state information,
most of it loaded from a table when the form opens. If I reset
during debug, the state is lost, and the form no longer works.

It is not self-healing: I am forced to close and re-open the form.

What would be your approach to this situation?

(david)

"David W. Fenton" <dX********@bway.net.invalid> wrote in message
news:Xn**********************************@24.168.1 28.90...
MLH <CR**@NorthState.net> wrote in
news:ta********************************@4ax.com:
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.

During development, I'm constantly running tests on imperfect
code. On of the cumbersome jobs encountered is reassigning global
vars their values after a close encounter with an untrapped
runtime error.

Rather than writing a procedure to simply reassign them all with a
single bttn-clik, the way I've been doing it ever since Access 2.0
is by closing and then reopening the app. That gets cumbersome.
But its the only way I've ever known. Just wondering.


First off, if your app uses lots of global variables, then there's
probably something wrong with it.

Global constants are a different thing -- those are fine, but they
also don't get lost on reset because they are hardwired into the
compiled p-code.

You need to re-evaluate all the cases where you are using global
variables and figure out if you can replace them with self-healing
objets.

For years, I used a global variable to store a reference to the
current database for use in place of every declaration of Set db =
CurrentDB(). But that wouldn't survive a code reset during
development, so I started doing this:

If dbGlobal Is Nothing Then Set dbGlobal = CurrentDB()
Set rs = dbGlobal.OpenRecordset([SQL])

If you replace the global variable with a function that returns the
data type of the global variable, that function can "heal" itself:

Function dbGlobal() As DAO.Database
Static db As Database

If db Is Nothing Then Set db = CurrentDB()
dbGlobal = db
End Function

The way this works is that, with a STATIC variable, the first time
it's called, it initializes the internal STATIC variable, and as
long as there's not a code reset, just returns the value of the
STATIC variable. If there's a code reset, the STATIC variable gets
cleared and when the function is called it will be re-initialized.

This principle can be applied to any number of global variables that
are used to store application-wide data (such as form colors or any
other application-specific data).

Now, the problem is: where do you store the persistent data?

Well, you can have a table or you can use custom properties of the
MDB file. Why, then, not just look them up each time you use them?
Because it's much slower to do a table lookup up or to find the
value of a database custom property than it is to check a global
variable or get the value from a public function.

Now, as you can see, I'm limiting this to global variables that are
used for storing global values that are permanent throughout a
working session, and have only one value that is not changed after
the variable is initialized.

All global variables that change values at runtime SHOULD BE
ENTIRELY ELIMINATED FROM AN APPLICATION.

For passing data between forms, it's much better to *not* use global
variables. I tend to use class modules for this, as simple data
storage structures, because class modules can be self-initializing,
and because they provide a single intermediate structure for
mediating between runtime objects. That is, if you want form1 to get
data from form2, a class module makes it much easier to manage.
Form2 sets up the class module, and then form1 gets its data from
the class module. This makes it much easier to get the same data
from different forms, because the receiving form needs to know only
about the class module -- it doesn't need to know anything at all
about the source form.

That's the idea behind using global variables for that purpose, but
that has the downside of:

1. losing values on a code reset with no way to automatically
re-initialize them.

2. values don't clear themselves when they are obsolete, so you
could accidentally use data that was a different context.

With a class module-based structure you initialize an instance of
the class for the immediate purpose, populate its values, use the
values in a different context, then when done, destroy the instance,
thus clearing stored values.

The key issue here is that you just need to get away from using
global variables as much as possible. If you do that, you end up
with better code and less annoyance during coding.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc

Nov 13 '05 #9

P: n/a
"MLH" <CR**@NorthState.net> wrote in message
news:ta********************************@4ax.com...
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.


Yes, there is:

Simply distribute a mde to your users.

I hate to admit it, but a lot of my very small routines do NOT have error
handling, and I happen to think that they don't requite it.

So, if you use a mde, then un-handled errors don't re-set local, or global
vars...

So, this is just one of many reasons why a mde is the preferred choice, and
is what you should distribute to your users.
--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal
Nov 13 '05 #10

P: n/a
> I hate to admit it, but a lot of my very small routines do NOT have error
handling, and I happen to think that they don't requite it.
I didn't think so either when I was using A97.

But A2000 forms in MDE's give garbage error messages
unless there is an explicit error handler at the top
level.

(david)
"Albert D. Kallal" <ka****@msn.com> wrote in message
news:0BX2f.152042$1i.94413@pd7tw2no... "MLH" <CR**@NorthState.net> wrote in message
news:ta********************************@4ax.com...
A97 Topic: If there is a way to preserve the values assigned to
global variables when an untrapped runtime error occurs? I don't
think there is, but I thought I'd ask.


Yes, there is:

Simply distribute a mde to your users.

I hate to admit it, but a lot of my very small routines do NOT have error
handling, and I happen to think that they don't requite it.

So, if you use a mde, then un-handled errors don't re-set local, or global
vars...

So, this is just one of many reasons why a mde is the preferred choice,
and is what you should distribute to your users.
--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal

Nov 13 '05 #11

P: n/a
MLH
Its good to know that if you use an mde, un-handled errors don't
re-set local, or global vars. I do distribute mde's. I was really
wanting to avoid them being reset during untrapped errors
during my own development for convenience - nothing more.
Laziness really.
Nov 13 '05 #12

P: n/a
MLH wrote:
Now there's an idea. Thx.
One method is, instead of global variables, at least the key ones you want to keep,
use controls on an invisible form.


The other (better) idea is to trap your runtime errors, handle the
obvious one (e.g. File not found, just tell the user he typed that in
wrong[1] and offer him a browse dialog to select one)

Reminds me of my fav response to users reporting errors:
What did you type in wrong to get that result?
Nov 13 '05 #13

P: n/a
MLH wrote:
Its good to know that if you use an mde, un-handled errors don't
re-set local, or global vars. I do distribute mde's. I was really
wanting to avoid them being reset during untrapped errors
during my own development for convenience - nothing more.
Laziness really.


I use a sub called Globs() that loads my global variables (both of them,
workspace and current database objects). In my error handling I log
errors to a table, in that procedure it checks the error number and can
do things depending on the error, if the error is an object variable not
set then it calls Globs() and can recover.
Nov 13 '05 #14

P: n/a
Trevor Best <no****@localhost.invalid> wrote in
news:43***********************@news.zen.co.uk:
MLH wrote:
Its good to know that if you use an mde, un-handled errors don't
re-set local, or global vars. I do distribute mde's. I was
really wanting to avoid them being reset during untrapped errors
during my own development for convenience - nothing more.
Laziness really.


I use a sub called Globs() that loads my global variables (both of
them, workspace and current database objects). In my error
handling I log errors to a table, in that procedure it checks the
error number and can do things depending on the error, if the
error is an object variable not set then it calls Globs() and can
recover.


You could replace each of those two globals with a function
returning an object of the appropriate type and have the function
check Is Nothing each time it runs and re-initialize. If you use a
STATIC variable in those functions, you wouldn't need a global at
all.

I have code for this for the database variable that I've posted a
million times. Search Google Groups for Public Function dbLocal and
that should bring it up for you.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #15

P: n/a
David W. Fenton wrote:
You could replace each of those two globals with a function
returning an object of the appropriate type and have the function
check Is Nothing each time it runs and re-initialize. If you use a
STATIC variable in those functions, you wouldn't need a global at
all.

I have code for this for the database variable that I've posted a
million times. Search Google Groups for Public Function dbLocal and
that should bring it up for you.


Thanks David, I'll look into it when I start something fresh. I have
seen it posted b4 but havn't done anything with it as the main app I
work on has been around since 1999 so would be a lot of work to change
it in 150,000+ lines of code :-)
Nov 13 '05 #16

P: n/a
Trevor Best <no****@localhost.invalid> wrote in
news:43***********************@news.zen.co.uk:
David W. Fenton wrote:
You could replace each of those two globals with a function
returning an object of the appropriate type and have the function
check Is Nothing each time it runs and re-initialize. If you use
a STATIC variable in those functions, you wouldn't need a global
at all.

I have code for this for the database variable that I've posted a
million times. Search Google Groups for Public Function dbLocal
and that should bring it up for you.


Thanks David, I'll look into it when I start something fresh. I
have seen it posted b4 but havn't done anything with it as the
main app I work on has been around since 1999 so would be a lot of
work to change it in 150,000+ lines of code :-)


I don't know how many apps I've changed it in, but as I revisit any
of them for updates, I implement my dbLocal() function, though I
sometimes give it the name of the global variable that had
previously been used, which makes it a pretty painless conversion.
Keep in mind that if you're doing this:

If dbGlobal Is Nothing Then Set dbGlobal = CurrentDB()
dbGlobal.OpenRecordset(,.,)

It won't cause an error, because the test if dbGlobal Is Nothing
will initialize it so that it *can't* be nothing, and you'll get a
compile error on that, which you can then go through and search and
replace out of there.

Basically, how much work it takes to implement the new function
depends on how you've been using your global db variable.

But it sure does make new programming way easy!

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #17

P: n/a
MLH
I Like That.
xxxxxxxxxxxxxxxx

Reminds me of my fav response to users reporting errors:
What did you type in wrong to get that result?


Nov 13 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.