How to use NumberFormatInfo to remove parenthesis for negative values
Asked Answered
A

6

11

We're currently using the following for creating US dollar values in our web application:

string.Format("{0:C0}", dollarValue );

In this example, if dollarValue is 145, then we'll see: $145. If it is -145, then we'll see ($145) rather than -$145. Note that for us, dollarValue is a double, but it could be any number-type. I think.

Anyway, what I want is for it to be either $145 or -$145.

Now, according to my research, it might be possible to do this using the NumberFormatInfo class. I can't figure out how to use it, and I can't find any valid example. I did see this question here: C# creating a custom NumberFormatInfo to display "Free" when a currency value is $0.00 but the example from MSDN linked to from this question seems a bit different from what I really want to do.

I realize, I will need to do something of the following:

double dollarValue = -145d;
string myMoney = dollarValue.ToString( "C0", someIFormatProvider );

where someIFormatProvider is likely of type NumberFormatInfo. Now, what I've done is this:

NumberFormatInfo ni = new NumberformatInfo();
ni.CurrencyNegativePattern = 1; // The value 1 should mean not to use parenthesis
string myMoney = dollarValue.ToString( "C0", ni );

...and I get an "Instance is Read-Only" exception. While the "documentation" for the CurrencyNegativePattern property says you can SET and GET the value, apparently, you can't. Also, NumberFormatInfo is a sealed class. I can't easily create a new class based off it and override the value.

I'm at a loss as to how to deal with this. Right now, my workaround is to just negate my negative value and have a positive result that I do the string.Format(...) again. Yes, I realize there is no negative sign in front of this, but, of course, that's easily resolved by adding a "-" in front of the result as needed.

Would someone be able to provide me with a working example of how to effectively use the NumbefFormatInfo class correctly in this situation? Thanks.

Astronautics answered 13/6, 2012 at 12:32 Comment(2)
Are you sure the error comes from setting the CurrencyNegativePattern of a NumberFormatInfo instance? I've seen this Read-Only exception, but it is raised from trying to modify the CurrentUICulture properties?Dacy
The code works for me (after fixing the case on NumberformatInfo)Gangplank
C
2
double dollarValue = -145d;
 System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
 string mymoney = dollarValue.ToString("C", modCulture);
          MessageBox.Show(mymoney);

If your Operating System current culture is en-US then you dont need the following line

System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");

The code will be

double dollarValue = -145d;
string mymoney = dollarValue.ToString("C");

and If you want to do with NumberFormatInfo

double dollarValue = -145d; 
System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
     NumberFormatInfo number = modCulture.NumberFormat;
     string mymoney = dollarValue.ToString("C", number);

another way

double dollarValue = -145d;
System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
NumberFormatInfo number = modCulture.NumberFormat;
string mymoney = dollarValue.ToString(String.Format("C",number));
Console.WriteLine(mymoney);
Contraposition answered 13/6, 2012 at 12:41 Comment(4)
And here's the doc.Singapore
I tried this answer in a console app for testing and the result was ($145). If I used "C" instead of "0:C0", for the format, I got ($145.00).Astronautics
Okay, the NumberFormatInfo answer you provided works if I set the CurrencyNegativePattern to 1. This also correctly sets the currency symbol which isn't properly set if I don't use the culture. Good job.Astronautics
@Contraposition thank you for your answer. I think there is a missing part in your code, this is, the part where you specify "number.CurrencyNegativePattern = 1" in order to remove the parenthesis. See this answer: https://mcmap.net/q/972537/-how-to-use-numberformatinfo-to-remove-parenthesis-for-negative-valuesEbb
S
13

You can make a clone of the NumberFormat property in the CurrentCulture (this will ensure that you keep the correct currency symbol if you globalize your application). After that, just set the CurrencyNegativePattern property to the desired value and pass in your NumberFormatInfo in the double.ToString() function, like so:

