Go Premium for a chance to win a PS4. Enter to Win


Excel Cell Precedents

Posted on 2010-08-15
Medium Priority
Last Modified: 2013-11-26
I am looking for code that shows how to get the precedent cells for a dependent cell containing a formula.  The catch is that the returned precedent cells MUST be in the order in which they appear in the dependent cell's formula.

I have seen and fiddled with plenty of code examples from all over the Internet that suggest using the NavigateArrow method.  However, in all such cases the precedent cells are returned in whatever seemingly random order Excel decides--NOT the order in which they appear in the formula.

My current workaround involves regular expression matching on the formula to parse out precedent cell references.  This gives me the precedent cells in the order I require.  However, the regex matching string is a bit unwieldy, and still misses some precedents.

I'm looking for a solution, or at least something that gets me close to it, in VBA or VB.NET.  Thanks.
Question by:macabacus
  • 4
  • 3
  • 2
  • +1

Expert Comment

ID: 33442315
LVL 50

Expert Comment

by:Dave Brett
ID: 33442400
Having played a fair bit with these techniques I would go the Regex route. What Regex are you using and what precedents is it missing?


That method raises the same issue that macabus wants to avoid



Author Comment

ID: 33442505
Thanks for replying.  Not exactly sure which precedents it's missing.  I suppose if I knew that, I would just fix the Regex pattern.  I get feedback from end users every so often that report what is essentially a problem with the Regex pattern, but they're not in positions to elaborate.

I actually use about 5 Regex patterns in what I'm trying to achieve (one to replace defined names with their RefersTo properties, one to pluck out the cell references, another to do some other stuff, etc.), but I consider these patterns proprietary and cannot, unfortunately, post them publicly here.

I assume that someone must have figured out a foolproof pattern for extracting cell references from formulas (after replacing defined names), which is the pattern I am primarily interested in, but I haven't come across it yet.  So, any help you can provide along these lines is appreciated.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 50

Accepted Solution

Dave Brett earned 2000 total points
ID: 33442987
Its an interesting - read very difficult - task.  I have spent several  hours on this, reworking the NavigateArrows method from http://www.mrexcel.com/forum/showthread.php?t=297888  significantly in conjunction with a replace formula method to produce a  sequence list on a new sheet

The code
- searches offsheet references first
- longer references first

Would be interested in your comments



Const StrDelim = "||-||"
Const wsWorking = "ArrayDump"
Const ZZ = "aaa|"
Sub test()
    Dim strFormula As String
    Dim strNew As String
    Dim strAddress As String
    Dim vArr
    Dim vExcelArr
    Dim vElem
    Dim X
    Dim lngCnt As Long
    Dim lngCnt2 As Long
    Dim LngCht3 As Long
    Dim ws As Worksheet

    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With

    If ActiveCell.HasFormula Then
        strAddress = ActiveCell.Formula
        strFormula = Replace(Replace(ActiveCell.Formula, "$", vbNullString), "'", vbNullString)
        vArr = Split(OnecellsPrecedents(ActiveCell), StrDelim)

        vExcelArr = Range([a1], Cells(UBound(vArr) + 1, "B"))

        For Each vElem In vArr
            If InStr(vElem, "!") = 0 Then
                vExcelArr(lngCnt + 1, 1) = ZZ & vArr(lngCnt)
                vExcelArr(lngCnt + 1, 1) = vArr(lngCnt)
            End If
            lngCnt = lngCnt + 1

        On Error Resume Next
        On Error GoTo 0

        Set ws = Sheets.Add
        ws.Name = wsWorking

        lngCnt2 = 0

        Range([a1], Cells(UBound(vArr) + 1, "A")) = vExcelArr
        Range([a1], Cells(UBound(vArr) + 1, "A")).Sort Key1:=Range("A1"), Order1:=xlDescending, DataOption1:=xlSortNormal

        X = Range([a1], Cells(UBound(vArr) + 1, "B"))

        For lngcnt3 = 1 To UBound(X)
            X(lngcnt3, 2) = InStr(strFormula, Replace(X(lngcnt3, 1), ZZ, vbNullString))
            strFormula = Left$(strFormula, InStr(strFormula, Replace(X(lngcnt3, 1), ZZ, vbNullString)) - 1) & Application.WorksheetFunction.Rept("|", Len(Replace(X(lngcnt3, 1), ZZ, vbNullString))) & Right$(strFormula, Len(strFormula) - InStr(strFormula, Replace(X(lngcnt3, 1), ZZ, vbNullString)) - Len(Replace(X(lngcnt3, 1), ZZ, vbNullString)) + 1)
        Range([a1], Cells(UBound(vArr) + 1, "B")) = X
        Columns("A").Replace ZZ, vbNullString
        With Sheets(wsWorking)
            Sheets(wsWorking).[c1].Resize(UBound(vArr, 1) + 1) = "=RANK(RC[-1],R1C[-1]:R" & lngCnt & "C[-1])"
            .UsedRange.Sort Key1:=Range("C1"), Order1:=xlDescending, DataOption1:=xlSortNormal
            .[a1] = "'" & strAddress
        End With

        MsgBox "Not a formula", vbCritical
    End If

    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With
