Knowing the name of the current sub in code (1 Viewer)

747skipper

New member
Local time
Today, 15:18
Joined
Sep 30, 2019
Messages
13
OK a bit of a weird request, but does anyone know if I can obtain the name of the current sub or function at run time, in code?

I have a top level error handler to close a form and return to menu, acting as a back stop if an error I haven't allowed for occurs.
This covers several subs and functions and it would be really useful to know which one triggered it. (think line numbers in pre history)

I could declare a global variable and set it in each sub but I wondered if there is an easier way?

Thanks
 

isladogs

MVP / VIP
Local time
Today, 15:18
Joined
Jan 14, 2017
Messages
18,186
There is another way of doing this which I've used in several apps for some time
Its not 100% reliable. For example, it doesn't work in Form_Open events

1. Add the reference Microsoft Visual Basic for Applications Extensibility 5.3

2. In your error handler, add code like this:
Code:
strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description

For example:

Code:
Option Compare Database
Option Explicit

Dim strProc As String

Private Sub cmd1_Click()

On Error GoTo Err_Handler
    
    'raise error
    Err.Raise 91
    
Exit_Handler:
    Exit Sub
    
Err_Handler:
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description
    Resume Exit_Handler
End Sub

Private Sub cmd2_Click()
  
    On Error GoTo Err_Handler
              
    'raise error
    Dim N As Integer
    N = 3500 / 0   'error 11

   '  Err.Raise 11
    
Exit_Handler:
    Exit Sub
    
Err_Handler:
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description
    Resume Exit_Handler
End Sub

I've also experimented putting the strProc line immediately after the On Error line as well as in the error handler
 

jdraw

Super Moderator
Staff member
Local time
Today, 11:18
Joined
Jan 23, 2006
Messages
15,364
Colin,

Do you keep or have you tried a central logger file/table (centralized logging of errors.) that Pat mentioned in #18?
 

isladogs

MVP / VIP
Local time
Today, 15:18
Joined
Jan 14, 2017
Messages
18,186
Colin,

Do you keep or have you tried a central logger file/table (centralized logging of errors.) that Pat mentioned in #18?
Yes I have.
In fact, I first used the code in post #21 when I was setting up centralised error logging to a table.
The code also created an automatic email which was sent to me with full details of the error who/what/where/when etc together with Access & Windows versions in use
NOTE: The automated emails were sent 'silently' using CDO so end users weren't aware of it happening. However I made sure I had the agreement of my clients. They were able to opt out but none chose to do so
 

747skipper

New member
Local time
Today, 15:18
Joined
Sep 30, 2019
Messages
13
Wow what a lot of replies. Thank you all

@MajP
That's the sort of thing I wanted BUT when I call a sub and pass me.name it passes the form name not the sub name.

@KitaYama
Mz-Tools sounds good but I'm only doing odd jobs for a charity, I am no longer a professional programmer.

@MarkK
Thanks, Yes I follow your reasoning but I was trying to avoid having to code the name of the sub into each error handler.
I could just as well declare a global variable and set it in each sub.

@The_Doc_Man
Thank you for your full explanation. It makes great sense and explains why I can't take the lazy way out but need to code the name manually in each sub. I had hoped there was and object, like me.name in MajP's answer, which made the name of the sub available in code but it seems there isn't.

Thank you all
 

Gasman

Enthusiastic Amateur
Local time
Today, 15:18
Joined
Sep 21, 2011
Messages
14,044
There is another way of doing this which I've used in several apps for some time
Its not 100% reliable. For example, it doesn't work in Form_Open events

1. Add the reference Microsoft Visual Basic for Applications Extensibility 5.3

2. In your error handler, add code like this:
Code:
strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description

For example:

Code:
Option Compare Database
Option Explicit

Dim strProc As String

Private Sub cmd1_Click()

On Error GoTo Err_Handler
   
    'raise error
    Err.Raise 91
   
Exit_Handler:
    Exit Sub
   
Err_Handler:
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description
    Resume Exit_Handler
End Sub

Private Sub cmd2_Click()
 
    On Error GoTo Err_Handler
             
    'raise error
    Dim N As Integer
    N = 3500 / 0   'error 11

   '  Err.Raise 11
   
Exit_Handler:
    Exit Sub
   
Err_Handler:
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description
    Resume Exit_Handler
End Sub

