Equivalent of function String$() VB.Net? - vb.net

I am migrating an application from VB6 to VB.Net, Which is using the String$() function.
My question is: Which is the "equivalent" of VB6 String$() in following Code?
Dim Symbol As String=""
Dim iRet As Long
iRet = GetLocaleInfo(LCID, LOCALE_SCURRENCY, lpLCDataVar, 0)
Symbol = String$(iRet, 0)
Note that String$() is the function which returns a repeating character string of the length specified:
Syntax:
String$(number, character)
number Length of the returned string.
character Required. Character
code specifying the character or string expression whose first
character is used to build the return string.
(reference)
If I will remove $, It will give me error that "String" is a Class and cannot used as an expression.

This String constructor is the correct way to create a String containing a specific number of a specific character, e.g.
Dim c = "0"c
Dim count = 10
Dim str As New String(c, count)

The equivalent to String$ (in older BASICs) is StrDup (VB.NET).
So, in your case:
Symbol = StrDup(iRet, Chr(0))

The code appears to be getting the currency symbol (and decimal separator) for a culture. It would be better to write it using .NET methods instead of the half-way route of using VB6 in .NET.
For example,
Imports System.Globalization
Module Module1
Sub Main()
Dim lcid = 2057
Dim ci As New CultureInfo(lcid)
Console.WriteLine(ci.EnglishName)
Console.WriteLine(ci.NumberFormat.CurrencySymbol)
Console.WriteLine(ci.NumberFormat.NumberDecimalSeparator)
Console.ReadLine()
End Sub
End Module
outputs
English (United Kingdom)
£
.
There is much more information in the documentation for the CultureInfo Class.

Related

Setting a string format with single quote or double format

how can I correct my method which is currently converting Bytes to Megabite into this form double 90979.32
this is my code:
Public Function BytesToMegabytes(Bytes As Double) As Double
'This function gives an estimate to two decimal
'places. For a more precise answer, format to
'more decimal places or just return dblAns
Dim dblAns As Double
dblAns = (Bytes / 1024) / 1024
BytesToMegabytes = Format(dblAns, "###,###,##0.00")
End Function
I finally need a string in the format: 90979'32.
So I need it to be a single qoute on the format instead of the decimal point.
How can I do this?
Thank you all for your help!
A number only has a format like that when it is presented to the user as a string. Until then it is just a number.
The .ToString method can take a parameter which tells it which culture to use for the formatting.
We can take advantage of that by using an existing culture and modifying it to use an apostrophe as the decimal separator:
Option Strict On
Imports System.Globalization
Module Module1
Public Function BytesToMegabytes(Bytes As Long) As String
'This function gives an estimate to two decimal
'places. For a more precise answer, format to
'more decimal places or just return dblAns
Dim dblAns As Double = (Bytes / 1024) / 1024
Dim ci = New CultureInfo("en-GB")
ci.NumberFormat.NumberDecimalSeparator = "'"
Return dblAns.ToString("###,###,##0.00", ci)
End Function
Sub Main()
Console.WriteLine(BytesToMegabytes(123445568999))
Console.ReadLine()
End Sub
End Module
Outputs:
117,726'87
You probably know the code for the culture that you want to use, so if you used that instead of "en-GB" then there would be no need to set the NumberDecimalSeparator.
If you don't want the commas for number grouping, add in
ci.NumberFormat.NumberGroupSeparator = ""
Note that the Long type is probably better if you're dealing with bytes. The type of the returned value from a function must be the same as in the declaration: using Option Strict On will help you with things like that, and you should set it as the default for new VB.NET projects.
Ref: NumberFormatInfo Class

BC42322 VB.NET Runtime errors might occur when converting 'String' to 'IFormatProvider'

I'm trying to migrate old VB6(Visual Basic 6.0) Project to VB.net framework 4.6x.
But I had to move to .net framework 2.0 first.
I used to convert numbers in TextBox to formatted numbers using ToString as below.
In Visual Studio 2017 .net framework 2.0, I have BC42322 warning.
Is there a way to solve this?
txtDividend.Text = txtDividend.Text.ToString("###,###,##0")
I also have
On Error GoTo Error_Handle
at the start of the function to handle characters in that textbox
The Text property is already a string, and the ToString() method for string doesn't have the overload you want.
Since it seems this same text field can hold both the formatted and unformatted version of a value, what you may want to do is first strip off any formatting, convert to a numeric type like Integer or Decimal, and then use the ToString() method from there:
Public Function FormatDividend(dividend As String) As String
Dim extraCharacters As New Regex("[^\d,.-]")
dividend = extraCharacters.Replace(dividend, "")
Return FormatDividend(CDec(dividend))
End Function
Public Function FormatDividend(dividend As Decimal) As String
Return Dividend.ToString("###,###,##0")
End Function
You can call those functions like this:
txtDividend.Text = FormatDividend(txtDividend.Text)
And of course you can tweak that expression however you want, or change the overload and cast to use Integer instead of Decimal.
Since you are trying to migrate from an environment where "1000".ToString("###,##0") produced 1,000, you will want that to work in your new (.net). That solution is to create an extension method that essentially provides the overload.
<Extension>
Function ToString(input as String, format as String) as String
Static numericOnly As Regex = New Regex("[^\d.-]")
Dim asDec as Decimal
Decimal.TryParse(numericOnly.Replace(input, ""), asDec)
Return asDec.ToString(format)
End Function
Since I have more than one TextBox to use format, I upgraded Joel Coehoorn's answer to use format TextBox in my project.
First, I created CommonFunction.vb module file
Imports System.Text.RegularExpressions
Module CommonFunction
Public Function FormatNumberInText(text As String, format As String) As String
Dim extraCharacters As New Regex("[^\d,.-]")
text = extraCharacters.Replace(text, "")
Return FormatNumberInText(CDec(text), format)
End Function
Public Function FormatNumberInText(text As Decimal, format As String) As String
Return text.ToString(format)
End Function
End Module
and in my TextBox vb file, I used it as below.
txtDividend.Text = FormatNumberInText(txtDividend.Text, "###,###,##0")
txtDividendRatio.Text = FormatNumberInText(txtDividendRatio.Text, "###,###,##0.0#")
Thank you Joel Coehoorn.
It appears that the ToString() Method is designed to convert other types to a string and format them as desired. It was not designed to format an existing string. The simplest way I have found around this problem is to convert your string into another data type and then apply the ToString() Method.
So in your case I would convert to a double using the CDbl() Method:
txtDividend.Text = CDbl(txtDividend.Text).ToString("###,###,##0")

