How do I get NumberFormat.getCurrencyInstance()
to print negative USD currency values with a minus sign?

- 725
- 3
- 7
- 13
7 Answers
It requires a little tweaking of the DecimalFormat returned by NumberFormat.getCurrencyInstance()
to do it in a locale-independent manner. Here's what I did (tested on Android):
DecimalFormat formatter = (DecimalFormat)NumberFormat.getCurrencyInstance();
String symbol = formatter.getCurrency().getSymbol();
formatter.setNegativePrefix(symbol+"-"); // or "-"+symbol if that's what you need
formatter.setNegativeSuffix("");
IIRC, Currency.getSymbol()
may not return a value for all locales for all systems, but it should work for the major ones (and I think it has a reasonable fallback on its own, so you shouldn't have to do anything)

- 14,482
- 7
- 57
- 72
Here is one I always end up using either in a java class or via the fmt:formatNumber jstl tag:
DecimalFormat format = new DecimalFormat("$#,##0.00;$-#,##0.00");
String formatted = format.format(15.5);
It always produces at least a $0.00 and is consistent when displayed. Also includes thousands seperators where needed. You can move the minus sign in front of the dollar sign if that is your requirement.

- 17,657
- 4
- 26
- 21
It's probably best to create your own DecimalFormat
if you want a specific format rather than relying on the default.
Edit: You could probably also cast the result of NumberFormat.getCurrencyInstance() to DecimalFormat
and adjust it to your preferences.

- 342,105
- 78
- 482
- 720
-
Probably you are right, but my application should be able to format currency in may locales. Wouldn't it be too hard to implement formating for all those locales? – Žygimantas Jan 13 '10 at 12:16
Since I faced this problem again, I did some research and found a more resilient solution provided by the ICU:
NumberFormatter
.withLocale(...)
.unit(Currency.getInstance("USD"))
.sign(SignDisplay.AUTO) // "123", "0", and "-123"
.format(123)
.toString();
Check the API documentation of NumberFormatter for more details.

- 725
- 3
- 7
- 13
-
I get a Security Risk when I click on the NumberFormatter link above. – Don Smith Nov 26 '20 at 20:55
-
Thanks, fixed! The documentation was migrated. For posterity, if that ever happens again: https://www.google.com/search?q=icu+numberformatter – Žygimantas Nov 30 '21 at 14:14
Why poi REFUSES to support the FIRST option in excel currency formatting is beyond me!
I don't like using the DecimalFormat for currency because your end cell value becomes a non-numeric with the introduction of the currency symbol. While working for a major financial institution, I was tasked with resolving this formatting issue. The core idea of this change is, because POI refuses to be reasonable and have comprehensive support of Excel's native options, I will infiltrate their code and change their values at the core. The following is my WORKAROUND:
private static final String CURRENCY_FORMAT_OVERRIDE = "\"$\"#,##0.00_);-\"$\"#,##0.00";
private static final String CURRENCY_FORMAT_TARGET = "\"$\"#,##0.00_);(\"$\"#,##0.00)";
static { // static class level initializer
Field field = org.apache.poi.ss.usermodel.BuiltinFormats.class.getDeclaredField("_formats");
field.setAccessible(true);
String[] _formats = (String[])field.get(new org.apache.poi.ss.usermodel.BuiltinFormats());
for(int i = 0; i < _formats.length; ++i) {
if(_formats[i].equals(CURRENCY_FORMAT_TARGET)) {
_formats[i]=CURRENCY_FORMAT_OVERRIDE;
System.out.println("TAKE THAT, POI!!!");
}
}
}

- 31
- 5