I've also experimented putting the strProc line immediately after the On Error line as well as in the error handler
@isladogs
Colin, that works for me without that reference?
1652611983813.png


Code:
? Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
cmdAdd_Click
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 11:18
Joined
May 21, 2018
Messages
8,463
@MajP
That's the sort of thing I wanted BUT when I call a sub and pass me.name it passes the form name not the sub name.
NO that is not correct. It will pass whatever string you send it. I said to pass the form name and the name of the procedure. You must have done something wrong.
Call ErrorLog(Err.Description, Err.Number, Me.Name & " cmdClickMe_Click")
 

isladogs

MVP / VIP
Local time
Today, 15:18
Joined
Jan 14, 2017
Messages
18,186
@isladogs
Colin, that works for me without that reference?
View attachment 100533

Code:
? Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
cmdAdd_Click

Hi Paul
Thanks for confirming the code worked for you
I know it works in most cases despite many experienced developers stating here (and elsewhere) that it is impossible to get the name of the current procedure in code.

I'm surprised that worked without the reference but doing that in the Immediate window isn't the same as using it in error handling code.
Perhaps you could try again with error handling code similar to that I provided.
It may not be quite so reliable in that situation
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 11:18
Joined
Feb 19, 2002
Messages
42,970
Peter's code gets the procedure name and it is code you embed in your app so it is written in VBA so it is possible. I don't know if he uses the technique suggested by Colin or something different but it does seem to be possible. I'll try Colin's code later.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 10:18
Joined
Feb 28, 2001
Messages
26,999
@isladogs - Colin, I have a question. The original goal of this thread was to find out which line of code faulted using a generic routine. The example you showed appeared to be within an event routine. I accept that from that event routine you would be able to look for the line of code using the VBE references as you stated. However, if that event routine happens to not contain that handler, isn't it the case that an external handler won't see the location of the error because it is now out of scope?

I'm not questioning that it is possible for a local error routine to determine a specific line. I'm questioning the ability of a non-local routine to do it.

You could still do that lookup locally from the error handler and then call a generic logging/annunciation handler - but doesn't SOMETHING have to still be local at the time of the error in order to get that information?
 

Gasman

Enthusiastic Amateur
Local time
Today, 15:18
Joined
Sep 21, 2011
Messages
14,044
Hi Paul
Thanks for confirming the code worked for you
I know it works in most cases despite many experienced developers stating here (and elsewhere) that it is impossible to get the name of the current procedure in code.

I'm surprised that worked without the reference but doing that in the Immediate window isn't the same as using it in error handling code.
Perhaps you could try again with error handling code similar to that I provided.
It may not be quite so reliable in that situation
No, it still does?
1652631722713.png

1652631794159.png
 

isladogs

MVP / VIP
Local time
Today, 15:18
Joined
Jan 14, 2017
Messages
18,186
@The_Doc_Man
My interpretation of this thread was that the main goal was to find out the name of the current procedure using code.
That procedure name was then to be passed to a central error logging routine.
I did both of those many years ago

AFAIK, the procedure name can only be determined in the procedure itself
I tried to determine it as part of the central error logging routine to save a lot of repeated code . . . but was unsuccessful

So my generic error handling code in forms/reports consisted of:

Code:
Private Sub MyProcedureName()

On Error GoTo Err_Handler

    'code here
   
Exit_Handler:
    Exit Sub

Err_Handler:
    'create error message & log
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    PopulateErrorLog
    Resume Exit_Handler
   
End Sub

The PopulateErrorLog procedure is in a standard module and is used to log details of all errors to a table and send a 'silent' email to me for info/action

However. from experience I found that getting the procedure name in Form_Open events didn't work reliably so for those I used:

Code:
Private Sub Form_Open(Cancel As Integer)

On Error GoTo Err_Handler

'set information for error log
    strItemName = Me.Name
    SetNewObjectLogItems 'clear previously saved values from other forms/reports & set new
   
'other form open code here e.g. setup automatic form resizing

Exit_Handler:
    Exit Sub

Err_Handler:
    'create error message & log
    strProc = "Form_Open"
    PopulateErrorLog
    Resume Exit_Handler
   
End Sub

