Make instant of a Class persistent for whole session.

  • Thread starter Thread starter sime
  • Start date Start date
S

sime

Hello

When my database opens, I use Autoexec to run a function. In that
function I want to instantiate a class and have that instance remain
accessible for the whole session.

Specifically I am using the class to make variables efficiently
available to any other code.

I can do this with a form that hides itself - is that the only way to
do this? It seems a bit silly, but hey if that's the way I should do it
I won't complain. :-)

Thanks
Simon
 
Hi Simon,

Why can't you just declare the variables that you wish to persist as
globals, and set their value in the function that you run from your autoexec
macro. I really don't see the need to instantiate a class to accomplish this
goal. Something like this for determining the users NTUserID, and storing it
in the global variable named gstrUserName. Then just call the fOSUserName
function from your Autoexec macro.


Module name: basUtilities
Within this module:

' Get Login name
' http://www.mvps.org/access/api/api0008.htm

Option Compare Database
Option Explicit

Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Public gstrUserName As String

Function fOSUserName() As String
On Error GoTo ProcError

Dim lngLen As Long, lngX As Long
Dim strUserName As String

strUserName = String$(254, 0)
lngLen = 255
lngX = apiGetUserName(strUserName, lngLen)
If (lngX > 0) Then
fOSUserName = Left$(strUserName, lngLen - 1)
Else
fOSUserName = vbNullString
End If

gstrUserName = fOSUserName

ExitProc:
Exit Function
ProcError:
MsgBox "Error " & Err.Number & ": " & Err.Description, _
vbCritical, "Error in procedure fOSUserName..."
gstrUserName = "Unknown"
Resume ExitProc
End Function



Tom Wickerath
Microsoft Access MVP

http://www.access.qbuilt.com/html/expert_contributors.html
http://www.access.qbuilt.com/html/search.html
__________________________________________
 
Yes, that does the trick. And it works with Objects.

I had tried "Global" inside the class module, and I had tried your
suggestion with with things like "Static" and "Global Static". So
close!

Thanks heaps
Simon
 
Hi Simon,

You're welcome.

The only other thing you might do, just to help ensure that your global
variable will always have a value, is to use the Len function to ensure this
just prior to an attempt to reference it. Later versions of Access have been
much better than earlier versions about not losing global variables, however,
it is possible to lose the value if you are working in the Visual Basic
Environment, or it may not have been set in the first place if you opened
your database with the Shift key depressed in order to bypass the Autoexec
file. Here is an example:

If Len(gstrUserName) = 0 Then
fOSUserName ' Reinitialize value
End If

Select Case gstrUserName
Case blahblahblah
Do this
Case Else
Do that
End Select

This way, if the test for the length of your global variable is zero, a call
is made to re-initialize it just prior to attempting to do something with it,
such as Select Case.


Tom Wickerath
Microsoft Access MVP

http://www.access.qbuilt.com/html/expert_contributors.html
http://www.access.qbuilt.com/html/search.html
__________________________________________
 
