Iif not returning value as expected - vb.net

I use simple if statement and would like to retrieve true or false as Boolean type. I did like this:
Iif(text = "something", Convert.ToBoolean(True), Convert.ToBoolean(False))
I was trying also this:
Iif(text = "something", True, False)
For both cases i receive false, but my expression is for sure true. What i am doing wrong?

Use the If operator.
Dim someString As String = "something"
Dim matchSomeString As Boolean = If(someString = "something", True, False)

For a simple Boolean value, you can use the comparison result directly
dim text as String = "something"
dim result as Boolean
result = (text ="something")

AS by the MSDN definition
IIF : Returns one of two objects, depending on the evaluation of an expression.
IIF function has a return value that is you need to store the True or false part to some variable.
For eg:
Dim _decision As Boolean =IIf(text = "something", True, False);
then convert as
Convert.ToBoolean(_decision );

#Tushar Gupta (sorry can't comment yet, but I was about to answer any way)
You don't need to convert your value i juste tested the code below and it perfectly worked (irt was 4 and not 2 at the end of the run)
Dim irt = 2
Dim text As String = "abc"
Dim o = IIf(text = "abc", True, False)
If o Then irt = 4
End
So I guess you have not stored your return value, or your text value has not exactly the value you expect.
Anyway if you need only true/false I don't see why you are not using a simple if who would be faster.

Related

Checking if string contains only strings from a table

I need to check if my Listbox.List(i) string contains only numbers and signs '-','x' and '/'.
I tried to do it in opposite way
arrS= Array("a lot of signs")
For Each El in arrS
If Instr(Listbox.List(i),El)>0 Then
badSignFound = True:Exit For
End If
But this is non efficient. I have tried to do some counter, but still with INSTR i dont get only boolean 1 or 0, but position.
Is there any way i can just do a table from sings i need (1,2,3,4,5,'x','/','-') and do some checking of my string? Or i have to do this huge table and do it in my way?
You can use regular expressions, something like:
Function validate(s As String) As Boolean
Dim re As Object
Set re = CreateObject("vbscript.regexp")
re.Pattern = "[^0-9/\-x]"
validate = Not re.test(s)
End Function
This will return True if the string is in the alphabet 0123456789-/x and otherwise False.
See this for more on regular expressions in VBA.

How to affect to a boolean value the result of a boolean? expression

I would like to code in VB the equivalent of this in C#:
bool? a = whatever;
bool b= (a==true);
VB compiler does not accept this:
Dim a As Boolean?
Dim b As Boolean = (a = True)
I suppose in this context, it interprets (a = True) as an affectation while I want it to be interpreted as an expression.
(a == True) is apparently a syntax error.
You can use the GetValueOrDefault-method:
Dim a As Boolean?
Dim b As Boolean = a.GetValueOrDefault()
You could also use CBool
Dim a As Boolean?
Dim b As Boolean = CBool(a = True)
You need to be careful with the differences between 0, Nothing, and vbNull.
0 is a default value for a Boolean.
vbNull is a reserved Null value which should translate as 1.
Nothing will throw an exception in almost all circumstances.
Dim a As Boolean? = Nothing
Dim b As Boolean? = vbNull
Dim c As Boolean = vbNull
Dim d As Boolean
Print(a = True) 'will throw an Exception
Print(b = True) 'will return True (as vbNull = Int(1))
Print(c = True) 'will return True as the ? is unnecessary on a Boolean as vbNull = Int(1)
Print(d = True) 'will return False as the default value of a Boolean is 0
Print(a.GetValueOrDefault) 'will return False as this handles the Nothing case.
When working with unassigned values you should always check for Nothing first (or just follow good practice and set the value before you use it).
Dim a As Boolean?
Dim b As Boolean = IIf(IsNothing(a), False, a)
This will return False if a is Nothing, otherwise return A.
Only after testing for Nothing can you test for vbNull, as Nothing returns an error on all values. The code below will return False if Nothing or vbNull, or a otherwise.
Dim a As Boolean?
Dim b As Boolean = IIf(IsNothing(a), False, IIf(a = vbNull, False, a))
Note: you cannot use the code below as the test a = vbNull will be against Nothing which will throw an Exception.
Or(IsNothing(a), a = vbNull)
I would also avoid using GetValueOrDefault in any real application, as when you start using more complicated data types the default won't be so simple and you can get unexpected results. It's far better IMHO to test for IsNothing (or Object = Nothing, Object Is Nothing) than to rely on quirks of a datatype.
Best practice would be to ensure a has a value, which you can do using
Dim a As Boolean? = New Boolean()
Dim b As Boolean = a
The reason I say this is the best practice is because it translates to all Classes, not just Booleans. Noted that this is overkill for Booleans.
Hope this helps.

