From 9176c95ee6337c217b853a344cc5a2ae2e5f2d55 Mon Sep 17 00:00:00 2001 From: Cristian Date: Tue, 24 Jun 2025 15:40:35 -0400 Subject: [PATCH 1/2] support poi 5.4.1 --- .gitignore | 1 + nb-configuration.xml | 19 + pom.xml | 10 +- .../com/monitorjbl/xlsx/StreamingReader.java | 654 +++++++++--------- .../monitorjbl/xlsx/impl/StreamingSheet.java | 17 + .../xlsx/impl/StreamingSheetReader.java | 6 +- .../xlsx/impl/StreamingWorkbook.java | 11 + .../xlsx/impl/StreamingWorkbookReader.java | 351 +++++----- 8 files changed, 569 insertions(+), 500 deletions(-) create mode 100644 nb-configuration.xml diff --git a/.gitignore b/.gitignore index 6af4e309..91f58ce6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ .idea target .java-version +.nb-configuracion.xml \ No newline at end of file diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 00000000..83b5b99c --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,19 @@ + + + + + + all + ZULU_1.8 + + diff --git a/pom.xml b/pom.xml index 6a681bed..9c6a6bb7 100644 --- a/pom.xml +++ b/pom.xml @@ -5,14 +5,14 @@ 4.0.0 com.monitorjbl xlsx-streamer - 3.0.0 + 2.3.0 Streaming Excel reader Streaming Excel reader https://github.com/monitorjbl/excel-streaming-reader UTF-8 - 5.0.0 + 5.4.1 1.7.30 @@ -29,7 +29,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.14.0 1.8 1.8 @@ -38,7 +38,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.1 + 3.11.2 attach-sources @@ -51,7 +51,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.3.1 attach-sources diff --git a/src/main/java/com/monitorjbl/xlsx/StreamingReader.java b/src/main/java/com/monitorjbl/xlsx/StreamingReader.java index 5a7ae8b2..2e0c1ee3 100644 --- a/src/main/java/com/monitorjbl/xlsx/StreamingReader.java +++ b/src/main/java/com/monitorjbl/xlsx/StreamingReader.java @@ -17,7 +17,6 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.StaxHelper; import org.apache.poi.xssf.eventusermodel.XSSFReader; -import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,362 +36,381 @@ import static com.monitorjbl.xlsx.XmlUtils.document; import static com.monitorjbl.xlsx.XmlUtils.searchForNodeList; import static com.monitorjbl.xlsx.impl.TempFileUtil.writeInputStreamToFile; +import java.util.logging.Level; +import org.apache.poi.xssf.model.SharedStrings; /** - * Streaming Excel workbook implementation. Most advanced features of POI are not supported. - * Use this only if your application can handle iterating through an entire workbook, row by - * row. + * Streaming Excel workbook implementation. Most advanced features of POI are + * not supported. Use this only if your application can handle iterating through + * an entire workbook, row by row. */ public class StreamingReader implements Iterable, AutoCloseable { - private static final Logger log = LoggerFactory.getLogger(StreamingReader.class); - - private File tmp; - private final StreamingWorkbookReader workbook; - - public StreamingReader(StreamingWorkbookReader workbook) { - this.workbook = workbook; - } - - /** - * Returns a new streaming iterator to loop through rows. This iterator is not - * guaranteed to have all rows in memory, and any particular iteration may - * trigger a load from disk to read in new data. - * - * @return the streaming iterator - * @deprecated StreamingReader is equivalent to the POI Workbook object rather - * than the Sheet object. This method will be removed in a future release. - */ - @Override - public Iterator iterator() { - return workbook.first().iterator(); - } - - /** - * Closes the streaming resource, attempting to clean up any temporary files created. - * - * @throws com.monitorjbl.xlsx.exceptions.CloseException if there is an issue closing the stream - */ - @Override - public void close() throws IOException { - try { - workbook.close(); - } finally { - if(tmp != null) { - if (log.isDebugEnabled()) { - log.debug("Deleting tmp file [" + tmp.getAbsolutePath() + "]"); - } - tmp.delete(); - } - } - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private int rowCacheSize = 10; - private int bufferSize = 1024; - private int sheetIndex = 0; - private int sstCacheSizeBytes = -1; - private String sheetName; - private String password; - - public int getRowCacheSize() { - return rowCacheSize; - } - - public int getBufferSize() { - return bufferSize; - } - - /** - * @return The sheet index - * @deprecated This method will be removed in a future release. - */ - public int getSheetIndex() { - return sheetIndex; - } - /** - * @return The sheet name - * @deprecated This method will be removed in a future release. - */ - public String getSheetName() { - return sheetName; - } + private static final Logger log = LoggerFactory.getLogger(StreamingReader.class); - /** - * @return The password to use to unlock this workbook - */ - public String getPassword() { - return password; - } - - /** - * @return The size of the shared string table cache. If less than 0, no - * cache will be used and the entire table will be loaded into memory. - */ - public int getSstCacheSizeBytes() { - return sstCacheSizeBytes; - } + private File tmp; + private final StreamingWorkbookReader workbook; - /** - * The number of rows to keep in memory at any given point. - *

