Excel Cell Precedents

Posted on 2010-08-15
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.
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

LVL 50

Accepted Solution

Dave Brett earned 500 total points
ID: 33442987
Its an interesting - read very difficult - task.  I have spent several  hours on this, reworking the NavigateArrows method from  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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Excel can be a tricky bit of software to get your head around. Whilst you’ll be able to eventually get to grips with the basic understanding of how to get by, there are a few Excel tips that not everybody will even know about let alone know how to d…
This Micro Tutorial will demonstrate in Google Sheets how to use the HYPERLINK function to create live links inside your spreadsheet.
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…

831 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