They say a picture speaks a thousand words, so let's take a look at the VB call stack window:

This window shows you the procedure that we’re in (the top item), and the previous function calls that occurred to get there.
In other words, a call stack provides you with the path that was taken to get to where you are now.
Sadly, it is not normally possible to access the call stack in VBA (nor VB6). However, with our Global Error Handler, this is now a possibility...
ErrEx.CallStack gives you programmatic access to the VBA (or VB6) call stack details at runtime from within your global error handler.
The object returned from ErrEx.CallStack exposes two methods and six properties that relate directly to the call stack:
| .FirstLevel | (method): puts you at the top of the stack i.e. the procedure that caused the error |
| .NextLevel | (method): moves you to the next stack level, returns False if at the end of stack |
| .ProcedureName | (read-only property): returns the current stack item procedure name, as a string |
| .ModuleName | (read-only property): returns the current stack item module name, as a string |
| .ProjectName | (read-only property): returns the current stack item project name, as a string |
| .LineNumber | (read-only property): returns the current stack item source code line number - see QuickStart: Automatic line numbering |
| .LineCode | (read-only property): returns the current stack item source code line - see QuickStart: Automatic line numbering |
| .HasActiveErrorHandler (v1.3+) | (read-only property): indicates whether the procedure has an active error handler (On Error Goto X, or On Error Resume Next) or not. This is useful for logging propagating errors - see QuickStart: Error Propagation |
Furthermore, the ErrEx.CallStack class also exposes the VariablesInspector method which returns a class object for enumerating through the local variables that have been declared in the procedure at the current stack level.
Let's look at a way of logging the call stack to a log file (as seen earlier in QuickStart: Enabling and disabling):
Public Sub LogErrorToFile()
Dim FileNum As Long
Dim LogLine As String
On Error Resume Next ' If this procedure fails, something fairly major has gone wrong.
FileNum = FreeFile
Open "C:\ErrorLog.txt" For Append Access Write Lock Write As FileNum
Print #FileNum, Now() & " - " & CStr(ErrEx.Number) & " - " & CStr(ErrEx.Description)
'We will seperate the call stack onto seperate lines in the log
With ErrEx.CallStack
Do
Print #FileNum, " --> " & .ProjectName & "." & _
.ModuleName & "." & _
.ProcedureName & ", " & _
"#" & .LineNumber & ", " & _
.LineCode & vbCrLf
Loop While .NextLevel
End With
Close FileNum
End Sub
The above Do-loop is iterating through the call stack, logging to a file - outputting like this:
27/08/2008 12:30:00 - 11 - Division by zero
--> MyVBAProject.Module1.FnC, #1, Debug.Print 1 / 0
--> MyVBAProject.Module1.FnB, #2, Call FnC
--> MyVBAProject.Module1.FnA, #2, Call FnB
Take a look at the
VariablesInspector guide
(VBA only) where we enhance this logging further to include a dump of all the variables at each procedure stack level.