Make instant of a Class persistent for whole session.

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
 
T

Tom Wickerath

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
__________________________________________
 
S

sime

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
 
T

Tom Wickerath

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
__________________________________________
 
S

sime

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.
 
D

Dirk Goldgar

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?
 
S

sime

That is in a normal module I am guessing. Won't "TheClass" die once the
code finishes executing?
 
D

Dirk Goldgar

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.
 
D

Dirk Goldgar

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

Top