3

Any implementation for the next method:

public static decimal StringToDecimal(string sValue)
{
    if (string.IsNullOrEmpty(sValue))
    {
        return 0;
    }
    ...
}

my app imports data from excel or dbf files from other machines, I have no problem reading string data, but I didn't succeded to read properly numeric data especially Price column. The source machine may use comma as decimal separator or any formatting.

decimal.Parse(...) or decimal.TryParse(...) works only if the string format of the numeric value matches the app machine settings.

3
  • 2
    In "any format"? Does that include Elvish? Commented Nov 11, 2013 at 6:52
  • 1
    Give us a list of possible cases. But more likely you want to use CultureInfo.InvariantCulture to threat all numbers in a same (neutral) way. Commented Nov 11, 2013 at 6:53
  • 1
    possible formats: 1 234.56 ___ 1,234.56 ___ 1 234,56 ___ 1.23 ___ 1,23 Commented Nov 11, 2013 at 7:15

2 Answers 2

4

When you call decimal.TryParse or decimal.Parse, you can specify a culture (and therefore avoid just picking up the system settings). You could try each culture you're interested in one at a time until you find one where the value parses successfully.

bool decimal TryParseAllCultures(string text, out value)
{
    foreach (var culture in cultures)
    {
        if (decimal.TryParse(text, NumberStyles.Number, culture, out value))
        {
            return true;
        }
    }
    return false;
}

(You need to decide which cultures to support, and whether NumberStyles.Number is actually the NumberStyle you're interested in.)

Having said that, it's pretty dangerous to do that. Consider "1,234". That could mean "one thousand and twenty-four" in a culture which uses the comma as a thousands separator, or it could mean "just less than one and a quarter" in a culture which uses the comma as a decimal separator. If you're not able to tell which you should use, you could easily go very wrong. If you know the expected range of values, you could use that as heuristic information to check which value you actually want, but it still feels a little worrying to me.

Sign up to request clarification or add additional context in comments.

4 Comments

possible formats: __ 1 234.56 __ 1,234.56 __ 1 234,56 __ 1.23 __ 1,23
@user1104916: So what would "1,234" count as? Bearing in mind it could be equal to "1,234.00"? Or are there always two digits after the decimal point?
Just two digits after the decimal, if any
@user1104916: It's the "if any" which is a pain. Because I suspect "1,23" would be parsed in an English locale as 123. (It wouldn't check that the thousands separator is actually in the right place.)
0

This seems to work

    public static char DecimalSeparator(string sValue)
    {
        var decimalPosition = sValue.Length - 4;
        if (decimalPosition < 0)
        {
            return '.';
        }
        var decimalPart = sValue.Substring(decimalPosition);
        if (decimalPart.Contains(','))
        {
            return ',';
        }
        return '.';
    }

    public static decimal StringToDecimal(string toParse)
    {
        if (string.IsNullOrEmpty(toParse))
        {
            return 0;
        }

        var stb = new StringBuilder();
        var localDecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()[0];
        var sourceDecimalSeparator = DecimalSeparator(toParse);
        var sNumeric = "0123456789-" + sourceDecimalSeparator;

        for (var i = 0; i < toParse.Length; i++)
        {
            var currentChar = toParse[i];
            if (sNumeric.IndexOf(currentChar) > -1)
            {
                if (currentChar == sourceDecimalSeparator)
                {
                    currentChar = localDecimalSeparator;
                }
                stb.Append(currentChar);
            }
        }

        return decimal.Parse(stb.ToString());
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.