What does concatenating an empty string to a string do? - vba

I've come across this convention in some code I'm editing where they frequently concatenate an empty string to an existing string when assigning it to another variable.
For example:
Dim var1
Dim var2 = "string"
var1 = var2 & ""
I can't think of a reason why they would do this since & already makes the result a string. Is there any reason why this is done?

I can't think of a reason to do it exactly as you show, but this is a pattern you sometimes see used to coerce something into a string type - for example when working with database recordsets:
blah = rs.Fields("foo").Value & ""
where there's a chance that the field value may be null and you just want an empty string instead.
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/ampersand-operator
If an expression is not a string, it is converted to a String variant.
The data type of result is String if both expressions are string
expressions; otherwise, result is a String variant.
If both expressions are Null, result is Null. However, if only one
expression is Null, that expression is treated as a zero-length string
("") when concatenated with the other expression. Any expression that
is Empty is also treated as a zero-length string.

Related

How to split and trim a string in one line

I want to Split a string and then Trim the results in one single line.
So the string:
"psychology ¦ history ¦ geography"
should return the following members without trailing or leading spaces:
psychology
history
geography
I've tried:
String.Split("¦").Trim
but Trim does not work for arrays. Is there a one-line method, no matter how dirty, that does this job?
I'm sure this has been duped many times but I couldn't find the relevant solution for VB.Net. Please don't just link to a question in another language without explaining how I can convert the solution to VB.Net.
You can Split and Trim your string in one line using the LINQ's Select method.
Both assigning the string to a local variable:
Dim input As String = "psychology ¦ history ¦ geography"
Dim result1 = input.Split("¦"c).Select((Function(s) s.Trim))
Or directly using the string as source:
Dim result2 = "psychology ¦ history ¦ geography".Split("¦"c).Select((Function(s) s.Trim))
Note that the Type of result1 and result2 is now an IEnumerable(Of String), not an array:
LINQ's methods return a IEnumerable<T> if not otherwise instructed.
Also note that this syntax supposes that Option Infer is On. If you keep it Off, you need to declare the type explicitly:
Dim result As IEnumerable(Of String) = (...)
If you need a string Array as output, you need to ask:
Dim result3 As String() = input.Split("¦"c).Select((Function(s) s.Trim)).ToArray()
About the Type Characters (c) appended to the Split method parameter:
From the Visual Basic Language Reference: Char Data Type
Type Characters. Appending the literal type character C to a
single-character string literal forces it to the Char data type. Char
has no identifier type character.
If you don't have embedded spaces in the items, you can just pass the space character as a separator as well as pipe. Combine that with the remove empty entries option and multiple space separators aren't an issue. If you need to handle other whitespace characters, you can add those.
input.Split(New String() {"|", " "}, StringSplitOptions.RemoveEmptyEntries)

VB.net Issue with a string comparison failing

Below is the snippit of code that is having the trouble.
Private Const DOB_VALUE As Integer = 0
Private Const ADDRESS_VALUE As Integer = 1
Private Const NAME_VALUE As Integer = 2
For Each oRecord As KeyValuePair(Of Integer, String) In OriginalFileInfo
For Each nRecord As KeyValuePair(Of Integer, String) In WorkingFileInfo
Dim OriginalComparisonStringSubstrings As String() = oRecord.Value.ToString.ToLower.Split(":")
Dim WorkingComparisonStringSubstrings As String() = nRecord.Value.ToString.ToLower.Split(":")
' Are dates of birth the same?
If OriginalComparisonStringSubstrings(DOB_VALUE) Like WorkingComparisonStringSubstrings(DOB_VALUE) Then
' Are the address the same?
If OriginalComparisonStringSubstrings(ADDRESS_VALUE) Like WorkingComparisonStringSubstrings(ADDRESS_VALUE) Then
' Dob and address are the same, means we have a valid match. Lets check if the names match
If OriginalComparisonStringSubstrings(NAME_VALUE) Like WorkingComparisonStringSubstrings(NAME_VALUE) Then
' dob, address and name matches
Else
' Dob and address matches, name does not
End If
End If
End If
Next
Next
The issue is, when I get to the address value comparison, it is always failing. I have had my watch window active and the values are identical yet they do not compare. You can see my Watch window output below.
- WorkingComparisonStringSubstrings {Length=3} String()
(0) "4323" String
(1) "123 somewhere lane" String
(2) "j ii" String
- OriginalComparisonStringSubstrings {Length=3} String()
(0) "4323" String
(1) "123 somewhere lane" String
(2) "j ii j. .johnson" String
OriginalComparisonStringSubstrings(DOB_VALUE) Like WorkingComparisonStringSubstrings(DOB_VALUE) True Boolean
OriginalComparisonStringSubstrings(ADDRESS_VALUE) Like WorkingComparisonStringSubstrings(ADDRESS_VALUE) False Boolean
OriginalComparisonStringSubstrings(NAME_VALUE) Like WorkingComparisonStringSubstrings(NAME_VALUE) False Boolean
The comparison for the two addresses, which would be ("123 somewhere lane" Like "123 somewhere lane") should be true but is returning false. My question is why are these values failing in comparison when they are so apparently equal? In my code I am using "Like" comparisons but I have also tried String.Compare, StrComp, .Equals, =, and every other variation of comparison. In addition, the values are always a string from the time they are inserted into the FileInfo variable to the time they are split and compared.
Anyone have an idea of why they wont compare?
My colleague pointed out the issue. In the previous version of the program, we were dynamically changing the value of ADDRESS_VALUE. In this most recent version is when we changed the the values to a constant integer.
It appears in this version, before we made ADDRESS_VALUE constant, it was still being assigned a new value, so it was actually comparing the NAME_VALUE rather than comparing the ADDRESS_VALUE which would in fact fail.
Thank you everyone for your comments. They were really helpful.