Hehe, I came across this issue only an hour later. I was wondering if
there were any circumstances where the Global would lose it's value and
a bit of searching revealed that it can happen quite easily unless you
are careful with error handling (which I'm not) or creating an MDE
(which I'm not).

I have decided to take the "easy" option and have a hidden form. And
while I'm there I've turned it into a variable viewer and made it
visible during development.
 
sime said:
Hello

When my database opens, I use Autoexec to run a function. In that
function I want to instantiate a class and have that instance remain
accessible for the whole session.

Specifically I am using the class to make variables efficiently
available to any other code.

I can do this with a form that hides itself - is that the only way to
do this? It seems a bit silly, but hey if that's the way I should do it
I won't complain. :-)

Thanks
Simon

I might be missing something, but what about instantiating the class at
the top of the module in which the function is called? This assumes the
function is in a standard module.

Module MyMod
============
Option Compare Database
Option Explicit

Set TheClass = New MyClass
------------------------------
Function AutoexecFunction()
blah blah blah
End Function

Don't forget to Set TheClass = Nothing before you close everything up.
 
Smartin said:
I might be missing something, but what about instantiating the class
at the top of the module in which the function is called? This
assumes the function is in a standard module.

Module MyMod
============
Option Compare Database
Option Explicit

Set TheClass = New MyClass
------------------------------
Function AutoexecFunction()
blah blah blah
End Function

Don't forget to Set TheClass = Nothing before you close everything up.

Won't work. Executable statements must be enclosed in procedures; they
can't just sit at the top of a module. And if they could, what event
would cause them to be executed?
 
Dirk said:
Won't work. Executable statements must be enclosed in procedures; they
can't just sit at the top of a module. And if they could, what event
would cause them to be executed?

I thought I was doing something similar at work, but I will check the
code tomorrow to be sure and clarify or withdraw my proposition. Thanks
for the heads-up.
 
Smartin said:
I thought I was doing something similar at work, but I will check the
code tomorrow to be sure and clarify or withdraw my proposition. Thanks
for the heads-up.

My error, the declaration I am using is actually

Option Compare Database
Option Explicit

Public TheClass As New MyClass
 
That is in a normal module I am guessing. Won't "TheClass" die once the
code finishes executing?
 
sime said:
That is in a normal module I am guessing. Won't "TheClass" die once the
code finishes executing?

Yes, the declaration is in a normal module. Without meaning to be
argumentative, explain when should object TheClass die? The module does
not "close". It merely exists, and no code is fired to instantiate the
object. In better days I could probably have given a better explanation.
I hope this makes sense.

I will look into this a little further to be sure, but AFAICT the
instantiation of the class persists as long as the application is open.

Kind Regards,
 
Smartin said:
Yes, the declaration is in a normal module. Without meaning to be
argumentative, explain when should object TheClass die? The module does
not "close". It merely exists, and no code is fired to instantiate the
object. In better days I could probably have given a better explanation.
I hope this makes sense.

I will look into this a little further to be sure, but AFAICT the
instantiation of the class persists as long as the application is open.

Kind Regards,

Just to follow up and (hopefully) clarify, a publicly declared object is
accessible to the application for the life of the application. Unless,
of course, you set the object to Nothing.

Think of a publicly declared variable. It doesn't go away even though
the code asking for it is in another class/form/module.

Getting off topic somewhat, I would be interested to hear comments on
the virtues and pitfalls of using a class vs. a collection of variables
and functions in a module.

Personally, when I have a group of processes I want to apply to a
"thing" I like to create a class for it. I can swiftly reuse the code if
I need to use the "thing" in another application -- I simply drop in its
class module.

In the long run I find it is much easier to have the thing's methods and
properties on hand by typing a dot, rather than try to recall what Subs
and Functions are available. Plus, if I want to have multiple "things"
at the same time, a class makes this a snap.

For instance one "thing" I've been reusing quite a bit lately is
basically a text container I use to build up email messages in Access.
VBA and A97 do not provide a very robust collection of text manipulation
features, so I built functionality into the class like search and
replace, a tabulation mechanism for aligning columns of data, append,
automatic insertion of CrLf, etc. This reduces the amount of code I have
to write later -- and cleans up the code considerably.

HTH
 
sime said:
OOP is quite cool of course. Encapsulation and modulation.

Regarding Global/Public variables, I found I was losing the values I'd
assigned. The reason for these are better described by others (see
link). Maybe you could comment on the difference in your approach.
http://groups.google.com.au/groups?...81&as_maxd=27&as_maxm=1&as_maxy=2006&safe=off

.s

A cursory examination of those posts reveals the not-so-surprising
finding that a run-time error will cause values to be lost. Of course if
the program crashes, everything goes kaput.

There seem to be conflicting statements regarding whether this applies
to any error vs. only unhandled errors. My thinking is it's only the
latter. Pressing Cancel on certain forms raises an error that we can
trap. I can't recall having a problem with this scenario, with objects
or variables.

The technique of caching data on a hidden form is one I've heard before,
though I've never tried it myself. Since a form is just a special kind
of object, I wonder if it's any different than using your own class.
 
Smartin said:
The technique of caching data on a hidden form is one I've heard
before, though I've never tried it myself. Since a form is just a
special kind of object, I wonder if it's any different than using
your own class.

It is. Even if the VB project is reset due to an error, controls on
open forms -- even unbound controls on unbound forms -- retain their
values. Class objects declared in VBA code do not.
 
Dirk said:
It is. Even if the VB project is reset due to an error, controls on
open forms -- even unbound controls on unbound forms -- retain their
values. Class objects declared in VBA code do not.

Good information. Thank you.
 
Dirk said:
It is. Even if the VB project is reset due to an error, controls on
open forms -- even unbound controls on unbound forms -- retain their
values. Class objects declared in VBA code do not.

Might have a quibble here, after an experience today.

At work we have an A97 MDB that uses a class to store values from an
unbound form (the "search" form). The search form is called from a
button on the main UI and triggers a query to filter the recordset of
the main UI.

Today I (quite by accident) canceled the query in progress and the
application reset, expressing "cancel was pressed" (I didn't note the
error number). All forms closed, dropping me to the main database window.

Surprisingly, when I launched the main UI form again and called up the
search form, the object's properties were retained.

I will double check, but I believe the search form closes before the
query is launched. This being the case, doesn't that imply the class
object retained its values in spite of the error?
 
Smartin said:
Might have a quibble here, after an experience today.

At work we have an A97 MDB that uses a class to store values from an
unbound form (the "search" form). The search form is called from a
button on the main UI and triggers a query to filter the recordset of
the main UI.

Today I (quite by accident) canceled the query in progress and the
application reset, expressing "cancel was pressed" (I didn't note the
error number). All forms closed, dropping me to the main database
window.

Surprisingly, when I launched the main UI form again and called up the
search form, the object's properties were retained.

I will double check, but I believe the search form closes before the
query is launched. This being the case, doesn't that imply the class
object retained its values in spite of the error?

Interesting. I'm skeptical of your conclusion, but I don't know enough
to challenge it. Despite the fact that all forms were closed, I don't
know if the VBA project was reset or not. The closing of all forms
isn't the normal response to pressing Ctrl+Break while a query is
running (if that's how you did it), so maybe your cancel action was
trapped by an error handler, which might take those steps without
actually resetting the project.

If the project *was* reset, I'd have to see what the class object is
doing. I can easily envision a class module that stores the currently
selected values in non-volatile storage -- in a table, or as custom
properties, for example -- and reloads them when the class is
initialized. So it sounds like your "quibble" is worth investigating,
but I'm still sticking to my original assertion.
 

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

Back
Top