From d0e6830e446d2b9daac5357ea8576be4e91acf59 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 9 Sep 2025 22:27:48 +0100 Subject: [PATCH] issue when formatting number when divisor is needed (#895) * reproduce issue 69812 * workaround for issue --- .../poi/xssf/usermodel/TestXSSFBugs.java | 14 ++++++++++ .../poi/ss/usermodel/DataFormatter.java | 26 ++++++++++++++---- test-data/spreadsheet/bug69812.xlsx | Bin 0 -> 8625 bytes 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 test-data/spreadsheet/bug69812.xlsx diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index 22a9ec10e2..f049a1023f 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -3938,6 +3938,20 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { } } + @Test + void testBug69812() throws Exception { + try (XSSFWorkbook wb = openSampleWorkbook("bug69812.xlsx")) { + XSSFSheet sheet = wb.getSheetAt(0); + XSSFRow row = sheet.getRow(0); + XSSFCell cellA1 = row.getCell(0); + DataFormatter dataFormatter = new DataFormatter(); + String cellValue = dataFormatter.formatCellValue(cellA1); + // https://bz.apache.org/bugzilla/show_bug.cgi?id=69812: user says this should be "25,386" + assertEquals("25,396", cellValue); + assertEquals("#,##0,,", cellA1.getCellStyle().getDataFormatString()); + } + } + private static void readByCommonsCompress(File temp_excel_poi) throws IOException { /* read by commons-compress*/ try (ZipFile zipFile = ZipFile.builder().setFile(temp_excel_poi).get()) { diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/DataFormatter.java b/poi/src/main/java/org/apache/poi/ss/usermodel/DataFormatter.java index bfe795025e..e0ceb03a7b 100644 --- a/poi/src/main/java/org/apache/poi/ss/usermodel/DataFormatter.java +++ b/poi/src/main/java/org/apache/poi/ss/usermodel/DataFormatter.java @@ -808,6 +808,10 @@ public class DataFormatter { } } + boolean requiresScaling() { + return divider != null; + } + private Object scaleInput(Object obj) { if (divider != null) { if (obj instanceof BigDecimal) { @@ -965,12 +969,22 @@ public class DataFormatter { if (numberFormat == null) { return Double.toString(d); } - String formatted; - try { - //see https://github.com/apache/poi/pull/321 -- but this sometimes fails, thus the catch and retry - formatted = numberFormat.format(BigDecimal.valueOf(d)); - } catch (NumberFormatException nfe) { - formatted = numberFormat.format(d); + String formatted = null; + if (numberFormat instanceof InternalDecimalFormatWithScale) { + InternalDecimalFormatWithScale idfws = (InternalDecimalFormatWithScale) numberFormat; + if (idfws.requiresScaling()) { + // hack for https://bz.apache.org/bugzilla/show_bug.cgi?id=69812 + // the https://github.com/apache/poi/pull/321 hack causes problems here + formatted = idfws.format(d); + } + } + if (formatted == null) { + try { + //see https://github.com/apache/poi/pull/321 -- but this sometimes fails, thus the catch and retry + formatted = numberFormat.format(BigDecimal.valueOf(d)); + } catch (NumberFormatException nfe) { + formatted = numberFormat.format(d); + } } return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation } diff --git a/test-data/spreadsheet/bug69812.xlsx b/test-data/spreadsheet/bug69812.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..01dd98ed3c3777fd08ee369b409e1549122b32be GIT binary patch literal 8625 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