converting integer to decimal values while adding both

I am working on a vb.net application.
My code is the following:
txtTotalPrevious.Text = Val(txtTotalPrevious.Text) + Val(txtoldtotal.text)
my values are:
txtTotalPrevious.Text=187.0000
txtoldtotal=3
I get the result
result =190
but my expected result is:
result=190.0000
What is the issue in my logic?
You can use String.Format if you want to output string be like you want:
Dim str1 As String = "187.0000"
Dim str2 As String = "3"
Dim resultString As String = String.Format("{0:0.0000}", Val(str1) + Val(str2))
' And the result will be 190.0000
And if you want the double result:
Dim resultDouble as Double= Val(str1) + Val(str2)
' And the result will be Double 190
EDIT
Based on varocarbas comments you should consider some notes:
Avoid using Val method
The Val function stops reading the string at the first character it
cannot recognize as part of a number. Symbols and characters that are
often considered parts of numeric values, such as dollar signs and
commas, are not recognized. However, the function recognizes the radix
prefixes &O (for octal) and &H (for hexadecimal). Blanks, tabs, and
linefeed characters are stripped from the argument.
The following call
returns the value 1615198.
Val(" 1615 198th Street N.E.")
The Val function recognizes only the period (.) as a valid decimal
separator. When different decimal separators are used, as in
international applications, use CDbl or CInt instead to convert a
string to a number. To convert the string representation of a number
in a particular culture to a numeric value, use the numeric type's
Parse(String, IFormatProvider) method. For example, use Double.Parse
when converting a string to a Double.
As a VB.Net Programmer use & instead of + for string concatenation
When you use the + operator, you might not be able to determine
whether addition or string concatenation will occur. Use the &
operator for concatenation to eliminate ambiguity and to provide
self-documenting code.

using IndexOf in Mid function

Perhaps this is a simple solution for most, but I can't get this to work like it should according to syntax.
I have this line of text "Part Number123456Price$50.00"
I want to pull the part number out of it, so I use this function...
str = Mid(str, str.IndexOf("Part Number") + 12, str.IndexOf("Price"))
My results are str = "123456Price$50.0" every time. I know the part number can vary in length so I need a solid solution of pulling this out.
It can be confusing to mix the legacy VB string methods (such as Mid) with the .Net string methods (like IndexOf). The VB methods use 1 as the index of the first character while the .Net methods use 0.
The following code will extract the part number from a string
Dim str As String = "Part Number123456Price$50.00"
Dim iPart As Integer = str.IndexOf("Part Number") + 11
Dim iPrice As Integer = str.IndexOf("Price")
str = str.Substring(iPart, iPrice - iPart).Trim
The Mid() function of Visual Basic is documented as having three arguments: (1) a string, (2) the beginning location in the string, and (3) the number of characters to copy.
So if your string is "Part Number123456Price$50.00" and you want to pull the part number as a series of digits, the "123456" part of the string, using the Mid() function then you need to find the beginning of the part number digit string and to then know the number of digits.
If your string is in the variable str then you can find the offset by something like str.IndexOf("Number") + len("Number") which will provide the offset to after the string "Number".
Next you need to find the number of digits so you would do something like str.IndexOf("Price") to find where the text "Price" begins and then subtract from that offset the offset of where the digits begin.
The result of all of this is you need a bit of code something like the following. I have not tested this source as I am not a VB programmer so it may need a tweak and you might want to put some checks on data validity as well.
Dim TextNumber as String = "Number"
Dim TextPrice as String = "Price"
iOffset = str.IndexOf(TextNumber) + len(TextNumber)
str = Mid(str, iOffset, str.IndexOf(TextPrice) - iOffset)
Alternatively, if Price is always the format $00.00, this will also work.
Dim str as String = "Part Number123456Price$50.00"
str = str.Remove(str.IndexOf("Price"))

Comparing Strings - ASCII SPACE

What is the difference between doing this:
Dim strTest As String
If strTest > " " Then
End If
and this:
Dim strTest As String
If strTest <> "" Then
End If
I think that code sample 1 is comparing ASCII values (the ASCII code of a SPACE is 32). I have looked through the String section on MSDN but I am unable to find an answer.
Update
I am also confused about what happens here:
Dim strTest As String = "Test"
If strTest > " " Then
End If
The > (greater than) operator will test by alphabetical order or character code value order (depending on the Option Compare setting), whereas the <> (not equal) operator tests for equality. As long as the two strings are different at all, then <> will always evaluate to True. > will evaluate to true as long as the string on the right side of the operator comes after the first string alphabetically, or by character code value. Therefore:
Option Compare Text ' Compare strings alphabetically
...
Dim x As String = "Hello"
Dim y As String = "World"
If x <> y Then
' This block is executed because the strings are different
Else
' This block is skipped
End If
If x > y Then
' This block is skipped
Else
' This block is executed because "Hello" is less than "World" alphabetically
End If
In your question, however, you are comparing a null string variable (set to Nothing) with an empty string. In that case, the comparison operators treat a null variable as an empty string. Therefore, Nothing <> "" should evaluate to False because both sides of the operator are considered empty strings. An empty or null string should always be considered the first in the sort order, so Nothing > "Hello" should evaluate to False because an empty string comes before everything else. But, Nothing > "" should evaluate to False because they are both equal and therefore neither comes before or after the other.
To answer you final question, "Test" > " " will test if the letter T comes before or after a space. If Option Compare is set to Text, it will compare them alphabetically and should return True (this ultimately depends on the alphabetic sorting for your locale). If Option Compare is set to Binary, it will compare them based on their character code values. If they are ASCII strings, a space character has a lower value than a letter, like T, so it, also, should return True.