Syntax error using IIf - vba

This is a simple question I hope. I learned about IIf today and want to implement it in some cases to save a few lines.
IIF(isnumeric(inputs), resume next, call notnum)
This is in red meaning there is a syntax error, how fix this? I have scanned MSDN article on this so I am not being lazy here.

That's not how the IIf function works.
It's a function, not a statement: you use its return value like you would with any other function - using it for control flow is a bad idea.
At a glance, IIf works a little bit like the ternary operator does in other languages:
string result = (foo == 0 ? "Zero" : "NonZero");
Condition, value if true, value if false, and both possible values are of the same type.
It's for turning this:
If foo = 0
Debug.Print "Zero"
Else
Debug.Print "NonZero"
End If
Into this:
Debug.Print IIf(foo = 0, "Zero", "NonZero")
Be careful though, IIf evaluates both the true and the false parts, so you will not want to have side-effects there. For example, calling the below Foo procedure:
Public Sub Foo()
Debug.Print IIf(IsNumeric(42), A, B)
End Sub
Private Function A() As String
Debug.Print "in A"
A = "A"
End Function
Private Function B() As String
Debug.Print "in B"
B = "B"
End Function
Results in this output:
in A
in B
A
That's why using IIf for control flow isn't ideal. But when the true result and false result arguments are constant expressions, if used judiciously, it can help improve your code's readability by turning If...Else...End If blocks into a simple function call.
Like all good things, best not abuse it.

You cannot use iif like this.
Here is a possible way to solve this:
if isnumeric(input) then
do something ...
else
call notnum
end if

IIf returns a value. As Mat's Mug stated, you can use it, to hand data into another method or function, but you can't call a procedure or function, which has no return value.
IsNumeric() for the conditional is okay, though.

Related

(Micro Optimisation) - Exit function or let it run through all code

I am curious if Exit Sub, Exit Function, among others should be avoided when coding? I have read in various places that it is a bad practice and that you should, if possible, avoid it.
I have provided a function below to demonstrate what I mean:
Function Test()
Dim X As Integer
X = 5
If X = 10 Then
Test = True
Exit Function
Else
Test = False
Exit Function
End If
End Function
In the case above, the Exit Function isn't necessary since the entire code will be able to finish the entire routine without an issue. But by adding it, will it cause some issues?
The style you're using is from the VB5 and VBA era, which didn't support Return statement and we needed to assign the return value directly to the function name. In VB.NET you should always use Return assignment. Return will do both the assignment and the exit call in one statement.
Regarding your particular example, my impression is that the Exit Function statement does nothing more than doing a GoTo to the nearest End Function line. So these statements in your case are redundant and might get striped off by the compiler (not sure about this one).
Note that Exit statements become a nightmare from code-readability point of view. I have recently been a victim of this particular problem. Visual Basic is such a verbose language and Exit statements go unnoticed by the reader. A structured If/Else block is FAR more readable.
This depends on the current context of your code. If you are within a block (be that a loop, Sub or function etc.) and are attempting to leave, the Exit Statement will do fine.
The Return Statement will also work the same as a Exit Function or Exit Sub, see the answer to this SO question. But personally I prefer the exit statement in a function when I wish to return control to the calling code, but have no value to return.
In practically every case, there's a "better" approach than using Exit Function.
The following example will give the same result, but is shorter, and in my opinion much clearer.
Function Test() As Boolean
Dim X As Integer
X = 5
Return (X = 10)
End Function
To clarify a little, as #dotNET said. This is pre .net code. In dot net, you would change your code slightly to
Function Test() As Boolean
Dim X As Integer
X = 5
If X = 10 Then
Return True
Else
Return False
End If
End Function
This defines test as a function that returns a Boolean result and you use the Return statement to err.. return the result back to the calling statement and exits the function immediately at the aforementioned Return statement
for example ..
Dim result As Boolean
result = test

vba user defined operator in user defined fuction