NumberFormatInfo noParens = (NumberFormatInfo)CultureInfo.CurrentCulture.NumberFormat.Clone();
noParens.CurrencyNegativePattern = 1;
double dollarValue = -145d;
string output = dollarValue.ToString("C0", noParens); // outputs -$145
Span answered 13/6, 2012 at 12:51 Comment(2)
Interesting. Thank you, this worked. I am glad to see I wasn't too far off on the overall implementation. I just didn't know I needed to clone it.Astronautics
This will also allow you to use the current culture, so you don't have to hard-code it to "en-US" in case you end up globalizing your web application.Span
N
4

Try this...

string.Format( "{0:$#.;-$#.}", -145 )

or

dollarValue.ToString("$#.;-$#.")
Napkin answered 13/6, 2012 at 12:38 Comment(3)
You need to swap the $ and the -.Singapore
And of course, string.Format("{0:$#.;-$#.}", dollarValue) is equivalent to dollarValue.ToString("$#.;-$#.") in the same way as string.Format("{0:C0}", dollarValue) is equivalent to dollarValue.ToString("C0").Singapore
@Jeppe format fixed....thanks for the catch...and I like your second option a bit better...changed to reflect this.Napkin
C
2
double dollarValue = -145d;
 System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
 string mymoney = dollarValue.ToString("C", modCulture);
          MessageBox.Show(mymoney);

If your Operating System current culture is en-US then you dont need the following line

System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");

The code will be

double dollarValue = -145d;
string mymoney = dollarValue.ToString("C");

and If you want to do with NumberFormatInfo

double dollarValue = -145d; 
System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
     NumberFormatInfo number = modCulture.NumberFormat;
     string mymoney = dollarValue.ToString("C", number);

another way

double dollarValue = -145d;
System.Globalization.CultureInfo modCulture = new System.Globalization.CultureInfo("en-US");
NumberFormatInfo number = modCulture.NumberFormat;
string mymoney = dollarValue.ToString(String.Format("C",number));
Console.WriteLine(mymoney);
Contraposition answered 13/6, 2012 at 12:41 Comment(4)
And here's the doc.Singapore
I tried this answer in a console app for testing and the result was ($145). If I used "C" instead of "0:C0", for the format, I got ($145.00).Astronautics
Okay, the NumberFormatInfo answer you provided works if I set the CurrencyNegativePattern to 1. This also correctly sets the currency symbol which isn't properly set if I don't use the culture. Good job.Astronautics
@Contraposition thank you for your answer. I think there is a missing part in your code, this is, the part where you specify "number.CurrencyNegativePattern = 1" in order to remove the parenthesis. See this answer: https://mcmap.net/q/972537/-how-to-use-numberformatinfo-to-remove-parenthesis-for-negative-valuesEbb
V
2

'instance is ReadOnly' means you have a read-only instance of NumberFormatInfo. You can get a writable instance by cloning a read-only instance:

NumberFormatInfo writeable = (NumberFormatInfo) ni.Clone();
V2 answered 13/6, 2012 at 12:43 Comment(0)
I
1

Are you sure the CurrencyNegativePattern can't be assign? I've tried with this code:

double dollarValue = -145d;
System.Globalization.NumberFormatInfo ni = new System.Globalization.NumberFormatInfo();
ni.CurrencyNegativePattern = 1;
dropDownList.Items.Add(new ListItem(dollarValue.ToString("C0", ni)));

and it's success.

Interlude answered 13/6, 2012 at 12:43 Comment(0)
P
1

To make sure you remain in a "US-context" I'd do something like this:

double val = -145d;
NumberFormatInfo nfi = new CultureInfo("en-US").NumberFormat;
nfi.CurrencyNegativePattern = 1;
val.ToString("C0", nfi).Dump();

The Dump comes from LinqPad, which displays -$145 as a result.

The error you are getting feels like it comes from you getting your NumberFormatInfo something like this:

NumberFormatInfo nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;

In which case I'd replace by something like this:

NumberFormatInfo nfi = (NumberFormatInfo)Thread.CurrentThread.CurrentCulture.NumberFormat.Clone();
Parthenia answered 13/6, 2012 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.