From ece0efd344ecf0d53e39640783d280aee1221351 Mon Sep 17 00:00:00 2001 From: Andrew Duffy Date: Mon, 28 Jun 2021 22:01:16 +0100 Subject: [PATCH] Support DataFormatter --- .../monitorjbl/xlsx/impl/StreamingSheet.java | 21 ++++++++++------- .../xlsx/impl/StreamingWorkbook.java | 22 ++++++++++++++---- .../xlsx/impl/StreamingWorkbookReader.java | 4 ++++ .../xlsx/StreamingWorkbookTest.java | 17 ++++++++++++++ .../java/com/monitorjbl/xlsx/TestUtils.java | 5 ++++ src/test/resources/formats.xlsx | Bin 0 -> 9240 bytes 6 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 src/test/resources/formats.xlsx diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java index e89073e0..de128481 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java @@ -27,6 +27,7 @@ public class StreamingSheet implements Sheet { + private Workbook workbook; private final String name; private final StreamingSheetReader reader; @@ -36,6 +37,10 @@ public StreamingSheet(String name, StreamingSheetReader reader) { reader.setSheet(this); } + void setWorkbook(Workbook workbook) { + this.workbook = workbook; + } + StreamingSheetReader getReader() { return reader; } @@ -77,6 +82,14 @@ public boolean isColumnHidden(int columnIndex) { return reader.isColumnHidden(columnIndex); } + @Override + public Workbook getWorkbook() { + if (workbook == null) { + throw new UnsupportedOperationException(); + } + return workbook; + } + /* Unsupported */ /** @@ -849,14 +862,6 @@ public Drawing createDrawingPatriarch() { throw new UnsupportedOperationException(); } - /** - * Not supported - */ - @Override - public Workbook getWorkbook() { - throw new UnsupportedOperationException(); - } - /** * Not supported */ diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java index 47d1346a..163040b6 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java @@ -7,6 +7,7 @@ import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.Date1904Support; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.PictureData; @@ -19,8 +20,9 @@ import java.io.OutputStream; import java.util.Iterator; import java.util.List; +import java.util.stream.StreamSupport; -public class StreamingWorkbook implements Workbook, AutoCloseable { +public class StreamingWorkbook implements Workbook, Date1904Support, AutoCloseable { private final StreamingWorkbookReader reader; public StreamingWorkbook(StreamingWorkbookReader reader) { @@ -43,7 +45,7 @@ int findSheetByName(String name) { */ @Override public Iterator iterator() { - return reader.iterator(); + return StreamSupport.stream(reader.spliterator(), false).map(this::withWorkbook).iterator(); } /** @@ -95,7 +97,7 @@ public int getNumberOfSheets() { */ @Override public Sheet getSheetAt(int index) { - return reader.getSheets().get(index); + return withWorkbook(reader.getSheets().get(index)); } /** @@ -107,7 +109,7 @@ public Sheet getSheet(String name) { if(index == -1) { throw new MissingSheetException("Sheet '" + name + "' does not exist"); } - return reader.getSheets().get(index); + return withWorkbook(reader.getSheets().get(index)); } /** @@ -126,6 +128,11 @@ public boolean isSheetVeryHidden(int sheetIx) { return "veryHidden".equals(reader.getSheetProperties().get(sheetIx).get("state")); } + @Override + public boolean isDate1904() { + return reader.isDate1904(); + } + /** * {@inheritDoc} */ @@ -134,6 +141,13 @@ public void close() throws IOException { reader.close(); } + private Sheet withWorkbook(Sheet sheet) { + if (sheet instanceof StreamingSheet) { + ((StreamingSheet)sheet).setWorkbook(this); + } + return sheet; + } + /* Not supported */ /** diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java index 282f4bc9..3792b39e 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java @@ -180,6 +180,10 @@ List getSheets() { return sheets; } + boolean isDate1904() { + return use1904Dates; + } + public List> getSheetProperties() { return sheetProperties; } diff --git a/src/test/java/com/monitorjbl/xlsx/StreamingWorkbookTest.java b/src/test/java/com/monitorjbl/xlsx/StreamingWorkbookTest.java index 13a978cf..0456fb52 100644 --- a/src/test/java/com/monitorjbl/xlsx/StreamingWorkbookTest.java +++ b/src/test/java/com/monitorjbl/xlsx/StreamingWorkbookTest.java @@ -20,6 +20,7 @@ import java.util.function.Consumer; import static com.monitorjbl.xlsx.TestUtils.expectCachedType; +import static com.monitorjbl.xlsx.TestUtils.expectFormattedContent; import static com.monitorjbl.xlsx.TestUtils.expectFormula; import static com.monitorjbl.xlsx.TestUtils.expectSameStringContent; import static com.monitorjbl.xlsx.TestUtils.expectStringContent; @@ -190,6 +191,22 @@ public void testEntityExpansion() { })); } + @Test + public void testDataFormatter() throws IOException { + try(Workbook workbook = openWorkbook("formats.xlsx")) { + Sheet sheet = workbook.getSheetAt(0); + Iterator rowIterator = sheet.rowIterator(); + + Cell A1 = getCellFromNextRow(rowIterator, 0); + Cell A2 = getCellFromNextRow(rowIterator, 0); + Cell A3 = getCellFromNextRow(rowIterator, 0); + + expectFormattedContent(A1, "1234.6"); + expectFormattedContent(A2, "1918-11-11"); + expectFormattedContent(A3, "50%"); + } + } + private static class ExploitServer extends NanoHTTPD implements AutoCloseable { private final Consumer onRequest; diff --git a/src/test/java/com/monitorjbl/xlsx/TestUtils.java b/src/test/java/com/monitorjbl/xlsx/TestUtils.java index 46c67926..bb893f47 100644 --- a/src/test/java/com/monitorjbl/xlsx/TestUtils.java +++ b/src/test/java/com/monitorjbl/xlsx/TestUtils.java @@ -2,6 +2,7 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellReference; @@ -30,6 +31,10 @@ static void expectStringContent(Cell cell, String value) { assertEquals(value, cell.getStringCellValue(), "Cell " + ref(cell) + " has wrong string content."); } + static void expectFormattedContent(Cell cell, String value) { + assertEquals(value, new DataFormatter().formatCellValue(cell), "Cell " + ref(cell) + " has wrong formatted content."); + } + static void expectCachedType(Cell cell, CellType cellType) { assertEquals(cellType, cell.getCachedFormulaResultType(), "Cell " + ref(cell) + " has wrong cached type." + cellType); } diff --git a/src/test/resources/formats.xlsx b/src/test/resources/formats.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8955982b89d3b151d8c4dd4c784373aae2762636 GIT binary patch literal 9240 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 f%_;vO{+H3!P)3Gp(2s2e7=R6UY(Po#_e-xKUo literal 0 HcmV?d00001