VBA CSng(string) wrong format - vba

I read in a node from a xml file and try to parse one of its attributes to a single.
Dim x_coord_single As Single
Dim x_coord_string As String
x_coord_string = node.Attributes.getNamedItem("x_coord").Text
x_coord_single = CSng(x_coord_string )
After i assign x_coord_string it equals "9.0647"
But the CSng function returns 90647
I would expect x_coord_single to be 9.0647.
I tried CSng("9.0647") directly but it's the same outcome.
Any suggestions on why it is not?
I'm working with MS Access 2010 if it affects this anyhow.

Try like this:
Public Function fnStrChangeCommas(ByVal myValue As Variant) As String
fnStrChangeCommas = Replace(CStr(myValue), ".", ",")
End Function
x_coord_single = CSng(fnStrChangeCommas(x_coord_string ))
It should work, because your language regional settings use , as a decimal separator and the VBEditor uses the ..
To see the separators your system is using in VBA, run the following code:
Public Sub TestMe()
Debug.Print "Decimal separator: "; Application.DecimalSeparator
Debug.Print "Thousands separator: "; Application.ThousandsSeparator
End Sub
If it returns this:
Decimal separator: ,
Thousands separator: .
Then you may consider using the fnStrChangeCommas function.

The simple and universal method is to use Val:
x_coord_single = CSng(Val(x_coord_string))

Related

VB.net regex exclude certain characters from string

I am using regex.ismatch to check a string doesn't contain any one of a list of characters such as £&+(/?!;:* And also a quotation mark " not sure how to place that...
But can't get to to work...
If Regex.ismatch(Line, "^[^##£&+()*']"). Then
Msgbox("error")
End If
But doesn't work for me?
Any suggestions
You could do this pretty easily without Regex by simply doing something like this:
Public Shared Function HasSpecialChars(ByVal str As String) As Boolean
Const specialChars As String = "!##$%^&*()"
Dim indexOf As Integer = str.IndexOfAny(specialChars.ToCharArray())
Return indexOf <> -1
End Function

Good method to parse value from PowerPivot PivotItem?

I have a PivotItem with the following .name and .value properties:
[dimCalendar].[MonthName].&[April 2013]
I am only interested in the part where it says April 2013.
What is a good method to parse or otherwise get this value from the PivotItem?
Solution one: Split and replace
Split would be best with [ as the delimiter character. Get the upper bound of the Split array and replace the trailing ] with "".
Solution two: regular expressions
Add Microsoft VBregularexpression 5.5 as a reference.
Private Function Method(str As String) As String
Dim regexp As New regexp
regexp.Pattern = "\[.*\]\[.*\]\[(.*)\]"
Method = regexp.Replace(str, "$1")
End Function
If you only need the last one, this will work nicely :
Sub test_user1283776()
MsgBox get_PivotItem_From_PowerPivot("[dimCalendar].[MonthName].&[April 2013]")
End Sub
Function get_PivotItem_From_PowerPivot(PowerString As String) As String
Dim A() As String
A = Split(PowerString, ".&[")
get_PivotItem_From_PowerPivot = Trim(Replace(A(UBound(A)), "]", ""))
End Function

How to extract numbers UNTIL a space is reached in a string using Excel 2010?

I need to pull the code from the following string: 72381 Test 4Dx for Worms. The code is 72381 and the function that I'm using does a wonderful job of pulling ALL the numbers from a string and gives me back 723814, which pulls the 4 from the description of the code. The actual code is only the 72381. The codes are of varying length and are always followed by a space before the description begins; however there are spaces in the descriptions as well. This is the function I am using that I found from a previous search:
Function OnlyNums(sWord As String)
Dim sChar As String
Dim x As Integer
Dim sTemp As String
sTemp = ""
For x = 1 To Len(sWord)
sChar = Mid(sWord, x, 1)
If Asc(sChar) >= 48 And _
Asc(sChar) <= 57 Then
sTemp = sTemp & sChar
End If
Next
OnlyNums = Val(sTemp)
End Function
If the first character in the description part of your string is never numeric, you could use the VBA Val(string) function to return all of the numeric characters before the first non-numeric character.
Function GetNum(sWord As String)
GetNum = Val(sWord)
End Function
See the syntax of the Val(string) function for full details of it's usage.
You're looking for the find function.. Example:
or in VBA instr() and left()
Since you know the pattern is always code followed by space just use left of the string for the number of characters to the first space found using instr. Sample in immediate window above. Loop is going to be slow, and while it may validate they are numeric why bother if you know pattern is code then space?
In similar situations in C# code, I leave the loop early after finding the first instance of a space character (32). In VBA, you'd use Exit For.
You can get rid of the function altogether and use this:
split("72381 Test 4Dx for Worms"," ")(0)
This will split the string into an array using " " as the split char. Then it shows us address 0 in the array (the first element)
In the context of your function if you are dead set on using one it is this:
Function OnlyNums(sWord As String)
OnlyNums = Split(sWord, " ")(0)
End Function
While I like the simplicity of Mark's solution, you could use an efficient parser below to improve your character by character search (to cope with strings that don't start with numbers).
test
Sub test()
MsgBox StrOut("72381 Test 4Dx")
End Sub
code
Function StrOut(strIn As String)
Dim objRegex As Object
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Pattern = "^(\d+)(\s.+)$"
If .test(strIn) Then
StrOut = .Replace(strIn, "$1")
Else
StrOut = "no match"
End If
End With
End Function