Validating a string

I am trying to write a program where the user inputs a telephone number and a message is displayed if it contains a letter.
Module Module1
Sub Main()
Dim TelNumber As String
Dim Character As String
TelNumber = Console.ReadLine()
For Number = 0 To TelNumber.Length - 1
Character = TelNumber.Substring(Number)
If Integer.TryParse(Character, 0) <> 0 Then
Console.WriteLine("It cannot contain a letter")
Exit For
End If
Next
Console.ReadLine()
End Sub
End Module
However with this code even it only works properly if the string contains less than 11 charcaters, after that even if it does not contain any letters it still displays the message. How do I fix this? Also I don't understand what the second parameter of the Integer.TryParse function represents?
TelNumber.Substring(Number) does not just the Numberth character of the string.
It returns the string with Number characters stripped off its beginning.
Thus, in the first step of the loop, TelNumber.Substring(0) returns the whole string.
Then, Integer.TryParse() fails with integer overflow with long string.
Hint: simple string validation is a task for regular expressions.
With regular expressions it will also be very easy to extend tel.number format to something like +4915771828000 or 12-34-56.
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim telNumber As String = Console.ReadLine()
Dim telValidationRegex As Regex = New Regex("^\d+$")
If NOT telValidationRegex.Match(telNumber).Success Then
Console.WriteLine("Wrong telephone number format")
End If
Console.ReadLine()
End Sub
End Module
I don't have a compiler handy, but I can tell you what I think this should look like. First let's look at Int32.TryParse's documentation
result
Type: System.Int32
When this method returns, contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is null or String.Empty, is not of the correct format, or represents a number less than MinValue or greater than MaxValue. This parameter is passed uninitialized.
So, the second parameter is supposed to be an integer variable that contains the result of trying to parse the string.
Then, let's look at substring
startIndex
Type: System.Int32
The zero-based starting character position of a substring in this instance.
So what you're doing isn't looking at each character and trying to convert it to an integer. It's looking at the whole number, and trying to convert that to an integer. Then the whole number, except for the first character, and trying to convert that to a number. And so on.
I suspect you'll find that Int32 can only store numbers about 10 digits long (2^32, or 4294967296)
What you want to do is look at each character, something like this.
Module Module1
//Warning, did not try to compile
Sub Main()
Dim TelNumber As String
Dim Character As String
TelNumber = Console.ReadLine()
For Number = 0 To TelNumber.Length - 1
Character = TelNumbert(Number)
Dim OutputNumber as Integer
If Not Integer.TryParse(Character, OutputNumber) Then
Console.WriteLine("It cannot contain a letter")
Exit For
End If
Next
Console.ReadLine()
End Sub
End Module

Evaluate mathematical expression from a string using VB

I want to calculate a arithmetic expression from a string using VB, any ideas ?
As an example : "x+2" from a textbox, I want to evaluate the expression
Dim equation As String = "2+6/2"
Dim result = New DataTable().Compute(equation, Nothing)
you can use NCalc for this. It also accepts parameters like x, y, z,...
Dim e As Expression = new Expression("2 + 3 * 5")
Msgbox(17 = e.Evaluate())
You can use mxparser library for this purpose.Give a reference to mxparser.dll in your project by clicking ADD Reference button of Microsoft Visual Studio.The mxparser library source code or latest dll file can be from www.mathparser.org.The mXparser is a Math Parser for Java, Android, C# .NET (CLS) Libraries.
Imports org.mariuszgromada.math.mxparser
Private Function evaluate(ByVal str As String) AS Double
Dim expr As Expression = New Expression(str)
DIM d1 As Double
d1=0
d1=expr.calculate()
return d1
End Function
Call to the function can be as follows.
DIM str as String
str=""
str=((45^5)/45))*(5*6)
Dim d as Double
d=0
d=evaluate(str)
MsgBox(" The result of the expression is " + d.ToString)

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)