PDA

View Full Version : Interesting observation about evaluate command



CodeNinja
06-25-2012, 01:25 PM
One of my favorite new "Toys" in VBA is the command Evaluate. For those of you who do not know what this does, it is one of the more powerful tools available to you, so I highly suggest playing with it.

Evaluate basically takes a string and runs any functions based on that string (or at least that is my understanding of it). So, if you did:
i = evaluate("3 + 4")
msgbox(i)

You would get a message box showing 7.

Evaluate also works with functions you create... so if you did the following:

Public Function getColLtr(i As Integer)
getColLtr = Split(Sheet1.Cells(1, i).Address, "$")(1)

End Function

Sub test2()
Dim s As String
s = "getColLtr(5)"

MsgBox (Evaluate(s))
MsgBox (getColLtr(5))

End Sub

You will get two message boxes of "E". That is to be expected. What I found interesting is that when I run the code in step mode, it never steps through the function when Evaluating, but it does step through when iterating the second message box.

Bizarre. I tested to see if evaluate was more efficient (ran faster) than the same function without evaluate, and no big surprise, the act of evaluating makes the function less efficient. I just think it is interesting in the step through that it does not iterate through any functions.

No questions here, just an odd observation.

Thanks.

Trebor76
06-25-2012, 10:57 PM
but it does step through when iterating the second message box

Correct. That's because that line is calling the "getColLtr" function, but the previous line isn't.

The Evaluate function does what its name suggests, i.e. calculates the result of a string formula passed to it. It's a great alternative, amongst other uses, to trying to find a blank cell for your code to calculate a formula for later use.

Aaron Blood gives a great over of the function here (http://www.ozgrid.com/forum/showthread.php?t=52372).

Though there's generally no need to convert a column number to a letter for VBA use, the following is an example of the use of the Evaluate function in practice:


Option Explicit
Sub Macro5()
'http://www.vbaexpress.com/forum/showthread.php?t=42695
Dim intMyColNum As Integer

intMyColNum = 5
MsgBox Evaluate("substitute(address(1, " & intMyColNum & ", 4), ""1"", """")")

End Sub

Regards,

Robert

snb
06-26-2012, 01:38 AM
In that case I'd prefer:

sub snb()
j = 5
MsgBox Split(Columns(j).Address(, 0), ":")(0)
end sub

or


MsgBox [substitute(address(5,5,4),5,"")]

CodeNinja
06-26-2012, 05:37 AM
Aaron Blood gives a great over of the function here (http://www.ozgrid.com/forum/showthread.php?t=52372).


Trebor76,
That article was huge for me. Thanks.

Kenneth Hobs
06-26-2012, 06:43 AM
Here is an example using the split method and evaluate. The [] method will be immediate but the string for Evaluate method lets you build the expression to evaluate.

'http://www.mrexcel.com/forum/showthread.php?t=338789
Sub test_ColumnLetter_ColumnNumber()
MsgBox ColumnLetter(40), , "40"
MsgBox ColumnNumber("AN"), , "AN"
MsgBox ColumnLetterSNB(40), , "40"
End Sub

Function ColumnLetter(ColumnNum As Integer) As String
ColumnLetter = Split(Cells(1, ColumnNum).Address, "$")(1)
End Function

Function ColumnNumber(sColumnLetter As String) As Integer
ColumnNumber = Cells(1, sColumnLetter).Column
End Function

Function ColumnLetterSNB(ColumnNum As Integer) As String
Dim s As String
' http://www.vbaexpress.com/forum/showthread.php?t=42695
'MsgBox [substitute(address(5,5,4),5,"")]
s = "Substitute(Address(" & ColumnNum & ", " & ColumnNum & ",4)," & ColumnNum & ","""")"
ColumnLetterSNB = Evaluate(s)
End Function

When evaluating a range of cells, one could iterate each one. Using evaluate is more of a one liner method just up snb's alley. Here, I simply convert a range of cells to their absolute value or rewrite if not a number.

Sub Test_RangeNumbersToAbsolute()
' [A1:A5] = [If(IsNumber(A1:A5), Abs(A1:A5), A1:A5)]
RangeNumbersToAbsolute "A1:J5"
End Sub

Sub RangeNumbersToAbsolute(x As String)
Range(x).Value = Evaluate("If(IsNumber(" & x & "),Abs(" & x & ")," & x & ")")
End Sub

Bob Phillips
06-26-2012, 08:22 AM
Using Evaluate on one of your own functions makes no sense to me. The only reason I can think to use it at all is to evaluate array formulae within VBA as Application and WorksheetFunction both fail with these.

snb
06-26-2012, 08:59 AM
This way you can use the shorthand version of Evaluate:


Sub snb()
MsgBox ColumnLetterSNB(40)
End Sub

Function ColumnLetterSNB(ColumnNum As Integer) As String
ThisWorkbook.Names.Add "dw", ColumnNum
ColumnLetterSNB = [substitute(address(5,dw,4),5,"")]
End Function

Jan Karel Pieterse
06-26-2012, 09:22 PM
In 16 years of VBA programming I've only had one project where I could actually use the Evaluate function.
I needed a way for the user to specify the formula for the surface area calculation of shapes. The user wanted to be able to define his own shapes on a worksheet, where he could set up which dimensional variables there were and what formula would yield the surface area and volume of the shape. That is where Evaluate was useful.
Otherwise, I haven't seen any examples of evaluate you couldn't do more efficiently using plain straight-forward VB code.

CodeNinja
06-27-2012, 06:33 AM
In 16 years of VBA programming I've only had one project where I could actually use the Evaluate function.
I needed a way for the user to specify the formula for the surface area calculation of shapes. The user wanted to be able to define his own shapes on a worksheet, where he could set up which dimensional variables there were and what formula would yield the surface area and volume of the shape. That is where Evaluate was useful.
Otherwise, I haven't seen any examples of evaluate you couldn't do more efficiently using plain straight-forward VB code.

Actually, I thought evaluate was a perfect solution for this post:

http://www.vbaexpress.com/forum/showthread.php?t=42646

It is what got me looking at evaluate in the first place.

Jan Karel Pieterse
06-27-2012, 07:56 AM
Yep, that is one situation where evaluate comes in handy.

Trebor76
06-27-2012, 04:30 PM
I've actually posted the following on that thread as a ways to show the usefulness of the Evaluate function:


Option Explicit
Sub Macro1()

'Return the value of the formula =MID(B2,FIND("=",B2)+1,LEN(B2)-FIND("=",B2)+1) to cell A4
Range("A4").Value = Evaluate("MID(" & Range("B2").Address & ",FIND(""=""," & Range("B2").Address & ")+1,LEN(" & Range("B2").Address & ")-FIND(""=""," & Range("B2").Address & ")+1)")

End Sub

snb
06-28-2012, 12:11 AM
Which could also be gotten in VBA using:


range("A4")=split(range("B2"),"=")(1)


or

[A4]=[MID(B2,FIND("=",B2)+1,LEN(B2))]

Bob Phillips
06-28-2012, 12:22 AM
Which could also be gotten in VBA using:


range("A4")=split(range("B2"),"=")(1)


or

[A4]=[MID(B2,FIND("=",B2)+1,LEN(B2))]

The second is just another way of using Evaluate!

snb
06-28-2012, 12:57 AM
You get today's bonus points ! Congrats.

Bob Phillips
06-28-2012, 01:10 AM
And you get the points for repeating what someone else has already provided. Wastrel.

snb
06-28-2012, 01:40 AM
Thanks ;)