From: PJ Fanning Date: Thu, 6 Jul 2017 07:56:57 +0000 (+0000) Subject: [github-25] support excel number trailing comma format - Thabks to Luca Martini for... X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=23567cd3a0d7b092e60b49694cee1eb16eeef812;p=poi.git [github-25] support excel number trailing comma format - Thabks to Luca Martini for proving the patch git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1800975 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java index 0da7b6e714..f8dd2aefdb 100644 --- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java +++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java @@ -687,6 +687,57 @@ public class DataFormatter implements Observer { return sb.toString(); } + private static class InternalDecimalFormatWithScale extends Format { + + private static final Pattern endsWithCommas = Pattern.compile("(,+)$"); + private BigDecimal divider; + private static final BigDecimal ONE_THOUSAND = new BigDecimal(1000); + private final DecimalFormat df; + private static final String trimTrailingCommas(String s) { + return s.replaceAll(",+$", ""); + } + + public InternalDecimalFormatWithScale(String pattern, DecimalFormatSymbols symbols) { + df = new DecimalFormat(trimTrailingCommas(pattern), symbols); + setExcelStyleRoundingMode(df); + Matcher endsWithCommasMatcher = endsWithCommas.matcher(pattern); + if (endsWithCommasMatcher.find()) { + String commas = (endsWithCommasMatcher.group(1)); + BigDecimal temp = BigDecimal.ONE; + for (int i = 0; i < commas.length(); ++i) { + temp = temp.multiply(ONE_THOUSAND); + } + divider = temp; + } else { + divider = null; + } + } + + private Object scaleInput(Object obj) { + if (divider != null) { + if (obj instanceof BigDecimal) { + obj = ((BigDecimal) obj).divide(divider, RoundingMode.HALF_UP); + } else if (obj instanceof Double) { + obj = (Double) obj / divider.doubleValue(); + } else { + throw new UnsupportedOperationException(); + } + } + return obj; + } + + @Override + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { + obj = scaleInput(obj); + return df.format(obj, toAppendTo, pos); + } + + @Override + public Object parseObject(String source, ParsePosition pos) { + throw new UnsupportedOperationException(); + } + } + private Format createNumberFormat(String formatStr, double cellValue) { String format = cleanFormatForNumber(formatStr); DecimalFormatSymbols symbols = decimalSymbols; @@ -710,9 +761,7 @@ public class DataFormatter implements Observer { } try { - DecimalFormat df = new DecimalFormat(format, symbols); - setExcelStyleRoundingMode(df); - return df; + return new InternalDecimalFormatWithScale(format, symbols); } catch(IllegalArgumentException iae) { logger.log(POILogger.DEBUG, "Formatting failed for format " + formatStr + ", falling back", iae); // the pattern could not be parsed correctly, @@ -1247,4 +1296,4 @@ public class DataFormatter implements Observer { return null; // Not supported } } -} +} \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java index 211f801913..fb81622509 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java +++ b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java @@ -200,7 +200,7 @@ public class TestDataFormatter { ); } } - + @Test public void testConditionalRanges() { DataFormatter dfUS = new DataFormatter(Locale.US); @@ -820,7 +820,37 @@ public class TestDataFormatter { wb.close(); } - + + @Test + public void testFormatWithTrailingDotsUS() { + DataFormatter dfUS = new DataFormatter(Locale.US); + assertEquals("1,000,000", dfUS.formatRawCellContents(1000000, -1, "#,##0")); + assertEquals("1,000", dfUS.formatRawCellContents(1000000, -1, "#,##0,")); + assertEquals("1", dfUS.formatRawCellContents(1000000, -1, "#,##0,,")); + assertEquals("1,000,000.0", dfUS.formatRawCellContents(1000000, -1, "#,##0.0")); + assertEquals("1,000.0", dfUS.formatRawCellContents(1000000, -1, "#,##0.0,")); + assertEquals("1.0", dfUS.formatRawCellContents(1000000, -1, "#,##0.0,,")); + assertEquals("1,000,000.00", dfUS.formatRawCellContents(1000000, -1, "#,##0.00")); + assertEquals("1,000.00", dfUS.formatRawCellContents(1000000, -1, "#,##0.00,")); + assertEquals("1.00", dfUS.formatRawCellContents(1000000, -1, "#,##0.00,,")); + assertEquals("1,000,000", dfUS.formatRawCellContents(1e24, -1, "#,##0,,,,,,")); + } + + @Test + public void testFormatWithTrailingDotsOtherLocale() throws Exception { + DataFormatter dfIT = new DataFormatter(Locale.ITALY); + assertEquals("1.000.000", dfIT.formatRawCellContents(1000000, -1, "#,##0")); + assertEquals("1.000", dfIT.formatRawCellContents(1000000, -1, "#,##0,")); + assertEquals("1", dfIT.formatRawCellContents(1000000, -1, "#,##0,,")); + assertEquals("1.000.000,0", dfIT.formatRawCellContents(1000000, -1, "#,##0.0")); + assertEquals("1.000,0", dfIT.formatRawCellContents(1000000, -1, "#,##0.0,")); + assertEquals("1,0", dfIT.formatRawCellContents(1000000, -1, "#,##0.0,,")); + assertEquals("1.000.000,00", dfIT.formatRawCellContents(1000000, -1, "#,##0.00")); + assertEquals("1.000,00", dfIT.formatRawCellContents(1000000, -1, "#,##0.00,")); + assertEquals("1,00", dfIT.formatRawCellContents(1000000, -1, "#,##0.00,,")); + assertEquals("1.000.000", dfIT.formatRawCellContents(1e24, -1, "#,##0,,,,,,")); + } + /** * bug 60031: DataFormatter parses months incorrectly when put at the end of date segment */ @@ -895,4 +925,4 @@ public class TestDataFormatter { assertEquals("4,33 " + euro, df.formatRawCellContents(4.33, 178, formatString)); assertEquals("1.234,33 " + euro, df.formatRawCellContents(1234.33, 178, formatString)); } -} +} \ No newline at end of file