Use the contents of a string variable as a condition for an if statement?

Suppose I want to use an If statement, but I won't know until run-time what the actual condition of the If statement will be. Is there a way to do this by passing the condition as the contents of a string? As an example of the kind of thing I'm looking to acheive, consider the following bit of code;
Dim a as Integer = 1
Dim b as Integer = 2
Dim ConditionString As String = "<"
If a ConditionString b Then
...
End If
Mainly what I'm looking for is some way to leave the actual condition undefined until run-time. The reason I want to do this is because I need to have a set of threshold conditions in a database including not just the numeric values themselves, but also comparison operations. I might want to have something that amounts to "> 3.2 And < 5.6". As numbers are pulled in from data, the comparison operations need to be applied to the data depending on various conditions. Also, the database would be changed from time-to-time.
For such cases I love to use NCalc library, it has everything you need - it parses simple expressions (including logical and relational). Here is an example of it in C#:
var expr = new Expression("[X] > 3.2 and [X] < 5.6");
expr.Parameters["X"] = 10.0;
if (expr.Evaluate())
{
// ...
}
and VB.NET:
Dim expr As var = New Expression("[X] > 3.2 and [X] < 5.6")
expr.Parameters("X") = 10
If expr.Evaluate Then
' ...
End If
You can store a map of String to Func(Of Integer, Integer, Boolean) keyed by the strings "<", ">", "==", and so on, and take addresses of the functions that implement those conditions. For example:
Function LessThan(Integer a, Integer b) As Boolean
Return a < b
End Function
Dim Comparisons As New Map(Of String, Func(Of Integer, Integer, Boolean))
Comparisons.Add("<", AddressOf LessThan)
And then you can call it as such:
Dim a as Integer = 1
Dim b as Integer = 2
Dim ConditionString As String = "<"
If Comparisons(ConditionString)(a, b) Then
There are only a few possible conditions so I would just use a Select..Case statement:
Select Case ConditionString
Case "<"
Case ">"
'etc.
Case Else
End Select
Otherwise, you cannot (simply) convert a string "<" to an operator.
You just need a 'code', mapping some kind of value that you can store in a database to the various kinds of "conditions" you wish to test. Instead of a string, I'd suggest using an enum:
Enum ConditionEnum
LessThan
GreaterThan
Equal
SomeOtherVeryComplicatedBinaryFunction
End Enum
And then define a method that evaluates the condition along with the two arguments:
Public Sub EvaluateConditionWithArguments(ConditionEnum condition, Integer a, Integer b) As Boolean
EvaluateConditionWithArguments = False
Select Case condition
Case ConditionEnum.LessThan
If a < b Then
EvaluateConditionWithArguments = True
End If
...
End Select
End Sub

Passing a string to a database with ToUpper? VB.NET 2010

