I would go further than that and suggest not using IIf() in VBA at all! There is no reason to when IF..Then..Else and Select Case are so much more readable.
Again Pat and I seem to disagree but that is not correct.
I agree with Pat on everything she has posted so far in this thread but not on this: -
“not using IIf() in VBA at all”
But I will try to explain my reasoning the way I think… (reductio ad adsurdum)
Code:
Private Sub Form_Current()
[color=green]' We could use 1...[/color]
Me.txtMyTextBox.ForeColor = IIf((SomeThingOrOther), vbRed, vbGreen)
[color=green]' or 2...[/color]
If (SomeThingOrOther) Then
Me.txtMyTextBox.ForeColor = vbRed
Else
Me.txtMyTextBox.ForeColor = vbGreen
End If
End Sub
Both are very simple (reductio ad adsurdum) examples.
So what’s the difference? Well not very much at all.
Without testing I would say the second lot of code is faster than the first and it is easier to read than the first.
But I think the speed difference in the above example would be miniscule and in most cases not warranted.
So I think, as Pat has suggested, the difference comes down to how readable it is.
We, after awhile, come to understand the IIf Function like this: -
So we become familiar with the simple IIf function.
So, under the circumstance of being familiar with the simple IIf function, what’s the difference?
Believe it or not readability.
The readability of a function or subroutine can depend on if it is all in view at a given time.
This would be an old axiom that Pat would surly know.
Keep the function or subroutine to a single page.
That axiom was created to minimize ‘page flipping’ when the procedure was printed.
It is still valid in screen based systems.
If we can, but not always done, then viewing a procedure that is totally contained in the viewing area is good.
So, with practice And with simple cases And when speed is not important, we come back to readability.
(Please note the three AND’ed conditions above because that is why this thread was started.)
Code:
Private Sub Form_Current()
Me.txtMyTextBox.ForeColor = IIf((SomeThingOrOther), vbRed, vbGreen)
[color=green]' is better than...[/color]
If (SomeThingOrOther) Then
Me.txtMyTextBox.ForeColor = vbRed
Else
Me.txtMyTextBox.ForeColor = vbGreen
End If
End Sub
Simply because the vertical screen consumption of one line is better than five.
We all have our own opinion but what I really dislike are absolutes.
(I hope that was read as a personal preference and not a criticism.)
Maybe all it should be is just something to think about. (And try.)
I learned to like AND use AND read it, saving space. (Thanks Chris recalling the origin )
So I think too it's dependend from how familiar with this 'mysterious' IIF-statement I'am.
But, what I wanted to ask:
I would be really interested to know, how this IIf-statement is translated in machine code by the compiler!
Somebody who knows?
As shown before (see the instructive Posting #10 from Pat Hartman) there must be a difference between an IIf statement and its 'equal' If-Else solution.
So my question is how the compiler is translating this IIf statement in machine code .
It's been a while, but here's the general idea. Both of the
VBA constructs below would generate roughly the machine code.
I don't want to carry it a step further and assemble that
into machine code.
I think Chris used to work with the PDP-11 computers. This
is sort of MACRO-11.
Code:
IIf(A > B, A, B)
If A > B Then
fnValue = A
Exit Function
ELse
fnValue = B
Exit Function
End If
Start: Mov A, R0
Mov B, R1
Cmp R0, R1
BH MoveA
MoveB: Move R1, (SP)+
RTS PC
MoveA: Move R0, (SP)+
RTS PC
The generated code would be similar but not identical. The big difference is that the IIf() is actually LESS efficient so the fact that it is more concise is irrelevant. ALL segments of the IIf() are evaluated every time the IIf() is executed whereas only the "true" path of the nested If or Case statement is. So the IIf()'s code would not branch over the MoveB section.
Please take note that when an IIf() is evaluated in SQL it does NOT evaluate all paths each time as it does in VBA. It acts like the nested If in that it only evaluates along the "true" path.
Chris, a simple IIf() with only a single true and false is obviously simple enough to understand and would certainly be appropriate if your code actually needed the flexibility of a function. So, truth be told, I might at some time have actually used one in VBA. But in general I don't. The criteria I use for deciding how to do something when multiple choices are available are:
1. Readibility
2. Efficiency
Of course the priorities change if the code is in a loop that executes multiple times. The more frequently a piece of code is executed, the more important it is to make it efficient.
“Of course the priorities change if the code is in a loop that executes multiple times.
The more frequently a piece of code is executed, the more important it is to make it efficient.”
It implies that we should understand just when, where and under what circumstances we do or do not do things in a certain way.
And without that understanding we can not correctly choose between readability and efficiency.
Wayne
I also dislike them when they are complex enough to warrant a second look.
But when they are simple I think the saving of screen real estate can be the deciding factor.
Willi
I’m only on my second cup of coffee so I hope this makes sense: -
Code:
Sub Test()
Dim X As Long
Dim Y As Long
X = 1
Y = 1
MsgBox IIf(False, X / 1, Y / 0)
MsgBox MyTestFunction(X / 1, Y / 0)
End Sub
Function MyTestFunction(A As Long, B As Long) As Long
MsgBox "Here in MyTestFunction"
End Function
If we run these two lines of code they both raise the same division by zero error.
We know that the IIf function will raise the error but strictly speaking it is not raised in the IIf function.
Just like the MyTestFunction function, the error is raised while evaluating the arguments before they are passed to the function.
In the above example MyTestFunction does not execute its MsgBox.
So it seems it’s not the “fault” of the IIf function at all but the argument evaluating mechanism.
This would seem to explain why the IIf function seems to always evaluate both True and False parts.
Not because it’s the fault of the nasty old IIf function but simply because it is a function and all arguments are evaluated before passing.
Hope that makes some sense…now for my third cup of coffee.
fortunately having my 12th cup I think I could follow your explanations. And as I followed it fell like scales just from my hairs: what a stupid, simpletonary and dumpfpfeifentrotteliger* Kraut I am!
Apart from having given today two or three wrong and absolutly foolish advices, I did not thought over that this IIf statement could be just a normal, ordinary and alldaytrivial FUNCTION!
I really feel ashamed of my last question.
Sorry!
But I want thank you and Pat, and Wayne and all the others for your friendly and helpful Postings. To me it has been a very instructive and stimulating Thread.
Thank you all.
And now I will try 'to hold the ball flat'**...
Willi
*sorry, can't translate.
**hope you understand in english
With the conditions as stated above, even the If function behaves the same.
Code:
If Y / 0 Then
MsgBox "You'll never get here."
Else
MsgBox "You'll never get here either."
End If
The moral of the story is, don’t do divisions in arguments that are passed to any function.
In fact, don’t do anything that might cause any error while passing any argument to any function or subroutine.
The argument will simply crash at evaluation, before it gets to the procedure.
The validity of calculated or assignment arguments needs to be evaluated before we attempt to pass them.
The question of which is faster, the IIf or the If function needs to be tested but also requires a little more thought.
If Y / 0 Then, evaluates one passed argument to the If function.
IIf(False, X / 1, Y / 0), has to evaluate three passed arguments to the IIf function.
Which should be faster… and why?
Technically, from a code point of view, the IIf function is no better or worse than any other procedure when evaluating arguments.
For example: -
Code:
Option Explicit
Option Compare Text
Public Declare Function timeGetTime Lib "Winmm.dll" () As Long
Public Declare Sub Sleep Lib "kernel32" (ByVal lngMilliseconds As Long)
Sub Test()
Dim X As Long
Dim lngStart As Long
lngStart = timeGetTime()
X = MyTestFunctionA(DelayMilliseconds(2000))
MsgBox timeGetTime() - lngStart
lngStart = timeGetTime()
X = MyTestFunctionB(DelayMilliseconds(2000), DelayMilliseconds(3000))
MsgBox timeGetTime() - lngStart
End Sub
Function MyTestFunctionA(lngFirstMilliseconds As Long)
' Do nothing.
End Function
Function MyTestFunctionB(lngFirstMilliseconds As Long, lngSecondMilliseconds As Long)
' Do nothing.
End Function
Function DelayMilliseconds(Delay As Long) As Long
Sleep Delay
End Function
MyTestFunctionA takes 2 seconds to evaluate its argument.
MyTestFunctionB takes 5 seconds to evaluate its arguments.
Therefore the question is, “Why is the IIf function so maligned?”
Well, a bit more code is required…
Code:
lngStart = timeGetTime()
If True Then
X = MyTestFunctionA(DelayMilliseconds(2000)) ' < 2 seconds
Else
X = MyTestFunctionA(DelayMilliseconds(3000))
End If
MsgBox timeGetTime() - lngStart
lngStart = timeGetTime()
If False Then
X = MyTestFunctionA(DelayMilliseconds(2000))
Else
X = MyTestFunctionA(DelayMilliseconds(3000)) ' < 3 seconds
End If
MsgBox timeGetTime() - lngStart
But we would never do that... would we?
Well the sad fact is that some people do and that makes some people sad facts.
(But the point is…2 seconds XOR 3 seconds is still better than 5 seconds.)
Now that we understand the technical code point of view AND we only use readable IIf functions then the IIf function has the advantage of screen real estate.
Since, under these circumstances, the IIf function is readable then using it helps to make our whole procedure more readable simply by trying to keep the whole procedure ‘on screen’.
I think I might have to come back and edit this later.
having had a very instructive and enlithening journey on the marvelous land of the disregarded and frequently even calumniated IIF function (Thanks to all) I would like to wash out the ash from my hair and return to the origin starting point throwing my last dump question into the wideness of this very friendly and helpful council:
In a statement like
Code:
IF cond1 AND cond2 AND cond3 THEN ...
why does ACCESS will evaluate all this conditions, even if the first is false?
It is not because it is a function - as in the case of the IIf function - , or I'am wrong once again? Please show mercy....
No…one does not need to invent anything. It has already been invented.
This is difficult to try and explain…
The logical states are defined in hardware…software simply tries to keep pace.
The computer screen you are looking at is running on hardware logic.
The data that is being processed is being processed at a hardware logic level.
The software is trying to translate software instructions to hardware instructions.
Hardware logic governs the system, not the software.
The OR, AND, XOR, NAND, and the like, must be processed within the logical definition of the hardware truth tables.
Those tables will be found in digital electronics books and not necessarily in software books.
Without those digital electronic definitions your computer would not exist.
It does not matter what computer you use, nor what language you may use on that computer, but it must comply with the hardware truth tables.
Some languages may have the intelligence to ‘bail out’ after a False is found in an AND statement. VBA and BASICS do not. But they give you the option to write it in such a way that you achieve the same outcome. You now have the control and the flexibility.