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?
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