How do I make it so that the user can define the operator? For example the user will type
=iftrue(x+y,">=z",x+y) (much like a sumif or regular if function)
I understand I can use a normal if function or use a separate cell to solve for the logic. However the reason I am doing this is because I have a very cpu intensive computation that will have to recalculate rather than returning the already computed value.
This is currently what I have.
Function iftrue(Value1, Criteria1, ValueifTrue)
' Function
If Value1 = Criteria1 Then
iftrue = ValueifTrue
Else: iftrue = Value1
End If
End Function
This modified versions of your code will do I guess, try it out..
Function IfTrue(Value1, Criteria1, ValueifTrue)
'Function to Evaluate Calculation'
If Evaluate(Value1 & Criteria1) Then
IfTrue = ValueifTrue
Else
IfTrue = Value1
End If
End Function
This is just the basic idea, you might want to develop on this !

What are a good No OP operation for vb.net?

Something we can just put break point on while making sure it doesn't do anything else.
In c, that would be while(false);
What to do in vb.net?
If you always need it to break there you can put
Stop or Debugger.Break()
If you really want a No-Op for some reason (could this turn into a contest for the most ineffectual single line of code?!), how about these?
System.Threading.Thread.Sleep(1) - 1ms is unlikely to have a huge impact outside of a loop
Debug.Write("") - doesn't appear to output anything.
There is a legitimate use-case for this.
When a temporary breakpoint is required after the statement of interest and this is the last line inside an if statement, an extra no-op type statement is required to place the temporary breakpoint on.
In this case I use:
If someCondition >0 Then
doSomething
Space (1) 'Dummy line to place breakpoint
End If
This returns a string containing one space, but does not assign it to anything. I use it in VBA, but it's also supported in .net
My two cents...
You can combine any series of commands onto one line with colons:
If False Then : End If
Select Case False : Case Else : End Select
I've also made it into a sub. Then it gets a recognizable name of own:
'Definition...
Public Sub noop () 'Or Private, Protected, etc.
End Sub
'Usage...
Sub Main()
If sometest Then
noop
Else
MsgBox "test is false"
End If
End Sub
Very strange question, you could place a BreakPoint about anywhere in the code. But here are some useless lines :
Do While False
Loop
While False
End While
Even the following :
Dim hello = Nothing
Or this :
Format("", "")
A no-op statement is also useful as an aid to document code nicely and make it more easily understandable. You could for example put in a statement like A = A.
For example:
If MyNumber => 100 then A = A
Else:
I know this is an old query, but for what it is worth, my preferred solution to the original question is
Debug.Assert (vbTrue)
If you wanted, you could use a variable instead of vbTrue and then enable/disable all breakpoints in your code by changing one variable
Dim bDisableBreakpoints as Boolean: bDisableBreakpoints = vbTrue
'your code here
Debug.Assert (bDisableBreakpoints)
'rest of your code
Simply change bDisableBreakpoints to vbFalse and the breakpoints will be set wherever you have used Debug.Assert
My personal favorite is
dim b=1
Then I put a breakpoint there.

VB.NET: Assign value to variable inside an IF condition?