The process was a lot of work to setup a few years ago using A2010 BUT was VERY reliable for the intended purpose.
However, I've been unable to create a reliable example app in A365 which is why I haven't posted it.
Usually it works .... but not always.... and I haven't had time to determine why not.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 10:18
Joined
Feb 28, 2001
Messages
26,999
That answers my question. Thanks, Colin. (We actually agree - gotta be there to see what's there.)
 

KitaYama

Well-known member
Local time
Tomorrow, 00:18
Joined
Jan 6, 2022
Messages
1,489
@The_Doc_Man
My interpretation of this thread was that the main goal was to find out the name of the current procedure using code.
That procedure name was then to be passed to a central error logging routine.
I did both of those many years ago

AFAIK, the procedure name can only be determined in the procedure itself
I tried to determine it as part of the central error logging routine to save a lot of repeated code . . . but was unsuccessful

So my generic error handling code in forms/reports consisted of:

Code:
Private Sub MyProcedureName()

On Error GoTo Err_Handler

    'code here
  
Exit_Handler:
    Exit Sub

Err_Handler:
    'create error message & log
    strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
    PopulateErrorLog
    Resume Exit_Handler
  
End Sub

The PopulateErrorLog procedure is in a standard module and is used to log details of all errors to a table and send a 'silent' email to me for info/action

However. from experience I found that getting the procedure name in Form_Open events didn't work reliably so for those I used:

Code:
Private Sub Form_Open(Cancel As Integer)

On Error GoTo Err_Handler

'set information for error log
    strItemName = Me.Name
    SetNewObjectLogItems 'clear previously saved values from other forms/reports & set new
  
'other form open code here e.g. setup automatic form resizing

Exit_Handler:
    Exit Sub

Err_Handler:
    'create error message & log
    strProc = "Form_Open"
    PopulateErrorLog
    Resume Exit_Handler
  
End Sub

The process was a lot of work to setup a few years ago using A2010 BUT was VERY reliable for the intended purpose.
However, I've been unable to create a reliable example app in A365 which is why I haven't posted it.
Usually it works .... but not always.... and I haven't had time to determine why not.
@isladogs You're a star. I've been trying to do this for years, and everyone told me it's impossible. You made the impossible, possible.
Million thanks.

Anyhow, as a confirmation, your code works without the mentioned reference. Even from a sub and not immediate window.

1.png


Thanks again.
 

747skipper

New member
Local time
Today, 15:18
Joined
Sep 30, 2019
Messages
13
Thanks again Chaps,
@MajP reading your code more carefully I see the "& " cmdClickMe_Click"" which is just what I'm trying to avoid, since I will have to add a different version of this in every sub or function.

@isladogs (love the Lab)
I haven't tried it with the reference yet (because I have to look up how to get to the references option.
Without the reference it returns the name of the form.
I will try it later.

What I have found is this:
I defined an alternative function to replace "Call" passing it the name of the sub or function I wish to call and use CallByName to do the actual call. It doesn't give me a line number but it does tell me the name of the sub which crashed without my having to hard code it in every sub.
Of course it doesn't work for events but it should be fairly easy to work out that if I click something and it crashes that was the problem.


Public Function CallThis(FRM, This As String, Optional param As Variant, Optional RTN As Variant)
On Error GoTo ErrorHandler
If IsMissing(param) Then
result = CallByName(FRM, This, VbMethod)
Else
result = CallByName(FRM, This, VbMethod, param)
End If
CallThis = result
Exit Function

ErrorHandler:
MsgBox ("Error " & Err.Number & " " & Err.Description & " happened in sub " & This)
End Function


Please don't flame me if the layout doesn't match what you prefer, this isn't a real program just an illustration of a method.
It does handle returning the value from functions and could easily be extended if you call subs with more than one parameter.
 

sonic8

AWF VIP
Local time
Today, 16:18
Joined
Oct 27, 2015
Messages
998
There is another way of doing this which I've used in several apps for some time
[...]
Code:
strProc = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(Application.VBE.ActiveCodePane.TopLine, 0)
MsgBox "Error " & Err & " in procedure " & strProc & " :  " & vbCrLf & Err.Description
I tried your code by copying it to a form class module and also a to normal modules. - Unfortunately, it doesn't work either way. strProc is always an empty string.
 

Gasman

Enthusiastic Amateur
Local time
Today, 15:18
Joined
Sep 21, 2011
Messages
14,044
I tried your code by copying it to a form class module and also a to normal modules. - Unfortunately, it doesn't work either way. strProc is always an empty string.
Why did it work for me then, only tested in a form module, but even without the reference library?
 

Users who are viewing this thread

Top Bottom