I have this VBA function:
Public Function testPrec(target As Range) As String testPrec = target.Precedents.Address(External:=False) End Function
In cell C11, I have this formula:
If I call
testPrec from the immediate window, it works just fine:
EDIT: It also works fine if called from a non-UDF macro Sub. The anomaly is the UDF case.
If I call it from the worksheet as a UDF:
I just get back “$C$11”.
Does anyone know what’s going on, or even better how to get the actual precedents from within a UDF call? (I’m using Excel 2007.)
The only workaround I can think of is to get target.formula and parse it – not very nice.
It seems the constraint lies in that any call to
.Precedents in a call stack that includes a UDF gets handled differntly. So, find a way to do the call outside the call stack triggered from the UDF: One thought is to use events. Here is a overly simplistic example to demonstrate
In a module define
Public strPrecedent As String Public rngPrecedent As Range Public Function testPrec(target As Range) As String Set rngPrecedent = target testPrec = strPrecedent End Function
In a sheet define
Private Sub Worksheet_Calculate() If Not Module1.rngPrecedent Is Nothing Then Module1.strPrecedent = Module1.rngPrecedent.Precedents.Address(External:=False) End If End Sub
testPrec now returns the correct range address, albeit one recal late. The idea is to have the UDF build a list of addresses to get Precedents for, and an event to do the actual GetPrecedent work, returning the address strings to the list for pickup by the udf. You might be able to build a workable solution out of this, depending on your needs.
I ran into a similar problem: I had to format cells based on whether they contain a formula or a constant value.
HasFormula makes it possible to determine if a cell contains a formula, however, simple calculations, like
=123+45 are also detected as formulas (correctly from a technical point of view but incorrectly from a financial modelling perspective). So I wanted to use
Precedents in a UDF to see whether the given cell links to any other. As mentioned above the value of
Precedents during the execution of an UDF is not valid but I needed to know only if there is any precedent, not which cells they are.
So I compared the
FormulaR1C1 properties because they are different only in case the
Formula contains a cell reference.
There is one exception: If the
Formula contains Named Ranges, then
FormulaR1C1 can be equal even though the cell refers to something. (This was not relevant in my case and did not want to iterate all Names and check if they are contained in the
Formula outside quotation marks.