End Sub
Function OnecellsPrecedents(ByVal rng2) As String
'brettdj adapted the code from Bill Manville
'some versions of this are attributed to Mike Rickson
    Dim strAddress As String
    Dim strOut As String
    Dim rngReturn As Range
    Dim i As Long
    Dim lngArrow As Long
    Dim lngLink As Long
    Set rngReturn = Selection
    strAddress = rng2.Parent.Name & "!" & rng2.Address

    With rng2
            lngArrow = lngArrow + 1
            .NavigateArrow True, lngArrow, 1
            If ActiveCell.Parent.Name & "!" & ActiveCell.Address = strAddress Then Exit Do
            If Err.Number <> 0 Then Exit Do
            On Error Resume Next
            lngLink = 1
                If Err.Number <> 0 Then Exit Do
                strOut = strOut & (IIf(rng2.Parent.Name <> ActiveSheet.Name, ActiveSheet.Name & "!", vbNullString) & Selection.Address(0, 0) & StrDelim)
                lngLink = lngLink + 1
                .NavigateArrow True, lngArrow, lngLink

            On Error GoTo 0
        ActiveCell.ShowPrecedents Remove:=True
    End With
    With rngReturn
    End With
    OnecellsPrecedents = Left$(strOut, Len(strOut) - Len(StrDelim))
End Function

Open in new window


Author Comment

ID: 33443075
Thanks, Dave.  Seems to work pretty well, with two exceptions I found doing some quick checking:

1)  It doesn't not handle formulas that link to external workbooks, at least when those workbooks' names contain characters that would require single quotes in the formula.

2)  It doesn't handle links to other sheets in the same workbook when those other sheets' names contain characters that would require single quotes in the formula.  This causes the cell references shown in column A of the output to read something like "Sheet 2!A1" rather than "'Sheet 2'!A1".  The values in column B are then off by the amount of preceding single quotes that were omitted.

FYI, I use the following Regex pattern to check sheet names to see when Excel will require sheet names to be enclosed in single quotes in formulas:  "[\s~!@#%\^&\(\)\-\+\{\}'"";,\|<>]".  This pattern might also apply to workbook names.  Not sure if that would be helpful in refining the solution.

LVL 85

Expert Comment

by:Rory Archibald
ID: 33444084
Unless I'm misreading it, your regex to catch single quotes is incomplete. If you enter something that looks like a date separated with full stops, it requires single quotes.

Author Comment

ID: 33451376
I'm assuming "full stop" = "period".  Periods in worksheet names do not cause Excel to surround the names in single quotes, which is why periods are omitted from the pattern.
LVL 85

Expert Comment

by:Rory Archibald
ID: 33452020
I said "something that looks like a date separated with full stops". For example 14.02.10

Author Comment

ID: 33452070
You're correct.  Not really an issue for my purposes, though, and doesn't affect the outcome I'm trying to achieve.
LVL 85

Expert Comment

by:Rory Archibald
ID: 33452093
Hence the "FWIW"...

Featured Post

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After seeing numerous questions for Dynamic Data Validation I notice that most have used Visual Basic to solve the problem. This suggestion is purely formula based and can be used in multiple rows.
Simulator games are perfect for generating sample realistic data streams, especially for learning data analysis. It is even useful for demoing offerings such as Azure stream analytics, PowerBI etc.
Graphs within dashboards are meant to be dynamic, representing data from a period of time that will change each time the dashboard is updated with new data. Rather than update each graph to point to a different set within a static set of data, t…
This Micro Tutorial will demonstrate in Microsoft Excel how to add style and sexy appeal to horizontal bar charts.

916 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question