Reputation: 1298
EDITED WITH BETTER EXAMPLE
I'm trying to use the Evaluate function to evaluate a formula reference for a named range. However, when using the Evaluate function, if you do not explicitly state the sheet reference along with the cell reference, it will assume the active sheet as the cell reference. This causes the wrong result
In my real project I'm trying to only evaluate a part of the named range's formula, so it makes it even trickier.
Using a basic example of what I'm trying to do, let's say you have the following formula in Sheet 1 cell A1 whose name is MyCell:
="Don't evaluate this part"&"My Result Is " & A2
If the Active Sheet is Sheet 2 and you run the following code it will give you the wrong results (this is a quick and dirty example to illustrate the problem)
Dim s As String
s = Replace(Range("MyCell").Formula, """Don't evaluate this part""&", "")
Debug.Print Evaluate(s)
Instead of giving me the value that is in cell A2 of Sheet 1, it gives me the value that is in cell A2 of Sheet2.
Any ideas around this?
This is closest I found, but it is not my exact problem (despite similar titles) and it doesn't provide a solution: Excel VBA evaluate formula from another sheet
Upvotes: 1
Views: 2509
Reputation: 23505
Its nearly always better to use Worksheet.Evaluate rather than the default Application.Evaluate: as Mark Balhoff points out that allows you to control unqualified references. But Worksheet.Evaluate is also usually twice as fast as Application.Evaluate. See my blog post here for details https://fastexcel.wordpress.com/2011/11/02/evaluate-functions-and-formulas-fun-how-to-make-excels-evaluate-method-twice-as-fast/
Upvotes: 1
Reputation: 2356
The problem you are having is that by design Excel will assume all unspecific cell references are referring to the existing worksheet. This is why whenever possible it is recommended to explicitly state the worksheet in all code.
The cleanest way (verified with some MSDN definintion hunting) is to just explicitly state the worksheet without activating it:
Sub test2()
Debug.Print Range("MyCell").Worksheet.Evaluate(Range("MyCell").Formula)
End Sub
Alternatively this code will change the active worksheet to the correct one and then change it back after evaluation. Not recommended to perform sheet activations like the code below without extenuating circumstances. Not even here.
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim s As String
s = Replace(Range("MyCell").Formula, """Don't evaluate this part""&", "")
Range("MyCell").Worksheet.Activate ' Don't remember if .Worksheet or .Parent ??
Debug.Print Evaluate(s)
ws.Activate
End Sub
As pointed out in the comments by ThunderFrame, it is important to remember that this code assumes MyCell is a simple cell reference as stated in the question. Otherwise you will need to use other methods to determine the target worksheet name (or hardcode it).
Upvotes: 2
Reputation: 9461
Your line:
Debug.Print Evaluate(Range("MyCell").Formula)
is equivalent to:
Debug.Print Evaluate("=""My Result Is "" & A2")
which is why you get results according to the value of A2 in the ActiveSheet.
If you want to inspect the contents of the formula, you can use this line:
Debug.Print [MyCell].Formula
If you want the value of MyCell with respect to Sheet1, then you have 2 options:
1 - Use Debug.Print Range("Sheet1!MyCell").Value
2 - Use Debug.Print Sheet1.Range("MyCell").Value
Upvotes: 0