excelvba

NavigateArrow doesn't go to all dependent cells


In Excel VBA, I'm trying to use NavigateArrow to iterate through all of the cells whose formulas are dependent certain cell.

First, here's how I have the sheets set up:

On Sheet1, cell A1, when I click Formulas > Formula Auditing > Trace Dependents, it works as expected:

I want to iterate through all of those dependent cells in VBA. Here's what I've done:

Sub TraceAllDependents2()
    Const NAVIGATE_DEPENDENTS As Boolean = False
    Dim rgTraceDep As Range, rgDepRange As Range
    Dim rgBeforeNav As Range, rgAfterNav As Range
    Dim iArrowCounter As Long
    
    '===========================================================================
    'SET THE CELL TO TRACE HERE:
    Set rgTraceDep = ThisWorkbook.Worksheets("Sheet1").Range("A1")
    '===========================================================================
    
    iArrowCounter = 0 'init. Arrows are 1-based.
    Set rgBeforeNav = rgTraceDep
    rgTraceDep.ShowDependents
    
    Do 'loop through arrows:
        iArrowCounter = iArrowCounter + 1
        rgTraceDep.NavigateArrow NAVIGATE_DEPENDENTS, iArrowCounter: DoEvents
        Set rgAfterNav = ActiveCell
        If rgBeforeNav.Address(External:=True) <> rgAfterNav.Address(External:=True) Then
            'we followed an arrow:
            Debug.Print CellAddressWithSheetname(rgAfterNav.Address(External:=True)), "Arrow #" & iArrowCounter
        Else
            'this cell does NOT have any more arrows.
            Exit Do
        End If
    Loop 'until done with arrows.

    
    rgTraceDep.Parent.ClearArrows
End Sub

Function CellAddressWithSheetname(external_address As String) As String
    Dim strAddrSht As String
    strAddrSht = Replace(external_address, ThisWorkbook.Name, "")
    strAddrSht = Replace(strAddrSht, "[]", "")
    CellAddressWithSheetname = strAddrSht
End Function

Instead of iterating through all 6 dependent cells, it only goes through 3 of them:

Sheet2!$A$2            Arrow #1
Sheet1!$E$1            Arrow #2
Sheet1!$B$1            Arrow #3

What am I doing wrong?


Solution

  • As can be seen from the method signature

    expression.NavigateArrow(TowardPrecedent, ArrowNumber, LinkNumber)

    in addition to the ArrowNumber, there is a LinkNumber. The arrow pointing away from the current worksheet, i.e., the one pointing to Sheet2 and Sheet3 (and which is represented as Arrow 1), also requires the LinkNumber. In debug, is showed only Sheet2!$A$2, because that would be Arrow 1 and Link 1. With the remaining links number, all the others are also visible.

    A second loop is therefore needed to increment the links. In the following code, the second loop waits for an error message about a non-existent link, but the code can be optimized:

    Sub TraceAllDependents2()
        Const NAVIGATE_DEPENDENTS As Boolean = False
        Dim rgTraceDep As Range, rgDepRange As Range
        Dim rgBeforeNav As Range, rgAfterNav As Range
        Dim iArrowCounter As Long
        
        '===========================================================================
        'SET THE CELL TO TRACE HERE:
        Set rgTraceDep = ThisWorkbook.Worksheets("Sheet1").Range("A1")
        '===========================================================================
        
        iArrowCounter = 0 'init. Arrows are 1-based.
        Set rgBeforeNav = rgTraceDep
        rgTraceDep.ShowDependents
        
        Do 'loop through arrows:
            iArrowCounter = iArrowCounter + 1
            iLink = 1
            rgTraceDep.NavigateArrow NAVIGATE_DEPENDENTS, iArrowCounter, 1: DoEvents
            Set rgAfterNav = ActiveCell
            If rgBeforeNav.Address(External:=True) <> rgAfterNav.Address(External:=True) Then
                'we followed an arrow:
                Debug.Print CellAddressWithSheetname(rgAfterNav.Address(External:=True)), "Arrow #" & iArrowCounter
                Do
                    On Error Resume Next
                    iLink = iLink + 1
                    rgTraceDep.NavigateArrow NAVIGATE_DEPENDENTS, iArrowCounter, iLink: DoEvents
                    If Err.Number = 0 Then
                        Set rgAfterNav = ActiveCell
                        Debug.Print CellAddressWithSheetname(rgAfterNav.Address(External:=True)), "Arrow #" & iArrowCounter, "Link #" & iLink
                    Else
                        Exit Do
                    End If
                Loop Until Err.Number <> 0
            Else
                'this cell does NOT have any more arrows.
                Exit Do
            End If
        Loop 'until done with arrows.
    
        
        rgTraceDep.Parent.ClearArrows
    End Sub
    

    The code print following dependents:

    
    Sheet2!$A$2   Arrow #1
    Sheet3!$A$3   Arrow #1      Link #2
    Sheet2!$E$2   Arrow #1      Link #3
    Sheet3!$E$3   Arrow #1      Link #4
    Sheet1!$E$1   Arrow #2
    Sheet1!$B$1   Arrow #3