Access Cookbook - Ken Getz [144]
To incorporate this sort of profiling into your own applications, follow these steps:
Import the module basProfiler into your application. This module includes all the procedures needed to initialize and use the profile stack.
Insert a call to acbProInitCallStack into code that's executed when your application starts up. In the Solution in Recipe 7.2, you might have gotten by without calling the initialization routine. In this situation, however, you must call acbProInitCallStack each time you want to profile your code, or the profile stack will not work correctly. To call acbProInitCallStack, you must pass it three parameters, all of which are logical values (True or False). Table 7-2 lists the question answered by each of the parameters.
The procedure initializes some global variables and, if you're writing to a log file, writes a log header to the file. A typical call to acbProInitCallStack might look like this:
acbProInitCallStack False, True, True
Table 7-2. Parameters for acbProInitCallStack
Parameter name
Usage
blnDisplay
Display message box if an error occurs?
blnLog
Write to a log file or just track items in an array in memory?
blnTimeStamp
If writing to the log file, also write out time values?
For each procedure in your application, place a call to acbProPushStack as the first statement. This procedure places the value it's passed on the top of the stack, along with the current time. As the single argument for each call, pass the name of the current procedure. Our example places a pair of parentheses after function names and nothing after subroutine names, as a matter of style. As the last line in each procedure, add a call to acbProPopStack, which will remove the current name from the top of the stack and record the current time.
You can retrieve the name of the currently executing procedure at any time by calling the acbProCurrentProc function. This function looks at the top of the stack and returns the string it finds there.
To review the outcome of your logging, view the file LOGFILE.TXT (in your Access directory) in any text editor. If you followed the previous steps carefully, you should see matching entry and exit points for every routine. Nested levels are indented in the printout, and entry and exit points are marked differently (entry points with a "+" and exit points with a "-").
Discussion
The module you imported from 07-03.MDB, basProfiler, includes all the code that maintains the profiler. There are five public entry points to the module, as shown in Table 7-3.
Table 7-3. The five entry points into basProfiler
Procedure name
Purpose
Parameters
acbProInitStack
Initialize the profile stack.
acbProPushStack
Add an item to the profile stack.
A string to push
acbProPopStack
Remove an item from the profile stack.
acbProCurrentProc
Retrieve the name of the current procedure.
acbProLogString
Add any string to the log file.
A string to log
In general, the profiler works almost exactly like the simpler procedure stack shown in the Solution in Recipe 7.2. As a matter of fact, the code for this solution was written first and was then stripped down for use in the simpler example. This example includes the code necessary to write to the file on disk as well as to gather timing information. The next few paragraphs outline the major differences and how they work.
Whereas the Solution in Recipe 7.2 used a simple array of strings to hold the stack information, the profiler also needs to store starting and ending times for each routine. To create the stack, it uses an array of a user-defined type, acbStack, which is defined as follows:
Type acbStack
strItem As String
lngStart As Long
lngEnd As Long
End Type
Dim maStack(0 To acbcMaxStack) As acbStack
Access provides the Timer function, which returns the number of seconds since midnight, but this resolution won't give you enough information for measuring the duration of procedures in VBA. Another option is Windows's t function, which returns the number of milliseconds since