Know which sub is calling the target function?

Hello,

I have zillions of functions / subs in multiple vba module. I wrote a function (functionA) moths back and I know which module the function lives in. the issue is I am not sure which sub or function is calling my functionA – I really want to know which specific function is calling functionA. Is there a way to know it? Whichever way it permits me? Because I need to go to that caller function and make changes….any ideas?
I am confused.

thank you
RayneAsked:
Who is Participating?
 
aikimarkConnect With a Mentor Commented:
Having gone this far, I now realize that I've probably reinvented the push and pop functionality in the linked text.  Here's the example with a pop.
Option Explicit
Dim LastRtn As New Collection

Sub a(): LastRtn.Add "a"
    Dim vItem As Variant
    Debug.Print LastRtn.Count
    For Each vItem In LastRtn
        Debug.Print vItem
    Next
Call RemoveLast("a"): End Sub

Sub b(): LastRtn.Add "b"
    c
Call RemoveLast("b"): End Sub

Sub c(): LastRtn.Add "c"
    Debug.Print d
Call RemoveLast("c"): End Sub

Function d() As String: LastRtn.Add "d"
    a
    d = "Done"
Call RemoveLast("d"): End Function

Sub RemoveLast(parmRtnName)
    Dim lngLoop As Long
    For lngLoop = LastRtn.Count To 1 Step -1
        If LastRtn(lngLoop) = parmRtnName Then
            LastRtn.Remove lngLoop
            Exit For
        End If
    Next
End Sub

Open in new window


Note: any Exit Sub or Exit Function statements would also need to tweaked

Example:
Call RemoveLast("d"): Exit Function

Open in new window

0
 
Martin LissOlder than dirtCommented:
Is this a one-time situation? In other words are you trying to debug a problem?

If not then one thing you could do would be to add a parameter to functionA and pass the name of the calling function from each of the procedures that call functionA.
0
 
RayneAuthor Commented:
Something like ....

Option Explicit

Function myCallerFunction()
'Debug.Print Application.Caller.Name
Call callingThis

End Function




Function callingThis()

Dim dm As Variant

dm = Application.Caller.Parent.Parent.Name
' dm basically stores the string [myCallerFunction]

MsgBox "the caller is " & dm

End Function
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
RayneAuthor Commented:
still cant get it to work
0
 
Martin LissOlder than dirtCommented:
Before someone beats me to it :) if you are debugging you could add a breakpoint at the first line in functionA and then use Debug to look at the call stack. For more on debugging take a look at my article, most of which applies to VBA.
0
 
RayneAuthor Commented:
The issue is I am not sure which function or sub is calling FunctionA, so how it can be done ...
0
 
Martin LissOlder than dirtCommented:
Again let me ask. Are you having a problem that you're trying to debug?
0
 
Martin LissConnect With a Mentor Older than dirtCommented:
I'm going to assume you are trying to debug a problem and you don't know how to use Debug, so here's what you do.

Go to functionA and click in the left had margin next to the first line (the Private Function line) and click the margin. That will create a little red circle which indicates that a breakpoint has been set.

Run the program and when the code gets to the breakpoint go to View|Call stack and there you will see the procedures that led to you getting to the breakpoint
0
 
aikimarkCommented:
You could get by with this cheap solution.  If I start the code with either routine b or c, there will be two items in the collection with the last item being "a".  The item immediately prior will be the calling routine.
Option Explicit
Dim LastRtn As New Collection

Sub a(): LastRtn.Add "a"
Stop
End Sub

Sub b(): LastRtn.Add "b"
    a
End Sub

Sub c(): LastRtn.Add "c"
    a
End Sub

Open in new window

0
 
aikimarkCommented:
Just to be sure, I tried this with a function in the mix.
Option Explicit
Dim LastRtn As New Collection

Sub a(): LastRtn.Add "a"
    Dim vItem As Variant
    Debug.Print LastRtn.Count
    For Each vItem In LastRtn
        Debug.Print vItem
    Next
End Sub

Sub b(): LastRtn.Add "b"
    c
End Sub

Sub c(): LastRtn.Add "c"
    Debug.Print d
End Sub

Function d() As String: LastRtn.Add "d"
    a
    d = "Done"
End Function

Open in new window


When I start the execution with the b routine, the Immediate window contains these results
 4 
b
c
d
a
Done

Open in new window

0
 
aikimarkCommented:
Since you are working with multiple modules, you'd probably prefix the name of the routine with the name of the module/form.
Examples:
LastRtn.Add "module1.d"
LastRtn.Add "module1 d"
LastRtn.Add "module1-d"
LastRtn.Add "module1^d"

Open in new window

You would want to make the parsing easier by using a delimiter that couldn't be used as part of the module name.
0
 
RayneAuthor Commented:
Hello Martin & Aikimark,

First of all, sorry for the delayed reply, I was away from my machine. I greatly appreciate the time and effort all of you gave to help me out. Thank you for your diligence and effort to make this issue as clear as possible :)

Respectfully,
Rayne
0
 
Martin LissOlder than dirtCommented:
You're welcome and I'm glad I was able to help.

Marty - MVP 2009 to 2012
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.