- * Defaults to 10 - *

- * - * @param rowCacheSize number of rows - * @return reference to current {@code Builder} - */ - public Builder rowCacheSize(int rowCacheSize) { - this.rowCacheSize = rowCacheSize; - return this; + public StreamingReader(StreamingWorkbookReader workbook) { + this.workbook = workbook; } /** - * The number of bytes to read into memory from the input - * resource. - *

- * Defaults to 1024 - *

+ * Returns a new streaming iterator to loop through rows. This iterator is + * not guaranteed to have all rows in memory, and any particular iteration + * may trigger a load from disk to read in new data. * - * @param bufferSize buffer size in bytes - * @return reference to current {@code Builder} + * @return the streaming iterator + * @deprecated StreamingReader is equivalent to the POI Workbook object + * rather than the Sheet object. This method will be removed in a future + * release. */ - public Builder bufferSize(int bufferSize) { - this.bufferSize = bufferSize; - return this; + @Override + public Iterator iterator() { + return workbook.first().iterator(); } /** - * Which sheet to open. There can only be one sheet open - * for a single instance of {@code StreamingReader}. If - * more sheets need to be read, a new instance must be + * Closes the streaming resource, attempting to clean up any temporary files * created. - *

- * Defaults to 0 - *

* - * @param sheetIndex index of sheet - * @return reference to current {@code Builder} - * @deprecated This method will be removed in a future release. Use {@link StreamingWorkbook#getSheetAt(int)} instead. + * @throws com.monitorjbl.xlsx.exceptions.CloseException if there is an + * issue closing the stream */ - public Builder sheetIndex(int sheetIndex) { - this.sheetIndex = sheetIndex; - return this; + @Override + public void close() throws IOException { + try { + workbook.close(); + } finally { + if (tmp != null) { + if (log.isDebugEnabled()) { + log.debug("Deleting tmp file [" + tmp.getAbsolutePath() + "]"); + } + tmp.delete(); + } + } } - /** - * Which sheet to open. There can only be one sheet open - * for a single instance of {@code StreamingReader}. If - * more sheets need to be read, a new instance must be - * created. - * - * @param sheetName name of sheet - * @return reference to current {@code Builder} - * @deprecated This method will be removed in a future release. Use {@link StreamingWorkbook#getSheet(String)} instead. - */ - public Builder sheetName(String sheetName) { - this.sheetName = sheetName; - return this; + public static Builder builder() { + return new Builder(); } - /** - * For password protected files specify password to open file. - * If the password is incorrect a {@code ReadException} is thrown on - * {@code read}. - *

NULL indicates that no password should be used, this is the - * default value.

- * - * @param password to use when opening file - * @return reference to current {@code Builder} - */ - public Builder password(String password) { - this.password = password; - return this; - } + public static class Builder { - /** - *

!!! This option is experimental !!!

- * - * Set the size of the Shared Strings Table cache. This option exists to accommodate - * extremely large workbooks with millions of unique strings. Normally the SST is entirely - * loaded into memory, but with large workbooks with high cardinality (i.e., very few - * duplicate values) the SST may not fit entirely into memory. - *

- * By default, the entire SST *will* be loaded into memory. Setting a value greater than - * 0 for this option will only cache up to this many entries in memory. However, - * enabling this option at all will have some noticeable performance degredation as you are - * trading memory for disk space. - * - * @param sstCacheSizeBytes size of SST cache - * @return reference to current {@code Builder} - */ - public Builder sstCacheSizeBytes(int sstCacheSizeBytes) { - this.sstCacheSizeBytes = sstCacheSizeBytes; - return this; - } + private int rowCacheSize = 10; + private int bufferSize = 1024; + private int sheetIndex = 0; + private int sstCacheSizeBytes = -1; + private String sheetName; + private String password; - /** - * Reads a given {@code InputStream} and returns a new - * instance of {@code Workbook}. Due to Apache POI - * limitations, a temporary file must be written in order - * to create a streaming iterator. This process will use - * the same buffer size as specified in {@link #bufferSize(int)}. - * - * @param is input stream to read in - * @return A {@link Workbook} that can be read from - * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an issue reading the stream - */ - public Workbook open(InputStream is) { - StreamingWorkbookReader workbook = new StreamingWorkbookReader(this); - workbook.init(is); - return new StreamingWorkbook(workbook); - } + public int getRowCacheSize() { + return rowCacheSize; + } - /** - * Reads a given {@code File} and returns a new instance - * of {@code Workbook}. - * - * @param file file to read in - * @return built streaming reader instance - * @throws com.monitorjbl.xlsx.exceptions.OpenException if there is an issue opening the file - * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an issue reading the file - */ - public Workbook open(File file) { - StreamingWorkbookReader workbook = new StreamingWorkbookReader(this); - workbook.init(file); - return new StreamingWorkbook(workbook); - } + public int getBufferSize() { + return bufferSize; + } - /** - * Reads a given {@code InputStream} and returns a new - * instance of {@code StreamingReader}. Due to Apache POI - * limitations, a temporary file must be written in order - * to create a streaming iterator. This process will use - * the same buffer size as specified in {@link #bufferSize(int)}. - * - * @param is input stream to read in - * @return built streaming reader instance - * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an issue reading the stream - * @deprecated This method will be removed in a future release. Use {@link Builder#open(InputStream)} instead - */ - public StreamingReader read(InputStream is) { - File f = null; - try { - f = writeInputStreamToFile(is, bufferSize); - log.debug("Created temp file [" + f.getAbsolutePath() + "]"); - - StreamingReader r = read(f); - r.tmp = f; - return r; - } catch(IOException e) { - throw new ReadException("Unable to read input stream", e); - } catch(RuntimeException e) { - if(f != null) { - f.delete(); + /** + * @return The sheet index + * @deprecated This method will be removed in a future release. + */ + public int getSheetIndex() { + return sheetIndex; } - throw e; - } - } - /** - * Reads a given {@code File} and returns a new instance - * of {@code StreamingReader}. - * - * @param f file to read in - * @return built streaming reader instance - * @throws com.monitorjbl.xlsx.exceptions.OpenException if there is an issue opening the file - * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an issue reading the file - * @deprecated This method will be removed in a future release. Use {@link Builder#open(File)} instead - */ - public StreamingReader read(File f) { - try { - OPCPackage pkg; - if(password != null) { - // Based on: https://poi.apache.org/encryption.html - POIFSFileSystem poifs = new POIFSFileSystem(f); - EncryptionInfo info = new EncryptionInfo(poifs); - Decryptor d = Decryptor.getInstance(info); - d.verifyPassword(password); - pkg = OPCPackage.open(d.getDataStream(poifs)); - } else { - pkg = OPCPackage.open(f); + /** + * @return The sheet name + * @deprecated This method will be removed in a future release. + */ + public String getSheetName() { + return sheetName; + } + + /** + * @return The password to use to unlock this workbook + */ + public String getPassword() { + return password; } - boolean use1904Dates = false; - XSSFReader reader = new XSSFReader(pkg); - - SharedStringsTable sst; - File sstCache = null; - if(sstCacheSizeBytes > 0) { - sstCache = Files.createTempFile("", "").toFile(); - log.debug("Created sst cache file [" + sstCache.getAbsolutePath() + "]"); - sst = BufferedStringsTable.getSharedStringsTable(sstCache, sstCacheSizeBytes, pkg); - } else { - sst = reader.getSharedStringsTable(); + /** + * @return The size of the shared string table cache. If less than 0, no + * cache will be used and the entire table will be loaded into memory. + */ + public int getSstCacheSizeBytes() { + return sstCacheSizeBytes; } - StylesTable styles = reader.getStylesTable(); - NodeList workbookPr = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:workbookPr"); - if (workbookPr.getLength() == 1) { - final Node date1904 = workbookPr.item(0).getAttributes().getNamedItem("date1904"); - if (date1904 != null) { - use1904Dates = ("1".equals(date1904.getTextContent())); - } + /** + * The number of rows to keep in memory at any given point. + *

+ * Defaults to 10 + *

+ * + * @param rowCacheSize number of rows + * @return reference to current {@code Builder} + */ + public Builder rowCacheSize(int rowCacheSize) { + this.rowCacheSize = rowCacheSize; + return this; } - InputStream sheet = findSheet(reader); - if(sheet == null) { - throw new MissingSheetException("Unable to find sheet at index [" + sheetIndex + "]"); + + /** + * The number of bytes to read into memory from the input resource. + *

+ * Defaults to 1024 + *

+ * + * @param bufferSize buffer size in bytes + * @return reference to current {@code Builder} + */ + public Builder bufferSize(int bufferSize) { + this.bufferSize = bufferSize; + return this; } - XMLEventReader parser = StaxHelper.newXMLInputFactory().createXMLEventReader(sheet); - - return new StreamingReader(new StreamingWorkbookReader(sst, sstCache, pkg, new StreamingSheetReader(sst, styles, parser, use1904Dates, rowCacheSize), - this)); - } catch(IOException e) { - throw new OpenException("Failed to open file", e); - } catch(OpenXML4JException | XMLStreamException e) { - throw new ReadException("Unable to read workbook", e); - } catch(GeneralSecurityException e) { - throw new ReadException("Unable to read workbook - Decryption failed", e); - } - } + /** + * Which sheet to open. There can only be one sheet open for a single + * instance of {@code StreamingReader}. If more sheets need to be read, + * a new instance must be created. + *

+ * Defaults to 0 + *

+ * + * @param sheetIndex index of sheet + * @return reference to current {@code Builder} + * @deprecated This method will be removed in a future release. Use + * {@link StreamingWorkbook#getSheetAt(int)} instead. + */ + public Builder sheetIndex(int sheetIndex) { + this.sheetIndex = sheetIndex; + return this; + } - /** - * @deprecated This will be removed when the transition to the 1.x API is complete - */ - private InputStream findSheet(XSSFReader reader) throws IOException, InvalidFormatException { - int index = sheetIndex; - if(sheetName != null) { - index = -1; - //This file is separate from the worksheet data, and should be fairly small - NodeList nl = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:sheets/ss:sheet"); - for(int i = 0; i < nl.getLength(); i++) { - if(Objects.equals(nl.item(i).getAttributes().getNamedItem("name").getTextContent(), sheetName)) { - index = i; - } + /** + * Which sheet to open. There can only be one sheet open for a single + * instance of {@code StreamingReader}. If more sheets need to be read, + * a new instance must be created. + * + * @param sheetName name of sheet + * @return reference to current {@code Builder} + * @deprecated This method will be removed in a future release. Use + * {@link StreamingWorkbook#getSheet(String)} instead. + */ + public Builder sheetName(String sheetName) { + this.sheetName = sheetName; + return this; + } + + /** + * For password protected files specify password to open file. If the + * password is incorrect a {@code ReadException} is thrown on + * {@code read}. + *

+ * NULL indicates that no password should be used, this is the default + * value.

+ * + * @param password to use when opening file + * @return reference to current {@code Builder} + */ + public Builder password(String password) { + this.password = password; + return this; + } + + /** + *

!!! This option is experimental !!!

+ * + * Set the size of the Shared Strings Table cache. This option exists to + * accommodate extremely large workbooks with millions of unique + * strings. Normally the SST is entirely loaded into memory, but with + * large workbooks with high cardinality (i.e., very few duplicate + * values) the SST may not fit entirely into memory. + *

+ * By default, the entire SST *will* be loaded into memory. Setting a + * value greater than 0 for this option will only cache up to this many + * entries in memory. However, enabling this option at + * all will have some noticeable performance degredation as you are + * trading memory for disk space. + * + * @param sstCacheSizeBytes size of SST cache + * @return reference to current {@code Builder} + */ + public Builder sstCacheSizeBytes(int sstCacheSizeBytes) { + this.sstCacheSizeBytes = sstCacheSizeBytes; + return this; } - if(index < 0) { - return null; + + /** + * Reads a given {@code InputStream} and returns a new instance of + * {@code Workbook}. Due to Apache POI limitations, a temporary file + * must be written in order to create a streaming iterator. This process + * will use the same buffer size as specified in + * {@link #bufferSize(int)}. + * + * @param is input stream to read in + * @return A {@link Workbook} that can be read from + * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an + * issue reading the stream + */ + public Workbook open(InputStream is) { + StreamingWorkbookReader workbook = new StreamingWorkbookReader(this); + workbook.init(is); + return new StreamingWorkbook(workbook); } - } - Iterator iter = reader.getSheetsData(); - InputStream sheet = null; - - int i = 0; - while(iter.hasNext()) { - InputStream is = iter.next(); - if(i++ == index) { - sheet = is; - log.debug("Found sheet at index [" + sheetIndex + "]"); - break; + + /** + * Reads a given {@code File} and returns a new instance of + * {@code Workbook}. + * + * @param file file to read in + * @return built streaming reader instance + * @throws com.monitorjbl.xlsx.exceptions.OpenException if there is an + * issue opening the file + * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an + * issue reading the file + */ + public Workbook open(File file) { + StreamingWorkbookReader workbook = new StreamingWorkbookReader(this); + workbook.init(file); + return new StreamingWorkbook(workbook); + } + + /** + * Reads a given {@code InputStream} and returns a new instance of + * {@code StreamingReader}. Due to Apache POI limitations, a temporary + * file must be written in order to create a streaming iterator. This + * process will use the same buffer size as specified in + * {@link #bufferSize(int)}. + * + * @param is input stream to read in + * @return built streaming reader instance + * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an + * issue reading the stream + * @deprecated This method will be removed in a future release. Use + * {@link Builder#open(InputStream)} instead + */ + public StreamingReader read(InputStream is) { + File f = null; + try { + f = writeInputStreamToFile(is, bufferSize); + log.debug("Created temp file [" + f.getAbsolutePath() + "]"); + + StreamingReader r = read(f); + r.tmp = f; + return r; + } catch (IOException e) { + throw new ReadException("Unable to read input stream", e); + } catch (RuntimeException e) { + if (f != null) { + f.delete(); + } + throw e; + } + } + + /** + * Reads a given {@code File} and returns a new instance of + * {@code StreamingReader}. + * + * @param f file to read in + * @return built streaming reader instance + * @throws com.monitorjbl.xlsx.exceptions.OpenException if there is an + * issue opening the file + * @throws com.monitorjbl.xlsx.exceptions.ReadException if there is an + * issue reading the file + * @deprecated This method will be removed in a future release. Use + * {@link Builder#open(File)} instead + */ + public StreamingReader read(File f) { + try { + OPCPackage pkg; + if (password != null) { + // Based on: https://poi.apache.org/encryption.html + POIFSFileSystem poifs = new POIFSFileSystem(f); + EncryptionInfo info = new EncryptionInfo(poifs); + Decryptor d = Decryptor.getInstance(info); + d.verifyPassword(password); + pkg = OPCPackage.open(d.getDataStream(poifs)); + } else { + pkg = OPCPackage.open(f); + } + + boolean use1904Dates = false; + XSSFReader reader = new XSSFReader(pkg); + + SharedStrings sst; + File sstCache = null; + if (sstCacheSizeBytes > 0) { + sstCache = Files.createTempFile("", "").toFile(); + log.debug("Created sst cache file [" + sstCache.getAbsolutePath() + "]"); + sst = BufferedStringsTable.getSharedStringsTable(sstCache, sstCacheSizeBytes, pkg); + } else { + sst = reader.getSharedStringsTable(); + } + + StylesTable styles = reader.getStylesTable(); + NodeList workbookPr = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:workbookPr"); + if (workbookPr.getLength() == 1) { + final Node date1904 = workbookPr.item(0).getAttributes().getNamedItem("date1904"); + if (date1904 != null) { + use1904Dates = ("1".equals(date1904.getTextContent())); + } + } + InputStream sheet = findSheet(reader); + if (sheet == null) { + throw new MissingSheetException("Unable to find sheet at index [" + sheetIndex + "]"); + } + + XMLEventReader parser = StaxHelper.newXMLInputFactory().createXMLEventReader(sheet); + + return new StreamingReader(new StreamingWorkbookReader(sst, sstCache, pkg, new StreamingSheetReader(sst, styles, parser, use1904Dates, rowCacheSize), + this)); + } catch (IOException e) { + java.util.logging.Logger.getLogger(Builder.class.getName()).log(Level.SEVERE, "AQUIII", e); + throw new OpenException("Failed to open file", e); + } catch (OpenXML4JException | XMLStreamException e) { + throw new ReadException("Unable to read workbook", e); + } catch (GeneralSecurityException e) { + throw new ReadException("Unable to read workbook - Decryption failed", e); + } + } + + /** + * @deprecated This will be removed when the transition to the 1.x API + * is complete + */ + private InputStream findSheet(XSSFReader reader) throws IOException, InvalidFormatException { + int index = sheetIndex; + if (sheetName != null) { + index = -1; + //This file is separate from the worksheet data, and should be fairly small + NodeList nl = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:sheets/ss:sheet"); + for (int i = 0; i < nl.getLength(); i++) { + if (Objects.equals(nl.item(i).getAttributes().getNamedItem("name").getTextContent(), sheetName)) { + index = i; + } + } + if (index < 0) { + return null; + } + } + Iterator iter = reader.getSheetsData(); + InputStream sheet = null; + + int i = 0; + while (iter.hasNext()) { + InputStream is = iter.next(); + if (i++ == index) { + sheet = is; + log.debug("Found sheet at index [" + sheetIndex + "]"); + break; + } + } + return sheet; } - } - return sheet; } - } } diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java index e89073e0..9be727a0 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheet.java @@ -24,6 +24,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.poi.ss.usermodel.PageMargin; +import org.apache.poi.ss.usermodel.PaneType; public class StreamingSheet implements Sheet { @@ -1000,4 +1002,19 @@ public CellAddress getActiveCell() { public void setActiveCell(CellAddress cellAddress) { throw new UnsupportedOperationException(); } + + @Override + public double getMargin(PageMargin pm) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public void setMargin(PageMargin pm, double d) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public void createSplitPane(int i, int i1, int i2, int i3, PaneType pt) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } } diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheetReader.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheetReader.java index ee5aaf0b..d82aa2b4 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheetReader.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingSheetReader.java @@ -7,7 +7,6 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFRichTextString; @@ -28,11 +27,12 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import org.apache.poi.xssf.model.SharedStrings; public class StreamingSheetReader implements Iterable { private static final Logger log = LoggerFactory.getLogger(StreamingSheetReader.class); - private final SharedStringsTable sst; + private final SharedStrings sst; private final StylesTable stylesTable; private final XMLEventReader parser; private final DataFormatter dataFormatter = new DataFormatter(); @@ -52,7 +52,7 @@ public class StreamingSheetReader implements Iterable { private StreamingCell currentCell; private boolean use1904Dates; - public StreamingSheetReader(SharedStringsTable sst, StylesTable stylesTable, XMLEventReader parser, + public StreamingSheetReader(SharedStrings sst, StylesTable stylesTable, XMLEventReader parser, final boolean use1904Dates, int rowCacheSize) { this.sst = sst; this.stylesTable = stylesTable; diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java index 47d1346a..2e4b7c16 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbook.java @@ -19,6 +19,7 @@ import java.io.OutputStream; import java.util.Iterator; import java.util.List; +import org.apache.poi.ss.usermodel.CellReferenceType; public class StreamingWorkbook implements Workbook, AutoCloseable { private final StreamingWorkbookReader reader; @@ -509,4 +510,14 @@ public int addOlePackage(byte[] bytes, String s, String s1, String s2) throws IO public EvaluationWorkbook createEvaluationWorkbook() { return null; } + + @Override + public CellReferenceType getCellReferenceType() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public void setCellReferenceType(CellReferenceType crt) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } } diff --git a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java index 282f4bc9..fcf1efaa 100644 --- a/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java +++ b/src/main/java/com/monitorjbl/xlsx/impl/StreamingWorkbookReader.java @@ -14,7 +14,6 @@ import org.apache.poi.util.StaxHelper; import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator; -import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,199 +39,203 @@ import static com.monitorjbl.xlsx.XmlUtils.searchForNodeList; import static com.monitorjbl.xlsx.impl.TempFileUtil.writeInputStreamToFile; import static java.util.Arrays.asList; +import org.apache.poi.xssf.model.SharedStrings; public class StreamingWorkbookReader implements Iterable, AutoCloseable { - private static final Logger log = LoggerFactory.getLogger(StreamingWorkbookReader.class); - - private final List sheets; - private final List> sheetProperties = new ArrayList<>(); - private final Builder builder; - private File tmp; - private File sstCache; - private OPCPackage pkg; - private SharedStringsTable sst; - private boolean use1904Dates = false; - - /** - * This constructor exists only so the StreamingReader can instantiate - * a StreamingWorkbook using its own reader implementation. Do not use - * going forward. - * - * @param sst The SST data for this workbook - * @param sstCache The backing cache file for the SST data - * @param pkg The POI package that should be closed when this workbook is closed - * @param reader A single streaming reader instance - * @param builder The builder containing all options - */ - @Deprecated - public StreamingWorkbookReader(SharedStringsTable sst, File sstCache, OPCPackage pkg, StreamingSheetReader reader, Builder builder) { - this.sst = sst; - this.sstCache = sstCache; - this.pkg = pkg; - this.sheets = asList(new StreamingSheet(null, reader)); - this.builder = builder; - } - - public StreamingWorkbookReader(Builder builder) { - this.sheets = new ArrayList<>(); - this.builder = builder; - } - - public StreamingSheetReader first() { - return sheets.get(0).getReader(); - } - - public void init(InputStream is) { - File f = null; - try { - f = writeInputStreamToFile(is, builder.getBufferSize()); - log.debug("Created temp file [" + f.getAbsolutePath() + "]"); - - init(f); - tmp = f; - } catch(IOException e) { - throw new ReadException("Unable to read input stream", e); - } catch(RuntimeException e) { - if(f != null) { - f.delete(); - } - throw e; + + private static final Logger log = LoggerFactory.getLogger(StreamingWorkbookReader.class); + + private final List sheets; + private final List> sheetProperties = new ArrayList<>(); + private final Builder builder; + private File tmp; + private File sstCache; + private OPCPackage pkg; + private SharedStrings sst; + private boolean use1904Dates = false; + + /** + * This constructor exists only so the StreamingReader can instantiate a + * StreamingWorkbook using its own reader implementation. Do not use going + * forward. + * + * @param sst The SST data for this workbook + * @param sstCache The backing cache file for the SST data + * @param pkg The POI package that should be closed when this workbook is + * closed + * @param reader A single streaming reader instance + * @param builder The builder containing all options + */ + @Deprecated + public StreamingWorkbookReader(SharedStrings sst, File sstCache, OPCPackage pkg, StreamingSheetReader reader, Builder builder) { + this.sst = sst; + this.sstCache = sstCache; + this.pkg = pkg; + this.sheets = asList(new StreamingSheet(null, reader)); + this.builder = builder; } - } - - public void init(File f) { - try { - if(builder.getPassword() != null) { - // Based on: https://poi.apache.org/encryption.html - POIFSFileSystem poifs = new POIFSFileSystem(f); - EncryptionInfo info = new EncryptionInfo(poifs); - Decryptor d = Decryptor.getInstance(info); - d.verifyPassword(builder.getPassword()); - pkg = OPCPackage.open(d.getDataStream(poifs)); - } else { - pkg = OPCPackage.open(f); - } - - XSSFReader reader = new XSSFReader(pkg); - if(builder.getSstCacheSizeBytes() > 0) { - sstCache = Files.createTempFile("", "").toFile(); - log.debug("Created sst cache file [" + sstCache.getAbsolutePath() + "]"); - sst = BufferedStringsTable.getSharedStringsTable(sstCache, builder.getSstCacheSizeBytes(), pkg); - } else { - sst = reader.getSharedStringsTable(); - } - - StylesTable styles = reader.getStylesTable(); - NodeList workbookPr = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:workbookPr"); - if(workbookPr.getLength() == 1) { - final Node date1904 = workbookPr.item(0).getAttributes().getNamedItem("date1904"); - if(date1904 != null) { - use1904Dates = ("1".equals(date1904.getTextContent())); - } - } - - loadSheets(reader, sst, styles, builder.getRowCacheSize()); - } catch(IOException e) { - throw new OpenException("Failed to open file", e); - } catch(OpenXML4JException | XMLStreamException e) { - throw new ReadException("Unable to read workbook", e); - } catch(GeneralSecurityException e) { - throw new ReadException("Unable to read workbook - Decryption failed", e); + + public StreamingWorkbookReader(Builder builder) { + this.sheets = new ArrayList<>(); + this.builder = builder; } - } - - void loadSheets(XSSFReader reader, SharedStringsTable sst, StylesTable stylesTable, int rowCacheSize) - throws IOException, InvalidFormatException, XMLStreamException { - lookupSheetNames(reader); - - //Some workbooks have multiple references to the same sheet. Need to filter - //them out before creating the XMLEventReader by keeping track of their URIs. - //The sheets are listed in order, so we must keep track of insertion order. - SheetIterator iter = (SheetIterator) reader.getSheetsData(); - Map sheetStreams = new LinkedHashMap<>(); - while(iter.hasNext()) { - InputStream is = iter.next(); - sheetStreams.put(iter.getSheetPart().getPartName().getURI(), is); + + public StreamingSheetReader first() { + return sheets.get(0).getReader(); } - //Iterate over the loaded streams - int i = 0; - for(URI uri : sheetStreams.keySet()) { - XMLEventReader parser = StaxHelper.newXMLInputFactory().createXMLEventReader(sheetStreams.get(uri)); - sheets.add(new StreamingSheet(sheetProperties.get(i++).get("name"), new StreamingSheetReader(sst, stylesTable, parser, use1904Dates, rowCacheSize))); + public void init(InputStream is) { + File f = null; + try { + f = writeInputStreamToFile(is, builder.getBufferSize()); + log.debug("Created temp file [" + f.getAbsolutePath() + "]"); + + init(f); + tmp = f; + } catch (IOException e) { + throw new ReadException("Unable to read input stream", e); + } catch (RuntimeException e) { + if (f != null) { + f.delete(); + } + throw e; + } } - } - - void lookupSheetNames(XSSFReader reader) throws IOException, InvalidFormatException { - sheetProperties.clear(); - NodeList nl = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:sheets/ss:sheet"); - for(int i = 0; i < nl.getLength(); i++) { - Map props = new HashMap<>(); - props.put("name", nl.item(i).getAttributes().getNamedItem("name").getTextContent()); - - Node state = nl.item(i).getAttributes().getNamedItem("state"); - props.put("state", state == null ? "visible" : state.getTextContent()); - sheetProperties.add(props); + + public void init(File f) { + try { + if (builder.getPassword() != null) { + // Based on: https://poi.apache.org/encryption.html + POIFSFileSystem poifs = new POIFSFileSystem(f); + EncryptionInfo info = new EncryptionInfo(poifs); + Decryptor d = Decryptor.getInstance(info); + d.verifyPassword(builder.getPassword()); + pkg = OPCPackage.open(d.getDataStream(poifs)); + } else { + pkg = OPCPackage.open(f); + } + + XSSFReader reader = new XSSFReader(pkg); + if (builder.getSstCacheSizeBytes() > 0) { + sstCache = Files.createTempFile("", "").toFile(); + log.debug("Created sst cache file [" + sstCache.getAbsolutePath() + "]"); + sst = BufferedStringsTable.getSharedStringsTable(sstCache, builder.getSstCacheSizeBytes(), pkg); + } else { + sst = reader.getSharedStringsTable(); + } + + StylesTable styles = reader.getStylesTable(); + NodeList workbookPr = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:workbookPr"); + if (workbookPr.getLength() == 1) { + final Node date1904 = workbookPr.item(0).getAttributes().getNamedItem("date1904"); + if (date1904 != null) { + use1904Dates = ("1".equals(date1904.getTextContent())); + } + } + + loadSheets(reader, sst, styles, builder.getRowCacheSize()); + } catch (IOException e) { + throw new OpenException("Failed to open file", e); + } catch (OpenXML4JException | XMLStreamException e) { + throw new ReadException("Unable to read workbook", e); + } catch (GeneralSecurityException e) { + throw new ReadException("Unable to read workbook - Decryption failed", e); + } } - } - - List getSheets() { - return sheets; - } - - public List> getSheetProperties() { - return sheetProperties; - } - - @Override - public Iterator iterator() { - return new StreamingSheetIterator(sheets.iterator()); - } - - @Override - public void close() throws IOException { - try { - for(StreamingSheet sheet : sheets) { - sheet.getReader().close(); - } - pkg.revert(); - } finally { - if(tmp != null) { - if(log.isDebugEnabled()) { - log.debug("Deleting tmp file [" + tmp.getAbsolutePath() + "]"); + + void loadSheets(XSSFReader reader, SharedStrings sst, StylesTable stylesTable, int rowCacheSize) + throws IOException, InvalidFormatException, XMLStreamException { + lookupSheetNames(reader); + + //Some workbooks have multiple references to the same sheet. Need to filter + //them out before creating the XMLEventReader by keeping track of their URIs. + //The sheets are listed in order, so we must keep track of insertion order. + SheetIterator iter = (SheetIterator) reader.getSheetsData(); + Map sheetStreams = new LinkedHashMap<>(); + while (iter.hasNext()) { + InputStream is = iter.next(); + sheetStreams.put(iter.getSheetPart().getPartName().getURI(), is); } - tmp.delete(); - } - if(sst instanceof BufferedStringsTable) { - if(log.isDebugEnabled()) { - log.debug("Deleting sst cache file [" + this.sstCache.getAbsolutePath() + "]"); + + //Iterate over the loaded streams + int i = 0; + for (URI uri : sheetStreams.keySet()) { + XMLEventReader parser = StaxHelper.newXMLInputFactory().createXMLEventReader(sheetStreams.get(uri)); + sheets.add(new StreamingSheet(sheetProperties.get(i++).get("name"), new StreamingSheetReader(sst, stylesTable, parser, use1904Dates, rowCacheSize))); } - ((BufferedStringsTable) sst).close(); - sstCache.delete(); - } } - } - static class StreamingSheetIterator implements Iterator { - private final Iterator iterator; + void lookupSheetNames(XSSFReader reader) throws IOException, InvalidFormatException { + sheetProperties.clear(); + NodeList nl = searchForNodeList(document(reader.getWorkbookData()), "/ss:workbook/ss:sheets/ss:sheet"); + for (int i = 0; i < nl.getLength(); i++) { + Map props = new HashMap<>(); + props.put("name", nl.item(i).getAttributes().getNamedItem("name").getTextContent()); + + Node state = nl.item(i).getAttributes().getNamedItem("state"); + props.put("state", state == null ? "visible" : state.getTextContent()); + sheetProperties.add(props); + } + } - public StreamingSheetIterator(Iterator iterator) { - this.iterator = iterator; + List getSheets() { + return sheets; } - @Override - public boolean hasNext() { - return iterator.hasNext(); + public List> getSheetProperties() { + return sheetProperties; } @Override - public Sheet next() { - return iterator.next(); + public Iterator iterator() { + return new StreamingSheetIterator(sheets.iterator()); } @Override - public void remove() { - throw new RuntimeException("NotSupported"); + public void close() throws IOException { + try { + for (StreamingSheet sheet : sheets) { + sheet.getReader().close(); + } + pkg.revert(); + } finally { + if (tmp != null) { + if (log.isDebugEnabled()) { + log.debug("Deleting tmp file [" + tmp.getAbsolutePath() + "]"); + } + tmp.delete(); + } + if (sst instanceof BufferedStringsTable) { + if (log.isDebugEnabled()) { + log.debug("Deleting sst cache file [" + this.sstCache.getAbsolutePath() + "]"); + } + ((BufferedStringsTable) sst).close(); + sstCache.delete(); + } + } + } + + static class StreamingSheetIterator implements Iterator { + + private final Iterator iterator; + + public StreamingSheetIterator(Iterator iterator) { + this.iterator = iterator; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Sheet next() { + return iterator.next(); + } + + @Override + public void remove() { + throw new RuntimeException("NotSupported"); + } } - } } From 6ef620b9deef97dd90f46ffcf4ff5f0bc63527af Mon Sep 17 00:00:00 2001 From: Cristian Date: Tue, 24 Jun 2025 17:26:35 -0400 Subject: [PATCH 2/2] fix --- nb-configuration.xml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 nb-configuration.xml diff --git a/nb-configuration.xml b/nb-configuration.xml deleted file mode 100644 index 83b5b99c..00000000 --- a/nb-configuration.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - all - ZULU_1.8 - -