is there any possibility to assign a value to a variable inside an IF condition in VB.NET?
Something like that:
Dim customer As Customer = Nothing
If IsNothing(customer = GetCustomer(id)) Then
Return False
End If
Thank you
Sorry, no. On the other hand, it would get really confusing, since VB.NET uses the same operator for both assignment and equality.
If a = b Then 'wait, is this an assignment or comparison?!
Instead, just set the variable and compare:
Dim customer As Customer = Nothing
customer = GetCustomer(id)
If IsNothing(customer) Then
Return False
End If
No, I'm fairly sure this is not possible - but be thankful!
This is a "feature" of C-based languages that I would never encourage the use of, because it is probably misused or misinterpreted more often than not.
I think the best approach is to try and express "one thought per line", and resist coding that combines two operations in the same line. Combining an assignment and a comparison in this way usually doesn't achieve much other than making the code more difficult to understand.
VB doesn't do that very well, especially since assignment and comparison both use the = operator. It'd get really confusing. And since VB to some degree is designed to be newbie-friendly (The B in "BASIC" actually stands for "Beginner's"), expressions with multiple side effects are not something the language generally likes to do.
If it's essential that you be able to do it all in one line, then you could make the GetCustomer method assign to a ByRef parameter, and return a boolean saying whether the assigned value was null. But really, it's better to just assign and then compare to null.
There is no builtin support for doing this, but you could use this workaround.
Public Function Assign(Of T)(ByRef destination As T, ByVal value As T) As T
destination = value
Return destination
End Function
And then it could be used like this.
Dim customer As Customer = Nothing
If IsNothing(Assign(customer, GetCustomer(id))) Then
Return False
End If
Thinking out loud because you didn't show Customer or GetCustomer...
Dim myCust As New Customer
If myCust.GetCustomer(someID) Then
End If
Class Customer
Private _customerID As Integer
Const noCustomer As Integer = -1
Public Sub New()
Me._customerID = noCustomer 'no customer
End Sub
Public Function GetCustomer(ByVal id As Integer) As Boolean
'perform required action to get customer
'if successful then set Me._customerID to ID else set it to no customer value
Return Me.HaveCustomer
End Function
Public Function HaveCustomer() As Boolean
If Me._customerID = noCustomer Then Return False Else Return True
End Function
End Class
Yes, it is possible to assign a value to a variable inside an IF condition in VB.NET.
There is even builtin support for doing this, albeit to a limited extend:
If Interlocked.Exchange(customer, GetCustomer(id)) Is Nothing Then
Return False
End If
where the methods within the Interlocked class are intended to be used within a multi-threading environment. By design, the return value of Exchange() is the old value, rather than the new one. Thus, to obtain the rather cryptic equivalent result:
If (customer = Interlocked.Exchange(customer, GetCustomer(id)) And customer Is Nothing Then
return false
End If
All of the people stating that this is an issue as VB uses the "same operator for both assignment and equality"..
I would argue that this is not a good reason as they could simply make slightly different syntax for it... for example:
Dim[Name = Expression]
If a = Dim[qwe = 1 + 2] Then
'qwe = 3
End If
'...
a = 3
If Dim[qwe = a = 1 + 2] Then
'qwe = True
End If

Syntax: "Exit Sub" or "Return" in VB.NET subroutines

Both "Exit Sub" or "Return" seem to accomplish the same thing -- exit a subroutine. Is there any difference in how they work under the covers?
That is,
Private Sub exitNow()
Exit Sub
End Sub
or
Private Sub exitNow()
Return
End Sub
From the doc:
In a Sub or Set procedure, the Return statement is equivalent to an Exit Sub or Exit Property statement, and expression must not be supplied.
So they're the same in this context.
(Return (<value>) is used in functions and property.get's. Obviously slightly different in that context).
I tend to prefer Return over Exit Sub. Because once in a while you change from Sub to Function. In this case Exit Sub could be converted to Exit Function, but this assumes that there was a previous assignment to the function name (alike VB 6), which most probably didn't happen. Return would catch this situation - if the method should return a value, Return with no argument will fail at compile time.
If you inspect the IL output of the 2 statements, they are the same. However, since ’return’ is meant for pushing something back to the caller, so strictly speaking, ‘Exit Sub’ is more suitable for using in a Sub.
They are the same in this context.
However, from the code readability point of view, "Exit Sub" would be clearer since the "Return" indicates that something some value is being used as an output (which is not the case with Sub-routines).
First of all, Procedures comes with sub, we should know that we are working on specific procedures that don't return a specific value with the ability of passing some specific parameters or even without passing any parameter. Such as:
Print something().
Calculate the factorial of integer number CalcFact(X).
Do some processes for a specific task.
Function is a specific process programmed to achieve a specific task by also passing some specific parameters, and it has to return some value that can be used to to complete the overall task, such as validation the user name and user pass.
In short Sub Doesn't return value and we call it directly "Print HelloWorld()" , whereas functions do such as:
ValidUsersNameAndPass("Johne","jOhNe13042019") ' This could return a Boolean value.
ValidUsersNameAndPass("Johne","jOhNe13042019"); // This could return a Boolean value.
I wanted to confirm that they act the same in lambda expressions too, and they do:
Sub test()
Dim a As Action = Sub() Exit Sub
Dim b As Action = Sub() Return
a()
b()
MsgBox("Yes they do!")
End Sub
While there are exceptions like guard clauses, in most cases I would consider either a sign that the method is too long.