Access Cookbook - Ken Getz [145]
Public Declare Function timeGetTime _
Lib "Kernel32" ( ) As Long
The code in basTestProfiler also uses timeGetTime in the Wait subroutine. This procedure does nothing but wait for the requested number of milliseconds, calling DoEvents inside the loop and giving Windows time to do its work:
Public Sub Wait (intWait As Integer)
Dim lngStart As Long
lngStart = timeGetTime( )
Do While timeGetTime( ) < lngStart + intWait
DoEvents
Loop
End Sub
The code in basProfiler opens and closes the output file each time it needs to write a piece of information. This slows down your application, but it ensures that if your machine crashes for some reason, your log file will always be current. Although you'll never directly call this routine, if you've never used Access to write directly to a text file you may find it interesting to see how it does its work.
The acbProWriteToLog procedure first checks to see if an error has ever occurred in the logging mechanism (that is, if mfLogErrorOccurred has been set to True). If so, it doesn't try to write anything to the file, because something may be wrong with the disk. If not, it gets a free file handle, opens the log file for appending, writes the item to the file, and then closes it. The following is the source code for the acbProWriteToLog routine:
Private Sub acbProWriteToLog (strItem As String)
Dim intFile As Integer
On Error GoTo HandleErr
' If an error has EVER occurred in this session,
' just get out of here.
If mfLogErrorOccurred Then Exit Sub
intFile = FreeFile
Open acbcLogFile For Append As intFile
Print #intFile, strItem
Close #intFile
ExitHere:
Exit Sub
HandleErr:
mfLogErrorOccurred = True
MsgBox Err & ": " & Err.Description, , "Writing to Log"
Resume ExitHere
End Sub
As in the Solution in Recipe 7.2, you'll find that for the procedure stack profiler mechanism to be of any value, you must be conscientious about the placement of your calls to acbProPushStack and acbProPopStack. If you have multiple exit points from routines, this is a good time to try to consolidate them. If you can't, you'll need to make sure that you've placed a call to acbProPopStack before every exit point in each procedure.
If you attempt to decipher the log file, you'll notice that the elapsed time for each procedure must also include any procedures it happens to call, as in the example of A calling B, which calls C, which calls D. The elapsed time for function A was 1,702 ms. That's the time that elapsed between the calls to acbProPushStack and acbProPopStack in function A, including the time it took to run all the calls to B, C, and D. This isn't necessarily a problem, nor is it wrong, but you should be aware that there's no way to "stop the clock" while in subordinate procedures.
The code for the profiler includes another public entry point, acbProLogString. The profiler doesn't actually call this procedure, but your own code can. Pass it a single string, and the profile will send that string to the log file for you. For example, the following code will append "This is a test" to the log file:
acbProLogString "This is a test"
7.4. Multitask Your VBA Code
Problem
If your VBA code includes a loop that runs for more than just a second or two, Access seems to come to a halt. You can't move the windows on the screen, and mouse-clicks inside Access are disregarded until your code has