Identify the current Function / sub etc.

R

Rod

I am writing an error handler. All code has the error handler:

TheFactory_Error:

If Err.Number <> 0 Then
Call TheFactoryErrorHandler
Resume Next
End If

TheFactoryErrorHandler then manages the error.

I want to pass to TheFactoryErrorHandler the name of the function, sub, etc.
that has caused the error. How do I identify the name of the currently
running function to pass to the error handler (Call
TheFactoryErrorHandler(OffendingFunction) )?
 
A

Allen Browne

Unfortunately, VBA does not expose the name of the executing procedure like
that.

A simple solution is to use a utility such as MZ Tools from www.mztools.com
.. This nifty little utility gives you a toolbar button that drops the
complete error handler into your procedure with the click of a button. It is
compeletely configurable, and will at the procedure name to the generic
error handling function you want to call.

As far as the generic error handler goes, I suggest you actually log the
errors, because users can't tell you what happened. Here's one way to log
them, using a table in the Access database:
Error Handling in VBA
at:
http://allenbrowne.com/ser-23a.html
 
P

Paul Shapiro

I was never able to find a documented function that returned the name of the
currently executing routine in Access, at least through version 2003. I use
a private module-wide constant to pass the module name into my error-logging
routine, but I never found anything better than copying and pasting the
routine name into the error-logging function call.
 
S

Stuart McCall

I was never able to find a documented function that returned the name of
the currently executing routine in Access, at least through version 2003. I
use a private module-wide constant to pass the module name into my
error-logging routine, but I never found anything better than copying and
pasting the routine name into the error-logging function call.

Application.CodeContextObject ??
 
S

Stuart McCall

Stuart McCall said:
Application.CodeContextObject ??

Sorry - hit 'send' too soon. I meant to say that the above could replace
your module-wide constant.
 
A

Allen Browne

CodeContextObject may or may not give you what you expect. It refers to the
object (form/report) that triggered the event. For error handling, I think
you need the name of the module containing the procedure that failed, not
the name of the object that called the failing code.

Say you have a standard module named Module1, with a function like this:
Function TestCCO()
Debug.Print Application.CodeContextObject.Name
End Function
Test in the Immediate Window: it fails with error 7955:
There is no current code context object.

Then place a command button on Form1, with this code:
Private Sub Command1_Click()
Call TestCCO
End Sub
This time the code does not fail, but neither does it report Module1. It
reports Form1, since that's the current code context object from which the
call was made. It's not the module containing the procedure that failed.

Years ago, I briefly thought I could use:
Me.Module.Name
until I realised that failed in an MDE.

So now I do what Paul does: use a private constant at the top of every
module (the same name in each module.) This way, we can cut'n'paste code
between modules without needing to make any changes, and the relevant
constant gets passed to the generic error handler.
 
S

Stuart McCall

Inline comments:

Allen Browne said:
CodeContextObject may or may not give you what you expect. It refers to
the object (form/report) that triggered the event. For error handling, I
think you need the name of the module containing the procedure that
failed, not the name of the object that called the failing code.

Say you have a standard module named Module1, with a function like this:
Function TestCCO()
Debug.Print Application.CodeContextObject.Name
End Function
Test in the Immediate Window: it fails with error 7955:
There is no current code context object.

Then place a command button on Form1, with this code:
Private Sub Command1_Click()
Call TestCCO
End Sub
This time the code does not fail, but neither does it report Module1. It
reports Form1, since that's the current code context object from which the
call was made. It's not the module containing the procedure that failed.

Ah. So it's nothing more than an adjunct to Screen.ActiveWhatever. Hadn't
realised that.
Years ago, I briefly thought I could use:
Me.Module.Name
until I realised that failed in an MDE.

So now I do what Paul does: use a private constant at the top of every
module (the same name in each module.) This way, we can cut'n'paste code
between modules without needing to make any changes, and the relevant
constant gets passed to the generic error handler.

I use a slightly different approach. I develop with no error handling, apart
from specialist cases which are necessary for correct operation. Then when
I'm ready to release, I use an add-in which goes through all the modules and
inserts error-trapping code where there is none. The generated code calls a
generic handler/logger and passes the routine name (the name is easily
parsed out using Module.ProcOfLine).
 

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