I'm trying to validate a textbox. If user enters all lower case characters then convert it to all upper case. So when its added to the database its all upper case. I need help with my function, I don't know if its a syntax error or something, here it is. I'm using VB.Net 2010
Public Function CheckLetters(ByVal strIn As String) As Boolean
Dim i As Integer
Dim strOne As String
For i = 0 To Len(strIn) - 1
strOne = strIn.Substring(i, 1).ToUpper
Select Case strOne
Case "A" To "Z"
Case Else
Return False
End Select
Next
Return True
End Function
How 'bout this:
Return Regex.IsMatch(strIn, "^[a-z]*$")
or this
Return strIn.All(Function(c) Char.IsLower(c))
There's no good reason for this method to be anything other than a one-liner. But if you really want to loop through the characters:
For Each c As Char In strIn
If Not Char.IsLower(c) Then Return False
Next c
Return True
Your code runs just fine here (VB does not require the brackets after ToUpper, but it's good for readability) - it accepts a string and returns True if that string only contains the characters "A" through "Z", false otherwise. The function doesn't convert anything - just returns that Boolean result.
If you want to actually convert the string to upper case, just use .ToUpper() on the string itself, e.g.
Dim MyString As String = "Contains some text"
MyString = MyString.ToUpper()
' Above would set MyString to "CONTAINS SOME TEXT"

Dynamic query Linq to xml VB.NET

Hey,
I want to write a query that the "where" in the query is a string something like"
Dim query as string= "Name =xxxx and Date > 10 "
Dim t = from book in doc.Descendants("books") Select _
[Name] = book..value, [Date] = book..value....
Where (query)
I build the query string on run time
Thanks...
I'm not saying this is your case but I see this a lot from people that came from ASP classic where we used to build dynamic SQL strings all of the time. We tend to hope that LINQ will give us some more power in part of the code but let us use strings elsewhere. Unfortunately this isn't true. Where takes a boolean argument and there's no way around that. You can write your own parser that uses reflection and eventually returns a boolean but you'd be writing a lot of code that could be error prone. Here's how you really should do it:
Assuming this is our data class:
Public Class TestObject
Public Property Name As String
Public Property Job As String
End Class
And here's our test data:
Dim Objects As New List(Of TestObject)
Objects.Add(New TestObject() With {.Name = "A", .Job = "Baker"})
Objects.Add(New TestObject() With {.Name = "B", .Job = "President"})
Objects.Add(New TestObject() With {.Name = "C", .Job = "Bus Driver"})
Objects.Add(New TestObject() With {.Name = "D", .Job = "Trainer"})
What you want to do is create a variable that represents the data to search for:
''//This variable simulates our choice. Normally we would be parsing the querystring, form data, XML values, etc
Dim RandNum = New Random().Next(0, 3)
Dim LookForName As String = Nothing
Select Case RandNum
Case 0 : LookForName = "A"
Case 1 : LookForName = "B"
Case 2 : LookForName = "C"
End Select
''//Query based on our name
Dim Subset = (From O In Objects Select O Where (O.Name = LookForName)).ToList()
If sometimes you need to search on Job and sometimes and sometimes you don't you just might have to write a couple of queries:
Dim Subset As List(Of TestObject)
Select Case RandNum
Case 0
Subset = (From O In Objects Select O Where (O.Name = "A" And O.Job = "Baker")).ToList()
Case Else
Select Case RandNum
Case 1 : LookForName = "B"
Case 2 : LookForName = "C"
End Select
Subset = (From O In Objects Select O Where (O.Name = LookForName)).ToList()
End Select
And just to explain writing your own query parser (which is a path that I recommend you DO NOT go down), here is a very, very, very rough start. It only supports = and only strings and can break at multiple points.
Public Shared Function QueryParser(ByVal obj As Object, ByVal ParamArray queries() As String) As Boolean
''//Sanity check
If obj Is Nothing Then Throw New ArgumentNullException("obj")
If (queries Is Nothing) OrElse (queries.Count = 0) Then Throw New ArgumentNullException("queries")
''//Array of property/value
Dim NameValue() As String
''//Loop through each query
For Each Q In queries
''//Remove whitespace around equals sign
Q = System.Text.RegularExpressions.Regex.Replace(Q, "\s+=\s+", "=")
''//Break the query into two parts.
''//NOTE: this only supports the equal sign right now
NameValue = Q.Split("="c)
''//NOTE: if either part of the query also contains an equal sign then this exception will be thrown
If NameValue.Length <> 2 Then Throw New ArgumentException("Queries must be in the format X=Y")
''//Grab the property by name
Dim P = obj.GetType().GetProperty(NameValue(0))
''//Make sure it exists
If P Is Nothing Then Throw New ApplicationException(String.Format("Cannot find property {0}", NameValue(0)))
''//We only support strings right now
If Not P.PropertyType Is GetType(String) Then Throw New ApplicationException("Only string property types are support")
''//Get the value of the property for the supplied object
Dim V = P.GetValue(obj, Nothing)
''//Assumming null never equals null return false for a null value
If V Is Nothing Then Return False
''//Compare the two strings, return false if something doesn't match.
''//You could use String.Compare here, too, but this will use the current Option Compare rules
If V.ToString() <> NameValue(1) Then Return False
Next
''//The above didn't fail so return true
Return True
End Function
This code would allow you to write:
Dim Subset = (From O In Objects Select O Where (QueryParser(O, "Name = A", "Job = Baker"))).ToList()
No, there is nothing directly like what you're looking for where you can pass in a string. As they say, when all you have is a hammer, everything looks like a nail...The real problem is that you need to learn what LINQ is good at and apply it to your code (if it is a good fit), rather than try and make it do what you could with a dynamically built SQL query string.
What you should probably be doing is making those "Where" clauses strongly typed anyway. Your current code has a lot of potential to blow up and be hard to debug.
What you could do instead is something like this (sorry, using C#, been a while since I've touched VB.NET):
var query = from book in doc.Descendants("books")
select book;
if(needsNameComparison)
{
query = query.where(book.Name == nameToCompare);
}
if(needsDateComparison)
{
query = query.Where(book.Date > 10);
}
List<book> bookList = query.ToList();
With LINQ, "query" isn't actually run until the "ToList()" call. Since it uses late execution, the query is dynamic in that it's being built on until it actually needs to run. This is similar to the code you were looking to use before since you were building a query string ahead of time, then executing it at a specific point.