How to filter anything but numbers from a string

I want to filter out other characters from a string as well as split the remaining numbers with periods.
This is my string: major.number=9minor.number=10revision.number=0build.number=804
and this is the expected output: 9.10.0.804
Any suggestions?
As to my comment, if your text is going to be constant you can use String.Split to remove the text and String.Join to add your deliminators. Quick example using your string.
Sub Main()
Dim value As String = "major.number=9minor.number=10revision.number=0build.number=804"
Dim seperator() As String = {"major.number=", "minor.number=", "revision.number=", "build.number="}
Console.WriteLine(String.Join(".", value.Split(seperator, StringSplitOptions.RemoveEmptyEntries)))
Console.ReadLine()
End Sub
If your string does not always follow a specific pattern, you could use Regex.Replace:
Sub Main()
Dim value as String = "major.number=9minor.number=10revision.number=0build.number=804"
Dim version as String = Regex.Replace(value, "\D*(\d+)\D*", "$1.") ' Run the regex
version = version.Substring(0, version.Length - 1) ' Trim the last dot
End
Note you should Imports System.Text.RegularExpressions.

How to update Format function from VB to VB.NET

I am trying to port a VB function to VB.NET, but I cannot get the function to work correctly and update properly.
rFormat = Format(Format(Value, fmt), String$(Len(fmt), "#"))
It seems like the problem lies with the String$() function parameter which is used to align decimal points of values. How would I be able to properly fix this, or is there another way to achieve this?
EDIT
The following is an example console application that shows the issues that I am having.
Imports Microsoft.VisualBasic
Module Module1
Sub Main()
Dim rFormat As String
Dim fmt As String
Dim value As Object
fmt = "########.000"
value = 12345.2451212
'value = 12345
'~~~~~~~~~~~~~~~~~~~~~
'rFormat = Microsoft.VisualBasic.Format(Microsoft.VisualBasic.Format(value, fmt), "".PadLeft(fmt.Length, "#"c))
'Console.WriteLine(rFormat) ' <<Not working prints all "#" for any value!>>>
'rFormat = Microsoft.VisualBasic.Format(Microsoft.VisualBasic.Format(value, fmt), "".PadLeft(fmt.Length))
'Console.WriteLine(rFormat) '<<Not working prints nothing>>
'rFormat = (String.Format(value, fmt)).PadLeft(Len(fmt))
'Console.WriteLine(rFormat) ' <<Not working prints the value 12345.2451212>>> should print>>>>> 12345.245
'for integer values< works good>
rFormat = String.Format("{0," + fmt.Length.ToString + "}", String.Format(value, fmt))
Console.WriteLine(rFormat) ' <<Not working prints the value 12345.2451212>>> should print>>>>> 12345.245
'for integer values< works good>
End Sub
End Module
All String$ does is repeat the character specified in the second parameter the number of times specified in the first parameter.
So if fmt is, for example "9999", then the String$ command will produce "####".
You can replace this with the String.PadLeft method and continue to use the VB Format function from the Microsoft.VisualBasic namespace:
rFormat = Microsoft.VisualBasic.Format(Microsoft.VisualBasic.Format(value, fmt), "".PadLeft(fmt.Length, "#"c))
EDIT:
Based on the edit in the question, the correct format logic should be:
rFormat = String.Format("{0:" & fmt & "}", value)
It is very helpful to review the String.Format documentation since it has a lot of examples and explanation.
It sounds like you're wanting to pad out your results so they are a fixed length. How about using the String.PadLeft Method or the String.PadLeft(int32,char) Method to Pad out rFormat.
Something like this for spaces:
rFormat = (String.Format(value, fmt)).PadLeft(Len(fmt))
Edit
Boy is it hard to find VB6 documentation online. It appears that the # in a VB6 Custom Format has to do with String justification per this Forum posting and this SO answer they suggest something something like this.
rFormat = String.Format("{0," + fmt.Length.ToString + "}", String.Format(value, fmt))
This is using the Composite Formatting Alignment Component
Alignment Component
The optional alignment component is a signed integer indicating the preferred formatted field width. If the value of alignment is less than the length of the formatted string, alignment is ignored and the length of the formatted string is used as the field width. The formatted data in the field is right-aligned if alignment is positive and left-aligned if alignment is negative. If padding is necessary, white space is used. The comma is required if alignment is specified.
The main issue that I see in your updated example is that you are using an object to store your Double. By changing values declaration to a Decimal and changing the format function I was able to get it to work.
Sub Main()
Dim rFormat As String
Dim fmt As String
Dim value As Double
fmt = "#######0.000"
value = 12345.2451212
rFormat = String.Format("{0," + fmt.Length.ToString + "}", value.ToString(fmt))
Console.WriteLine(rFormat)
Console.ReadLine()
End Sub
In VBNet, you can also do this:
Dim rFormat As String = String.Empty
Dim fmt As String = "########.000"
Dim value As Object = 12345.2451212
rFormat = (CDbl(value)).ToString(fmt)