Cannot perform an operation with converted label text - c#

I'm a bit stuck: I am trying to perform an if statement comparing a label.text that originally has a currency string created from .ToString("C");
and a decimal. I have tried converting the label to decimal since I'm going to be comparing it to a decimal but it keeps triggering an exception:
Input string was not in a correct format.
here is my current code:
if(Convert.ToDecimal(SomeLabel.Text) > 1000.00m) { //DO SOMETHING }
//SomeLabel.Text has a value of $1000.00

//SomeLabel.Text has a value of $1000.00
The dollar sign is the reason for the issue. Yoa are probably using a different currency symbol. You can force it with decimal.Parse/decimal.TryParse(which handles invalid input):
string input = "$1000.00";
decimal decimalValue;
if(decimal.TryParse(input, out decimalValue))
{
// using current CurrencySymbol, same as Convert.ToDecimal
Console.WriteLine("Converted successfully: " + decimalValue);
}
else
{
var usCulture = new CultureInfo("en-US");
if (decimal.TryParse(input, NumberStyles.Currency, usCulture, out decimalValue))
{
// using dollar sign as CurrencySymbol
Console.WriteLine("Converted successfully with CultureInfo(en-US): " + decimalValue);
}
else
{
Console.WriteLine("Could not be parsed to decimal");
}
}
Output:
Converted successfully with CultureInfo(en-US): 1000.00
It's worth noting that NumberFormatInfo.InvariantInfo.CurrencySymbol does not return the dollar sign(what i thought) but ¤.

Convert.ToDecimal uses decimal.Parse explicitly this method uses NumberStyles.Number by default.
This is a composite style which includes AllowDecimalPoint but not AllowCurrencySymbol style even if your CurrentCulture's CurrencySymbol is $ and NumberDecimalSeparator is ..
You can use decimal.parse(String, NumberStyles, IFormatProvider) overlaod that takes these as a parameters like;
string s = "$1000.00";
var d = decimal.Parse(s, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint,
CultureInfo.GetCultureInfo("en-US"));
d will be 1000 after parsing.

As per your example. your string value is $1000.00.
This contains a $ sign that's why the compiler is unable to cast string to decimal.
try removing the unusable character by replace. Or try the method below
Regex digitsOnly = new Regex(#"[0-9.]"); // this regex matches only digits and decimal
string decimalnumberstring = digitsOnly.Replace(SomeLabel.Text, "");// replace all non numbers (except decimal) with empty string
then try to convert the string value like below.
if(Convert.ToDecimal(decimalnumberstring) > 1000.00m) { //DO SOMETHING }
hope it helps....

Take the Dollar Sign off of your text first:
Source: $1000
double result = 0M;
String value = SomeLabel.Text.Substring(1);
if (Double.TryParse(value, out result)) {
//
}
return result;

Try this
if(decimal.Parse(SomeLabel.Text) > 1000.00m)
{
}

Related

C# string to Decimal On All style or Culture

Hi I want to find if there is any better way to parse the string to Decimal which covers various format
$1.30
£1.50
€2,50
2,50  €
2.500,00  €
I see a lot of examples using culture to convert . & ,. But in my case, I don't have anything to identify the culture.
This display field I get from the client and I need to extract the value.
I tried following (which didn't work for all scenario) but would like to know if we have any best way to handle this.
Decimal.Parse(value,NumberStyles.Currency |
NumberStyles.Number|NumberStyles.AllowThousands |
NumberStyles.AllowTrailingSign | NumberStyles.AllowCurrencySymbol)
I also tried to use Regex to remove the currency sign but unable to convert both 1.8 or 1,8 in one logic.
Well, assuming you always get a valid currency format, and it's only the culture that changes, you could guess which character is used as a decimal point and which is used as a thousands separator by checking which appears the last in the number. Then remove all the thousand separators and parse it like its culture was invariant.
The code would look like the following:
// Replace with your input
var numberString = "2.500,00 €";
// Regex to extract the number part from the string (supports thousands and decimal separators)
// Simple replace of all non numeric and non ',' '.' characters with nothing might suffice as well
// Depends on the input you receive
var regex = new Regex"^[^\\d-]*(-?(?:\\d|(?<=\\d)\\.(?=\\d{3}))+(?:,\\d+)?|-?(?:\\d|(?<=\\d),(?=\\d{3}))+(?:\\.\\d+)?)[^\\d]*$");
char decimalChar;
char thousandsChar;
// Get the numeric part from the string
var numberPart = regex.Match(numberString).Groups[1].Value;
// Try to guess which character is used for decimals and which is used for thousands
if (numberPart.LastIndexOf(',') > numberPart.LastIndexOf('.'))
{
decimalChar = ',';
thousandsChar = '.';
}
else
{
decimalChar = '.';
thousandsChar = ',';
}
// Remove thousands separators as they are not needed for parsing
numberPart = numberPart.Replace(thousandsChar.ToString(), string.Empty);
// Replace decimal separator with the one from InvariantCulture
// This makes sure the decimal parses successfully using InvariantCulture
numberPart = numberPart.Replace(decimalChar.ToString(),
CultureInfo.InvariantCulture.NumberFormat.CurrencyDecimalSeparator);
// Voilá
var result = decimal.Parse(numberPart, NumberStyles.AllowDecimalPoint | NumberStyles.Number, CultureInfo.InvariantCulture);
It does look a bit of complicated for a simple decimal parsing, but I think should do the work for all the input numbers you get or at least the most of them.
If you do this in some sort of loop, you might want to use compiled regex.
The problem here is that in one case . means decimal point but in other it is a thousnads separator. And then you have , as decimal separator. Clearly, it is impossible for the parser to "guess" what is meant, so the only thing you can do is to decide on some rules on how to handle which case.
If you have control over the UI the best approach would be to validate user input and just reject any value that can't be parsed with an explanation on which format is expected.
If you have no control over the UI, the second best option would be to check for some "rules" and then devise which culture is appropriate for that given input and try to run it through decimal.TryParse for that given culture.
For the given input you have, you could have the following rules:
input.StartsWith("$") -> en-US
input.StartsWith("£") -> en-GB
input.StartsWith("€") || input.EndsWith("€") -> de-DE
These could reasonably handle all cases.
In code:
static void Main(string[] args)
{
string[] inputs =
{
"$1.30",
"£1.50",
"€2,50",
"2,50 €",
"2.500,00 €"
};
for (int i = 0; i < inputs.Length; i++)
{
Console.Write((i + 1).ToString() + ". ");
if (decimal.TryParse(inputs[i], NumberStyles.Currency,
GetAppropriateCulture(inputs[i]), out var parsed))
{
Console.WriteLine(parsed);
}
else
{
Console.WriteLine("Can't parse");
}
}
}
private static CultureInfo GetAppropriateCulture(string input)
{
if (input.StartsWith("$"))
return CultureInfo.CreateSpecificCulture("en-US");
if (input.StartsWith("£"))
return CultureInfo.CreateSpecificCulture("en-GB");
if (input.StartsWith("€") || input.EndsWith("€"))
return CultureInfo.CreateSpecificCulture("de-DE");
return CultureInfo.InvariantCulture;
}
Output:
1.30
1.50
2.50
2.50
2500.00
The only way you could do that is just strip string from symbols and change . and , to decimal separator. Something like:
public decimal UniversalConvertDecimal(string str)
{
char currentDecimalSeparator = Convert.ToChar(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator);
str = str.Replace('.', currentDecimalSeparator);
str = str.Replace(',', currentDecimalSeparator);
StringBuilder builder = new StringBuilder(str.Length);
foreach(var ch in str)
{
if(Char.IsDigit(ch) || ch == currentDecimalSeparator)
builder.Add(ch);
}
string s = builder.ToString();
return Convert.ToDecimal(s);
}
First you have to get current decimal separator from your system.
Then you have to replace . and , with current decimal separator.
Next, you will have to strip the string from any other char than a digit or decimal separator. At the end you can be sure that Convert.ToDecimal is going to work. But I don't know if it is something you want to achieve.
If you need some mechanism to save currency to database, there is a far simpler solution. Just convert this currency to least currency part. For example instead of $1, save 100 cents.
So if you have $1.99, just multiply it by 100 and you will get: 199 cents. And this integer can be saved to db.

Convert decimal currency to comma separated value

I get from a webservice the following strings:
12.95
or
1,200.99
Is there an option to convert these values to the following values without manipulating the string?
12,95
or
1200,99
I tried it with some Culture options but didn't get it right...
EDIT
I tried this:
//return string.Format( "{0:f2}", Convert.ToDecimal( price ) );
//return string.Format(CultureInfo.GetCultureInfo("de-de"), "{0:0}", price);
NumberFormatInfo format = new System.Globalization.NumberFormatInfo();
format.CurrencyDecimalDigits = 2;
format.CurrencyDecimalSeparator = ",";
format.CurrencyGroupSeparator = "";
return decimal.Parse(price).ToString(format);
var input = "1,200.99";
//Convert to decimal using US culture (or other culture using . as decimal separator)
decimal value = decimal.Parse(input, CultureInfo.GetCultureInfo("en-US"));
//Convert to string using DE culture (or other culture using , as decimal separator)
string output = value.ToString(CultureInfo.GetCultureInfo("de-DE"));
Console.WriteLine(output); //1200,99
What about something like this:
double number;
double.TryParse("1,200.99", NumberStyles.Any, CultureInfo.CreateSpecificCulture("en-US"), out number);
var formattedNumber = number.ToString(CultureInfo.CreateSpecificCulture("de-DE"));
Then return or write out formattedNumber (whatever you need to do).
Yes and no. First, what you have is a string, and so you cannot change the formatting of it as you're attempting to. However, to achieve what you would like, you can parse the string into a decimal value and then use the formatting options for decimals to display it in any reasonable way.
You may try for something like this:
String.Format("{0:#,###0}", 0);
or may be like this:
string str = yourNumber.Remove(",").Replace(".",",");
Close enough tronc,
Try this snippet:
String curStr = "12.95";
Decimal decVal;
var valid = Decimal.TryParse(curStr, out decVal);
if (!valid) throw new Exception("Invalid format.");
String newFormat = decVal.ToString("C", System.Globalization.CultureInfo.CreateSpecificCulture("de-DE"));
Within the toString(...) call, you can append a number after 'C' to specify how many decimal places should follow. E.g "C3".

Find Currency Symbol in Currency Data C#

I want to find which Currency Symbol exists in Currency Format data.
For example, Input String = $56.23
public class FormatConverter
{
private CultureInfo _cultureInfo;
public void UpdateCultureInfo()
{
Thread.CurrentThread.CurrentCulture.ClearCachedData();
var thread = new Thread(
s => _cultureInfo = Thread.CurrentThread.CurrentCulture);
thread.Start();
thread.Join();
}
Bool TryParseCurrencySymbolAndValue(string input, out string CurrencySymbol,
out double value)
{
if(_cultureInfo == null)
UpdateCultureInfo();
try{
// Convert Currency data into double
value = Double.Parse(input, NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
// How to extract Currency Symbol?
CurrencySymbol = "$";
return true;
}
catch(Exception ex){ /* Exception Handling */}
return false;
}
}
I want to extract "$" symbol from a string and 56.23 separately and then I want to apply CultureInfo to 56.23 into French Format. The output should be $56,23.
In some cases, input might be "Euro sign" or some other currency symbol in the beginning or in the end of input string.
I know how to convert into CurrentCulture for Numeric part. I don't know how to extract currency Symbol from a string.
It sounds like you already know how to parse the string into a number type (correct me if I'm wrong). You're using double in your example, I would suggest decimal but that's your choice.
To get the currency symbol you can use a simple regular expression
Regex ex = new Regex(#"\p{Sc}");
CurrencySymbol = ex.Match(input).Value;
I hope that helps.
Look at this link as well to give you and idea as to the many different ways you can find and or use IndexOf
[IndexOf String Examples][1]
the question is will the format always have the $ as the first char..? if the answer is yes
regardless of USC or Foreign Currency use the String.IndexOf Method
String.IndexOf("$")
here is a coded example that you may look at
using System;
class Program
{
static void Main()
{
// A.
// The input string.
const string s = "Tom Cruise is an Idiot he should pay $54.95.";
// B.
// Test with IndexOf.
if (s.IndexOf("$") != -1)
{
Console.Write("string contains '$'");
}
Console.ReadLine();
}
}
Output
string contains '$'
Can you please try with?
float curSymbol;
bool isValid = float.TryParse(curValue,
NumberStyles.Currency,
CultureInfo.GetCultureInfo("en-US"), out curSymbol);
Get the curSymbol. :) Be sure to pass currency values with symbol:)

Convert string to decimal with format

I need convert a String to a decimal in C#, but this string have different formats.
For example:
"50085"
"500,85"
"500.85"
This should be convert for 500,85 in decimal. Is there is a simplified form to do this convertion using format?
Some cultures use a comma to indicate the floating point. You can test this with the following code on an aspx page:
var x = decimal.Parse("500,85");
Response.Write(x + (decimal)0.15);
This gives the answer 501 when the thread culture has been set to a culture that uses the comma as floating point. You can force this like so:
var x = decimal.Parse("500,85", new NumberFormatInfo() { NumberDecimalSeparator = "," });
While decimal.Parse() is the method you are looking for, you will have to provide a bit more information to it. It will not automatically pick between the 3 formats you give, you will have to tell it which format you are expecting (in the form of an IFormatProvider). Note that even with an IFormatProvider, I don't think "50085" will be properly pulled in.
The only consistent thing I see is that it appears from your examples that you always expect two decimal places of precision. If that is the case, you could strip out all periods and commas and then divide by 100.
Maybe something like:
public decimal? CustomParse(string incomingValue)
{
decimal val;
if (!decimal.TryParse(incomingValue.Replace(",", "").Replace(".", ""), NumberStyles.Number, CultureInfo.InvariantCulture, out val))
return null;
return val / 100;
}
This will work, depending on your culture settings:
string s = "500.85";
decimal d = decimal.Parse(s);
If your culture does not by default allow , instead of . as a decimal point, you will probably need to:
s = s.Replace(',','.');
But will need to check for multiple .'s... this seems to boil down to more of an issue of input sanitization. If you are able to validate and sanitize the input to all conform to a set of rules, the conversion to decimal will be a lot easier.
Try this code below:
string numValue = "500,85";
System.Globalization.CultureInfo culInfo = new System.Globalization.CultureInfo("fr-FR");
decimal decValue;
bool decValid = decimal.TryParse(numValue, System.Globalization.NumberStyles.Number, culInfo.NumberFormat, out decValue);
if (decValid)
{
lblDecNum.Text = Convert.ToString(decValue, culInfo.NumberFormat);
}
Since I am giving a value of 500,85 I will assume that the culture is French and hence the decimal separator is ",". Then decimal.TryParse(numValue, System.Globalization.NumberStyles.Number, culInfo.NumberFormat,out decValue);
will return the value as 500.85 in decValue. Similarly if the user is English US then change the culInfo constructor.
There are numerous ways:
System.Convert.ToDecimal("232.23")
Double.Parse("232.23")
double test;
Double.TryParse("232.23", out test)
Make sure you try and catch...
This is a new feature called Digit Grouping Symbol.
Steps:
Open Region and Language in control panel
Click on Additional setting
On Numbers tab
Set Digit Grouping Symbol as custom setting.
Change comma; replace with (any character as A to Z or {/,}).
Digit Grouping Symbol=e;
Example:
string checkFormate = "123e123";
decimal outPut = 0.0M;
decimal.TryParse(checkFormate, out outPut);
Ans: outPut=123123;
Try This
public decimal AutoParse(string value)
{
if (Convert.ToDecimal("3.3") == ((decimal)3.3))
{
return Convert.ToDecimal(value.Replace(",", "."));
}
else
{
return Convert.ToDecimal(value.Replace(".", ","));
}
}

What is the best way to convert any currency into decimal in C#?

What is the best way to convert any currency into decimal in C#?
public static decimal returnDecimalFromCurrency(string dataToCheck) {
decimal varValue;
if (!Decimal.TryParse(dataToCheck, NumberStyles.Number | NumberStyles.AllowCurrencySymbol, CultureInfo.CurrentCulture, out varValue)) {
varValue = decimal.MinValue;
}
return varValue;
}
But this one does work for only my current currency. If i pass it EURO currency it won't get converted.
Or the only way is to always check what currency it is and pass proper CultureInfo:
CultureInfo.GetCultureInfo("pl-PL") for zl, or CultureInfo.GetCultureInfo("en-GB") for pounds?
Edit:
Or maybe this is the quick "working" hack?
Decimal.TryParse(dataToCheck.Trim().Replace("zł", "").Replace("€", ""), NumberStyles.Number | NumberStyles.AllowCurrencySymbol, CultureInfo.GetCultureInfo("pl-PL"), out varValue)
But to be honest I don't really like it.
I'd avoid trying to parse the currency with Decimal.TryParse and instead strip off the currency - giving the resultant string to TryParse. Deal with the currency separately - of course, create a function to do this if you need to do it more than once.
Here 's what works for me, I hope it helps you too:
public static decimal Parse(string currencyString)
{
return Parse(currencyString, Thread.CurrentThread.CurrentCulture);
}
public static decimal Parse(string currencyString, CultureInfo culture)
{
currencyString = currencyString.Replace(culture.NumberFormat.CurrencySymbol, System.String.Empty);
var value = Convert.ToDecimal(currencyString, culture);
return value;
}
I solved this same problem with a hybrid approach. The regex to ignore period, comma, parenthesis (in my case I know negatives are in parenthesis), and digits is fairly simple. Just use that to find your symbol, and then build a culture from it. Then parse.
//[^\d\.,()]+ all non-digit, non-period, non-comma, non-parenthesis chars
var regex = new Regex("[^\\d\\.,()]+");
var match = regex.Match(currencyString);
if(match == null){ //throw exception }
var currencySymbol = match.Value;
var cultureInfo = Thread.CurrentThread.CurrentCulture.Clone() as CultureInfo;
cultureInfo.NumberFormat.CurrencySymbol = currencySymbol;
var decimalValue = Decimal.Parse(currencyString, NumberStyles.Currency, cultureInfo);
I ran into this issue today, and I ended up just looping through all of the cultures, and passing each one to the TryParse function.
var myString = "$400.01";
var result = 0.0m;
var culture = System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures)
.First(c => decimal.TryParse(myString, System.Globalization.NumberStyles.Currency, c, out value))
// result = 400.01m

Categories

Resources