global array vs dlookup (1 Viewer)

benjamin.weizmann

Registered User.
Local time
Today, 14:14
Joined
Aug 30, 2016
Messages
78
hi :)
I do have a table with technical parameters which defined by the admin

Most of my dlookup functions are to this table and I wonder what is the best way to retrieve information for it (memory space and run time aspects)
maybe to stay dlookup way like it's now, or to pass all this table to array which be loaded when logging in, and contact to array directly when it's needed?

thanks
Ben
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 05:14
Joined
May 7, 2009
Messages
19,227
i prefer DLookup against Public variables.
public variables tend to be destroyed whenever a runtime error occurs.
besides not all the variables will be used frequently at all time.
they'll be sitting there wasting memory.
speed, negligible.
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 22:14
Joined
Jul 9, 2003
Messages
16,269
I avoid Dlookup. Two reasons. I dimly recall reading somewhere that Dlookup is inefficient.


I just don't like them, I find them complicated.
Not sure this is a valid reason!



Sent from my SM-G925F using Tapatalk
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 16:14
Joined
Feb 28, 2001
Messages
27,128
Benjamin,

Rather than a global array, you could create a dictionary object although how you name things might be problematic.

Read up on the dictionary object by looking at this reference and browsing around in the examples of how to create, populate, use, and destroy such objects.

https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/dictionary-object

As for the case of a global array, this object also exists in memory and has to be rebuilt at each app restart.

Arnel is correct that public variables tend to be destroyed after a run-time error, but that isn't always the case. The trick is that every form needs an OnError event to trap an error not handled from individual event codes. Then you can still pop up a message box and force the form to exit - but since YOU handled the error, the globals would be preserved. Here's why:

Every subroutine and function COULD have error trapping code in it. That would almost entirely eliminate "global destruction." But sometimes that's not practical. You can trap things where you know what to do about the error, perhaps, but it quickly gets burdensome to fully establish traps everywhere.

Lots of people take the other approach and trap nothing. That is because they know that Access will catch the trap. And that is actually quite true. But... Access isn't kind to you when you feed it a load of trap.

A trap handler exists as an element of what is called a "Call Frame." When you call something as a subroutine, a new call frame is created. All variables declared locally in what you call are instantiated in that frame (as part of the stack). You can see the call frame in a code/debug window because there is a menu-bar View option to show the call stack. When you declare an "ON ERROR <do something>" you are creating a trap handler. However, that exists ONLY on the call stack. If your subroutine returns to its caller, your trap handler is disestablished when its frame is collapsed by the EXIT SUB or whatever you use.

If you have several layers of calls, EACH layer can have its own handler and if you call something and then return from it, your handler for that layer is still in force when you return - no need to re-declare it.

But what if you have a layer that doesn't have a handler? What Windows does, and therefore what Access does, is they establish a rule that says if you don't have a handler, your current call frame is toast. They clean it up and return to your caller with an error signal. If the caller of the failing routine ALSO doesn't have a handler, IT gets collapsed on the stack - much like a string of dominoes.

The collapse sequence stops when a handler accepts the trap. IF the handler that accepts the trap is within Access itself (rather than one of yours) then you get the popup for which one of the options is RESET. At the moment you take the reset option, you just blew away your global context. That's because to Access, YOUR CODE is a subroutine for which its call context just got blown away.

Which is why I told you to have a form-based error handler to intercept the trap BEFORE it gets to the Access "Last Chance" error handler. That would protect your globals.

For a personal project, taking the Access handler isn't such a big deal. But for a project in full production status, you really want to stop that if you can, and you want your code to be stable even in the face of adversity. Which is why extra care is needed if you are going to play around with global variables.

NOTE: It is NOT TOTALLY WRONG to use global variables despite the lively thread on whether global variables are a good or a bad thing. After all, it is your project, not ours. However, it IS suicidal to use globals without assuring some level of error protection.
 

benjamin.weizmann

Registered User.
Local time
Today, 14:14
Joined
Aug 30, 2016
Messages
78
Benjamin,

Rather than a global array, you could create a dictionary object although how you name things might be problematic.

Read up on the dictionary object by looking at this reference and browsing around in the examples of how to create, populate, use, and destroy such objects.

https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/dictionary-object

As for the case of a global array, this object also exists in memory and has to be rebuilt at each app restart.

Arnel is correct that public variables tend to be destroyed after a run-time error, but that isn't always the case. The trick is that every form needs an OnError event to trap an error not handled from individual event codes. Then you can still pop up a message box and force the form to exit - but since YOU handled the error, the globals would be preserved. Here's why:

Every subroutine and function COULD have error trapping code in it. That would almost entirely eliminate "global destruction." But sometimes that's not practical. You can trap things where you know what to do about the error, perhaps, but it quickly gets burdensome to fully establish traps everywhere.

Lots of people take the other approach and trap nothing. That is because they know that Access will catch the trap. And that is actually quite true. But... Access isn't kind to you when you feed it a load of trap.

A trap handler exists as an element of what is called a "Call Frame." When you call something as a subroutine, a new call frame is created. All variables declared locally in what you call are instantiated in that frame (as part of the stack). You can see the call frame in a code/debug window because there is a menu-bar View option to show the call stack. When you declare an "ON ERROR <do something>" you are creating a trap handler. However, that exists ONLY on the call stack. If your subroutine returns to its caller, your trap handler is disestablished when its frame is collapsed by the EXIT SUB or whatever you use.

If you have several layers of calls, EACH layer can have its own handler and if you call something and then return from it, your handler for that layer is still in force when you return - no need to re-declare it.

But what if you have a layer that doesn't have a handler? What Windows does, and therefore what Access does, is they establish a rule that says if you don't have a handler, your current call frame is toast. They clean it up and return to your caller with an error signal. If the caller of the failing routine ALSO doesn't have a handler, IT gets collapsed on the stack - much like a string of dominoes.

The collapse sequence stops when a handler accepts the trap. IF the handler that accepts the trap is within Access itself (rather than one of yours) then you get the popup for which one of the options is RESET. At the moment you take the reset option, you just blew away your global context. That's because to Access, YOUR CODE is a subroutine for which its call context just got blown away.

Which is why I told you to have a form-based error handler to intercept the trap BEFORE it gets to the Access "Last Chance" error handler. That would protect your globals.

For a personal project, taking the Access handler isn't such a big deal. But for a project in full production status, you really want to stop that if you can, and you want your code to be stable even in the face of adversity. Which is why extra care is needed if you are going to play around with global variables.

NOTE: It is NOT TOTALLY WRONG to use global variables despite the lively thread on whether global variables are a good or a bad thing. After all, it is your project, not ours. However, it IS suicidal to use globals without assuring some level of error protection.

I would get marriage with u with his response , first thanks u
second ...with my English and little knowledge of access I would read it 10000 time
I try do it :)
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 16:14
Joined
Feb 28, 2001
Messages
27,128
You are welcome. And my wife would probably object to the "marriage" part. But thanks any way.
;)
 

Mark_

Longboard on the internet
Local time
Today, 14:14
Joined
Sep 12, 2017
Messages
2,111
hi :)
I do have a table with technical parameters which defined by the admin

Most of my dlookup functions are to this table and I wonder what is the best way to retrieve information for it (memory space and run time aspects)
maybe to stay dlookup way like it's now, or to pass all this table to array which be loaded when logging in, and contact to array directly when it's needed?

thanks
Ben

Can the data in the table change while your app is running?

IF yes, use DLookup as you will always get the current value.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 16:14
Joined
Feb 28, 2001
Messages
27,128
I do have a table with technical parameters which defined by the admin

Most of my dlookup functions are to this table and I wonder what is the best way to retrieve information for it (memory space and run time aspects)
maybe to stay dlookup way like it's now, or to pass all this table to array which be loaded when logging in, and contact to array directly when it's needed?

Overlooked this one...

If this is a shared application, putting things in an array is wrong if there is ANY CHANCE that the underlying table of tech parameters could ever be updated while someone is in the database AND that update is supposed to be visible.

Putting table contents into an array or a dictionary object, either way, is taking a static snapshot of the table at the time you create the object. If you want changes visible, then the table MUST be in the shared back end AND you MUST use either DLookup or some type of query / recordset operation to keep up to date, because the memory copies of that table DO NOT reside in the back end. They reside in the FRONT END (where Access itself and your workspace reside). And the FE is not shared. Only the BE is shared. Only the BE can hold something that everyone could see.
 

Users who are viewing this thread

Top Bottom