mirror of https://github.com/apache/poi.git
[github-184] New EmittingSXSSFWorkbook. Thanks to mobreza. This closes #184
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1879302 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
09d81ea7da
commit
f06c45421b
|
@ -0,0 +1,69 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
|
||||
/**
|
||||
* A variant of SXSSFSheet that uses IRowGenerator to create rows.
|
||||
*
|
||||
* This variant is experimental and APIs may change at short notice.
|
||||
*
|
||||
* @see EmittingSXSSFWorkbook
|
||||
* @since 5.0.0
|
||||
*/
|
||||
@Beta
|
||||
public class EmittingSXSSFSheet extends SXSSFSheet {
|
||||
private IRowGenerator rowGenerator;
|
||||
|
||||
public EmittingSXSSFSheet(EmittingSXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
|
||||
super(workbook, xSheet, workbook.getRandomAccessWindowSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getWorksheetXMLInputStream() throws IOException {
|
||||
throw new RuntimeException("Not supported by EmittingSXSSFSheet");
|
||||
}
|
||||
|
||||
public void setRowGenerator(IRowGenerator rowGenerator) {
|
||||
this.rowGenerator = rowGenerator;
|
||||
}
|
||||
|
||||
public void writeRows(OutputStream out) throws IOException {
|
||||
// delayed creation of SheetDataWriter
|
||||
_writer = ((EmittingSXSSFWorkbook) _workbook).createSheetDataWriter(out);
|
||||
try {
|
||||
if (this.rowGenerator != null) {
|
||||
this.rowGenerator.generateRows(this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Error generating Excel rows", e);
|
||||
} finally {
|
||||
// flush buffered rows
|
||||
flushRows(0);
|
||||
// flush writer buffer
|
||||
_writer.close();
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
/**
|
||||
* An variant of SXSSFWorkbook that avoids generating a temporary file and writes data directly to
|
||||
* the provided OutputStream.
|
||||
*
|
||||
* This variant is experimental and APIs may change at short notice.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
@Beta
|
||||
public class EmittingSXSSFWorkbook extends SXSSFWorkbook {
|
||||
private static final POILogger logger = POILogFactory.getLogger(EmittingSXSSFWorkbook.class);
|
||||
|
||||
public EmittingSXSSFWorkbook() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public EmittingSXSSFWorkbook(XSSFWorkbook workbook) {
|
||||
this(workbook, SXSSFWorkbook.DEFAULT_WINDOW_SIZE);
|
||||
}
|
||||
|
||||
public EmittingSXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize) {
|
||||
super(workbook, rowAccessWindowSize, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SheetDataWriter createSheetDataWriter() throws IOException {
|
||||
throw new RuntimeException("Not supported by EmittingSXSSFWorkbook");
|
||||
}
|
||||
|
||||
protected StreamingSheetWriter createSheetDataWriter(OutputStream out) throws IOException {
|
||||
return new StreamingSheetWriter(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ISheetInjector createSheetInjector(SXSSFSheet sxSheet) throws IOException {
|
||||
EmittingSXSSFSheet ssxSheet = (EmittingSXSSFSheet) sxSheet;
|
||||
return (output) -> {
|
||||
ssxSheet.writeRows(output);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
SXSSFSheet createAndRegisterSXSSFSheet(XSSFSheet xSheet) {
|
||||
final EmittingSXSSFSheet sxSheet;
|
||||
try {
|
||||
sxSheet = new EmittingSXSSFSheet(this, xSheet);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
registerSheetMapping(sxSheet, xSheet);
|
||||
return sxSheet;
|
||||
}
|
||||
|
||||
public EmittingSXSSFSheet createSheet() {
|
||||
return (EmittingSXSSFSheet) super.createSheet();
|
||||
}
|
||||
|
||||
public EmittingSXSSFSheet createSheet(String sheetname) {
|
||||
return (EmittingSXSSFSheet) super.createSheet(sheetname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator of the sheets in the workbook in sheet order. Includes hidden and very hidden sheets.
|
||||
*
|
||||
* @return an iterator of the sheets.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Sheet> sheetIterator() {
|
||||
return new SheetIterator<Sheet>();
|
||||
}
|
||||
|
||||
private final class SheetIterator<T extends Sheet> implements Iterator<T> {
|
||||
final private Iterator<XSSFSheet> it;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public SheetIterator() {
|
||||
it = (Iterator<XSSFSheet>) (Iterator<? extends Sheet>) _wb.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T next() throws NoSuchElementException {
|
||||
final XSSFSheet xssfSheet = it.next();
|
||||
EmittingSXSSFSheet sxSheet = (EmittingSXSSFSheet) getSXSSFSheet(xssfSheet);
|
||||
return (T) (sxSheet == null ? xssfSheet : sxSheet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unexpected behavior may occur if sheets are reordered after iterator has been created. Support for the remove
|
||||
* method may be added in the future if someone can figure out a reliable implementation.
|
||||
*/
|
||||
@Override
|
||||
public void remove() throws IllegalStateException {
|
||||
throw new UnsupportedOperationException("remove method not supported on XSSFWorkbook.iterator(). "
|
||||
+ "Use Sheet.removeSheetAt(int) instead.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #sheetIterator()} to allow foreach loops
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Sheet> iterator() {
|
||||
return sheetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SXSSFSheet getSheetAt(int index) {
|
||||
throw new RuntimeException("Not supported by EmittingSXSSFWorkbook");
|
||||
}
|
||||
|
||||
public XSSFSheet getXSSFSheetAt(int index) {
|
||||
return _wb.getSheetAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sheet at the given index for streaming.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the streaming sheet at
|
||||
*/
|
||||
public EmittingSXSSFSheet getStreamingSheetAt(int index) {
|
||||
XSSFSheet xSheet = _wb.getSheetAt(index);
|
||||
SXSSFSheet sxSheet = getSXSSFSheet(xSheet);
|
||||
if (sxSheet == null && xSheet != null) {
|
||||
return (EmittingSXSSFSheet) createAndRegisterSXSSFSheet(xSheet);
|
||||
} else {
|
||||
return (EmittingSXSSFSheet) sxSheet;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SXSSFSheet getSheet(String name) {
|
||||
throw new RuntimeException("Not supported by EmittingSXSSFWorkbook");
|
||||
}
|
||||
|
||||
public XSSFSheet getXSSFSheet(String name) {
|
||||
return _wb.getSheet(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sheet with the given name for streaming.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the streaming sheet
|
||||
*/
|
||||
public EmittingSXSSFSheet getStreamingSheet(String name) {
|
||||
XSSFSheet xSheet = _wb.getSheet(name);
|
||||
EmittingSXSSFSheet sxSheet = (EmittingSXSSFSheet) getSXSSFSheet(xSheet);
|
||||
if (sxSheet == null && xSheet != null) {
|
||||
return (EmittingSXSSFSheet) createAndRegisterSXSSFSheet(xSheet);
|
||||
} else {
|
||||
return sxSheet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes sheet at the given index
|
||||
*
|
||||
* @param index of the sheet to remove (0-based)
|
||||
*/
|
||||
@Override
|
||||
public void removeSheetAt(int index) {
|
||||
// Get the sheet to be removed
|
||||
XSSFSheet xSheet = _wb.getSheetAt(index);
|
||||
SXSSFSheet sxSheet = getSXSSFSheet(xSheet);
|
||||
|
||||
// De-register it
|
||||
_wb.removeSheetAt(index);
|
||||
|
||||
// The sheet may not be a streaming sheet and is not mapped
|
||||
if (sxSheet != null) {
|
||||
deregisterSheetMapping(xSheet);
|
||||
|
||||
// Clean up temporary resources
|
||||
try {
|
||||
sxSheet.dispose();
|
||||
} catch (IOException e) {
|
||||
logger.log(POILogger.WARN, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import org.apache.poi.util.Beta;
|
||||
|
||||
/**
|
||||
* IRowGenerator for Emitting SXSSF sheets
|
||||
*
|
||||
* @see EmittingSXSSFWorkbook
|
||||
*/
|
||||
@Beta
|
||||
public interface IRowGenerator {
|
||||
|
||||
/**
|
||||
* Generate and add rows to the sheet
|
||||
*
|
||||
* @param sheet the sheet
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
void generateRows(SXSSFSheet sheet) throws Exception;
|
||||
}
|
|
@ -106,12 +106,14 @@ public final class SXSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator {
|
|||
// Process the sheets as best we can
|
||||
for (Sheet sheet : wb) {
|
||||
|
||||
if (sheet instanceof SXSSFSheet) {
|
||||
// Check if any rows have already been flushed out
|
||||
int lastFlushedRowNum = ((SXSSFSheet) sheet).getLastFlushedRowNum();
|
||||
if (lastFlushedRowNum > -1) {
|
||||
if (! skipOutOfWindow) throw new RowFlushedException(0);
|
||||
logger.log(POILogger.INFO, "Rows up to " + lastFlushedRowNum + " have already been flushed, skipping");
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate what we have
|
||||
for (Row r : sheet) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.poi.openxml4j.opc.PackagePart;
|
|||
import org.apache.poi.ss.usermodel.Picture;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Shape;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.ImageUtils;
|
||||
import org.apache.poi.util.Internal;
|
||||
|
@ -201,7 +202,8 @@ public final class SXSSFPicture implements Picture {
|
|||
// THE FOLLOWING THREE LINES ARE THE MAIN CHANGE compared to the non-streaming version: use the SXSSF sheet,
|
||||
// not the XSSF sheet (which never contais rows when using SXSSF)
|
||||
XSSFSheet xssfSheet = getSheet();
|
||||
SXSSFSheet sheet = _wb.getSXSSFSheet(xssfSheet);
|
||||
SXSSFSheet sxSheet = _wb.getSXSSFSheet(xssfSheet);
|
||||
Sheet sheet = sxSheet == null ? xssfSheet : sxSheet;
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
float height = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
|
||||
return height * Units.PIXEL_DPI / Units.POINT_DPI;
|
||||
|
|
|
@ -65,15 +65,22 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
|||
public class SXSSFSheet implements Sheet
|
||||
{
|
||||
/*package*/ final XSSFSheet _sh;
|
||||
private final SXSSFWorkbook _workbook;
|
||||
protected final SXSSFWorkbook _workbook;
|
||||
private final TreeMap<Integer,SXSSFRow> _rows = new TreeMap<>();
|
||||
private final SheetDataWriter _writer;
|
||||
protected SheetDataWriter _writer;
|
||||
private int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
|
||||
private final AutoSizeColumnTracker _autoSizeColumnTracker;
|
||||
protected final AutoSizeColumnTracker _autoSizeColumnTracker;
|
||||
private int outlineLevelRow;
|
||||
private int lastFlushedRowNumber = -1;
|
||||
private boolean allFlushed;
|
||||
|
||||
protected SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet, int randomAccessWindowSize) {
|
||||
_workbook = workbook;
|
||||
_sh = xSheet;
|
||||
setRandomAccessWindowSize(randomAccessWindowSize);
|
||||
_autoSizeColumnTracker = new AutoSizeColumnTracker(this);
|
||||
}
|
||||
|
||||
public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
|
||||
_workbook = workbook;
|
||||
_sh = xSheet;
|
||||
|
@ -1904,7 +1911,7 @@ public class SXSSFSheet implements Sheet
|
|||
if (!allFlushed) {
|
||||
flushRows();
|
||||
}
|
||||
return _writer.dispose();
|
||||
return _writer == null || _writer.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -96,13 +96,17 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public static final int DEFAULT_WINDOW_SIZE = 100;
|
||||
private static final POILogger logger = POILogFactory.getLogger(SXSSFWorkbook.class);
|
||||
|
||||
private final XSSFWorkbook _wb;
|
||||
protected final XSSFWorkbook _wb;
|
||||
|
||||
private final Map<SXSSFSheet,XSSFSheet> _sxFromXHash = new HashMap<>();
|
||||
private final Map<XSSFSheet,SXSSFSheet> _xFromSxHash = new HashMap<>();
|
||||
|
||||
private int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE;
|
||||
|
||||
protected static interface ISheetInjector {
|
||||
void writeSheetData(OutputStream out) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* whether temp files should be compressed.
|
||||
*/
|
||||
|
@ -111,12 +115,12 @@ public class SXSSFWorkbook implements Workbook {
|
|||
/**
|
||||
* shared string table - a cache of strings in this workbook
|
||||
*/
|
||||
private final SharedStringsTable _sharedStringSource;
|
||||
protected final SharedStringsTable _sharedStringSource;
|
||||
|
||||
/**
|
||||
* controls whether Zip64 mode is used - Always became the default in POI 5.0.0
|
||||
*/
|
||||
private Zip64Mode zip64Mode = Zip64Mode.Always;
|
||||
protected Zip64Mode zip64Mode = Zip64Mode.Always;
|
||||
|
||||
/**
|
||||
* Construct a new workbook with default row window size
|
||||
|
@ -285,7 +289,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
return _randomAccessWindowSize;
|
||||
}
|
||||
|
||||
private void setRandomAccessWindowSize(int rowAccessWindowSize) {
|
||||
protected void setRandomAccessWindowSize(int rowAccessWindowSize) {
|
||||
if(rowAccessWindowSize == 0 || rowAccessWindowSize < -1) {
|
||||
throw new IllegalArgumentException("rowAccessWindowSize must be greater than 0 or -1");
|
||||
}
|
||||
|
@ -377,7 +381,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
_xFromSxHash.remove(xSheet);
|
||||
}
|
||||
|
||||
private XSSFSheet getSheetFromZipEntryName(String sheetRef)
|
||||
protected XSSFSheet getSheetFromZipEntryName(String sheetRef)
|
||||
{
|
||||
for(XSSFSheet sheet : _sxFromXHash.values())
|
||||
{
|
||||
|
@ -408,9 +412,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
// See bug 56557, we should not inject data into the special ChartSheets
|
||||
if (xSheet != null && !(xSheet instanceof XSSFChartSheet)) {
|
||||
SXSSFSheet sxSheet = getSXSSFSheet(xSheet);
|
||||
try (InputStream xis = sxSheet.getWorksheetXMLInputStream()) {
|
||||
copyStreamAndInjectWorksheet(is, zos, xis);
|
||||
}
|
||||
copyStreamAndInjectWorksheet(is, zos, createSheetInjector(sxSheet));
|
||||
} else {
|
||||
IOUtils.copy(is, zos);
|
||||
}
|
||||
|
@ -434,7 +436,17 @@ public class SXSSFWorkbook implements Workbook {
|
|||
}
|
||||
}
|
||||
|
||||
private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out, InputStream worksheetData) throws IOException {
|
||||
protected ISheetInjector createSheetInjector(SXSSFSheet sxSheet) throws IOException {
|
||||
return (output) -> {
|
||||
try (InputStream xis = sxSheet.getWorksheetXMLInputStream()) {
|
||||
// Copy the worksheet data to "output".
|
||||
IOUtils.copy(xis, output);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out, InputStream worksheetData) throws IOException {
|
||||
private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out, ISheetInjector sheetInjector) throws IOException {
|
||||
InputStreamReader inReader = new InputStreamReader(in, StandardCharsets.UTF_8);
|
||||
OutputStreamWriter outWriter = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
boolean needsStartTag = true;
|
||||
|
@ -526,8 +538,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
outWriter.write("<sheetData>\n");
|
||||
outWriter.flush();
|
||||
}
|
||||
//Copy the worksheet data to "out".
|
||||
IOUtils.copy(worksheetData,out);
|
||||
sheetInjector.writeSheetData(out);
|
||||
outWriter.write("</sheetData>");
|
||||
outWriter.flush();
|
||||
//Copy the rest of "in" to "out".
|
||||
|
@ -918,7 +929,8 @@ public class SXSSFWorkbook implements Workbook {
|
|||
for (SXSSFSheet sheet : _xFromSxHash.values())
|
||||
{
|
||||
try {
|
||||
sheet.getSheetDataWriter().close();
|
||||
SheetDataWriter _writer = sheet.getSheetDataWriter();
|
||||
if (_writer != null) _writer.close();
|
||||
} catch (IOException e) {
|
||||
logger.log(POILogger.WARN,
|
||||
"An exception occurred while closing sheet data writer for sheet "
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SheetDataWriter implements Closeable {
|
|||
private static final POILogger logger = POILogFactory.getLogger(SheetDataWriter.class);
|
||||
|
||||
private final File _fd;
|
||||
private final Writer _out;
|
||||
protected final Writer _out;
|
||||
private int _rownum;
|
||||
private int _numberOfFlushedRows;
|
||||
private int _lowestIndexOfFlushedRows; // meaningful only of _numberOfFlushedRows>0
|
||||
|
@ -73,6 +73,11 @@ public class SheetDataWriter implements Closeable {
|
|||
_out = createWriter(_fd);
|
||||
}
|
||||
|
||||
public SheetDataWriter(Writer writer) throws IOException {
|
||||
_fd = null;
|
||||
_out = writer;
|
||||
}
|
||||
|
||||
public SheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException {
|
||||
this();
|
||||
this._sharedStringSource = sharedStringsTable;
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Unlike SheetDataWriter, this writer does not create a temporary file, it writes data directly
|
||||
* to the provided OutputStream.
|
||||
* @since 5.0.0
|
||||
*/
|
||||
@Beta
|
||||
public class StreamingSheetWriter extends SheetDataWriter {
|
||||
private static final POILogger logger = POILogFactory.getLogger(StreamingSheetWriter.class);
|
||||
|
||||
public StreamingSheetWriter() throws IOException {
|
||||
throw new RuntimeException("StreamingSheetWriter requires OutputStream");
|
||||
}
|
||||
|
||||
public StreamingSheetWriter(OutputStream out) throws IOException {
|
||||
super(createWriter(out));
|
||||
logger.log(POILogger.DEBUG, "Preparing SSXSSF sheet writer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File createTempFile() throws IOException {
|
||||
throw new RuntimeException("Not supported with StreamingSheetWriter");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer createWriter(File fd) throws IOException {
|
||||
throw new RuntimeException("Not supported with StreamingSheetWriter");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a writer for the sheet data.
|
||||
*
|
||||
* @param out the output stream to write to
|
||||
*/
|
||||
protected static Writer createWriter(OutputStream out) throws IOException {
|
||||
return new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
_out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getWorksheetXMLInputStream() throws IOException {
|
||||
throw new RuntimeException("Not supported with StreamingSheetWriter");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean dispose() throws IOException {
|
||||
_out.close();
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.ss.usermodel.BaseTestXWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.util.NullOutputStream;
|
||||
import org.apache.poi.xssf.SXSSFITestDataProvider;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCell;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRow;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public final class TestEmittingSXSSFWorkbook extends BaseTestXWorkbook {
|
||||
|
||||
public TestEmittingSXSSFWorkbook() {
|
||||
super(SXSSFITestDataProvider.instance);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
((SXSSFITestDataProvider) _testDataProvider).cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* cloning of sheets is not supported in SXSSF
|
||||
*/
|
||||
@Override
|
||||
@Test
|
||||
public void cloneSheet() throws IOException {
|
||||
try {
|
||||
super.cloneSheet();
|
||||
fail("expected exception");
|
||||
} catch (RuntimeException e) {
|
||||
assertEquals("Not Implemented", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cloning of sheets is not supported in SXSSF
|
||||
*/
|
||||
@Override
|
||||
@Test
|
||||
public void sheetClone() throws IOException {
|
||||
try {
|
||||
super.sheetClone();
|
||||
fail("expected exception");
|
||||
} catch (RuntimeException e) {
|
||||
assertEquals("Not Implemented", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip this test, as SXSSF doesn't update formulas on sheet name changes.
|
||||
*/
|
||||
@Override
|
||||
@Ignore("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time")
|
||||
@Test
|
||||
public void setSheetName() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingWorkbook() throws IOException {
|
||||
XSSFWorkbook xssfWb1 = new XSSFWorkbook();
|
||||
xssfWb1.createSheet("S1");
|
||||
EmittingSXSSFWorkbook wb1 = new EmittingSXSSFWorkbook(xssfWb1);
|
||||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1);
|
||||
assertTrue(wb1.dispose());
|
||||
|
||||
EmittingSXSSFWorkbook wb2 = new EmittingSXSSFWorkbook(xssfWb2);
|
||||
assertEquals(1, wb2.getNumberOfSheets());
|
||||
Sheet sheet = wb2.getStreamingSheetAt(0);
|
||||
assertNotNull(sheet);
|
||||
assertEquals("S1", sheet.getSheetName());
|
||||
assertTrue(wb2.dispose());
|
||||
xssfWb2.close();
|
||||
xssfWb1.close();
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useSharedStringsTable() throws Exception {
|
||||
// not supported with EmittingSXSSF
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addToExistingWorkbook() throws IOException {
|
||||
XSSFWorkbook xssfWb1 = new XSSFWorkbook();
|
||||
xssfWb1.createSheet("S1");
|
||||
Sheet sheet = xssfWb1.createSheet("S2");
|
||||
Row row = sheet.createRow(1);
|
||||
Cell cell = row.createCell(1);
|
||||
cell.setCellValue("value 2_1_1");
|
||||
EmittingSXSSFWorkbook wb1 = new EmittingSXSSFWorkbook(xssfWb1);
|
||||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1);
|
||||
assertTrue(wb1.dispose());
|
||||
xssfWb1.close();
|
||||
|
||||
EmittingSXSSFWorkbook wb2 = new EmittingSXSSFWorkbook(xssfWb2);
|
||||
// Add a row to the existing empty sheet
|
||||
EmittingSXSSFSheet ssheet1 = wb2.getStreamingSheetAt(0);
|
||||
ssheet1.setRowGenerator((ssxSheet) -> {
|
||||
Row row1_1 = ssxSheet.createRow(1);
|
||||
Cell cell1_1_1 = row1_1.createCell(1);
|
||||
cell1_1_1.setCellValue("value 1_1_1");
|
||||
});
|
||||
|
||||
// Add a row to the existing non-empty sheet
|
||||
EmittingSXSSFSheet ssheet2 = wb2.getStreamingSheetAt(1);
|
||||
ssheet2.setRowGenerator((ssxSheet) -> {
|
||||
Row row2_2 = ssxSheet.createRow(2);
|
||||
Cell cell2_2_1 = row2_2.createCell(1);
|
||||
cell2_2_1.setCellValue("value 2_2_1");
|
||||
});
|
||||
// Add a sheet with one row
|
||||
EmittingSXSSFSheet ssheet3 = wb2.createSheet("S3");
|
||||
ssheet3.setRowGenerator((ssxSheet) -> {
|
||||
Row row3_1 = ssxSheet.createRow(1);
|
||||
Cell cell3_1_1 = row3_1.createCell(1);
|
||||
cell3_1_1.setCellValue("value 3_1_1");
|
||||
});
|
||||
|
||||
XSSFWorkbook xssfWb3 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb2);
|
||||
wb2.close();
|
||||
|
||||
assertEquals(3, xssfWb3.getNumberOfSheets());
|
||||
// Verify sheet 1
|
||||
XSSFSheet sheet1 = xssfWb3.getSheetAt(0);
|
||||
assertEquals("S1", sheet1.getSheetName());
|
||||
assertEquals(1, sheet1.getPhysicalNumberOfRows());
|
||||
XSSFRow row1_1 = sheet1.getRow(1);
|
||||
assertNotNull(row1_1);
|
||||
XSSFCell cell1_1_1 = row1_1.getCell(1);
|
||||
assertNotNull(cell1_1_1);
|
||||
assertEquals("value 1_1_1", cell1_1_1.getStringCellValue());
|
||||
// Verify sheet 2
|
||||
XSSFSheet sheet2 = xssfWb3.getSheetAt(1);
|
||||
assertEquals("S2", sheet2.getSheetName());
|
||||
assertEquals(2, sheet2.getPhysicalNumberOfRows());
|
||||
Row row2_1 = sheet2.getRow(1);
|
||||
assertNotNull(row2_1);
|
||||
Cell cell2_1_1 = row2_1.getCell(1);
|
||||
assertNotNull(cell2_1_1);
|
||||
assertEquals("value 2_1_1", cell2_1_1.getStringCellValue());
|
||||
XSSFRow row2_2 = sheet2.getRow(2);
|
||||
assertNotNull(row2_2);
|
||||
XSSFCell cell2_2_1 = row2_2.getCell(1);
|
||||
assertNotNull(cell2_2_1);
|
||||
assertEquals("value 2_2_1", cell2_2_1.getStringCellValue());
|
||||
// Verify sheet 3
|
||||
XSSFSheet sheet3 = xssfWb3.getSheetAt(2);
|
||||
assertEquals("S3", sheet3.getSheetName());
|
||||
assertEquals(1, sheet3.getPhysicalNumberOfRows());
|
||||
XSSFRow row3_1 = sheet3.getRow(1);
|
||||
assertNotNull(row3_1);
|
||||
XSSFCell cell3_1_1 = row3_1.getCell(1);
|
||||
assertNotNull(cell3_1_1);
|
||||
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue());
|
||||
|
||||
xssfWb2.close();
|
||||
xssfWb3.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sheetdataWriter() throws IOException {
|
||||
EmittingSXSSFWorkbook wb = new EmittingSXSSFWorkbook();
|
||||
SXSSFSheet sh = wb.createSheet();
|
||||
assertSame(sh.getClass(), EmittingSXSSFSheet.class);
|
||||
SheetDataWriter wr = sh.getSheetDataWriter();
|
||||
assertNull(wr);
|
||||
wb.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gzipSheetdataWriter() throws IOException {
|
||||
EmittingSXSSFWorkbook wb = new EmittingSXSSFWorkbook();
|
||||
wb.setCompressTempFiles(true);
|
||||
|
||||
final int rowNum = 1000;
|
||||
final int sheetNum = 5;
|
||||
populateData(wb, 1000, 5);
|
||||
|
||||
XSSFWorkbook xwb = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
|
||||
for (int i = 0; i < sheetNum; i++) {
|
||||
Sheet sh = xwb.getSheetAt(i);
|
||||
assertEquals("sheet" + i, sh.getSheetName());
|
||||
for (int j = 0; j < rowNum; j++) {
|
||||
Row row = sh.getRow(j);
|
||||
assertNotNull("row[" + j + "]", row);
|
||||
Cell cell1 = row.getCell(0);
|
||||
assertEquals(new CellReference(cell1).formatAsString(), cell1.getStringCellValue());
|
||||
|
||||
Cell cell2 = row.getCell(1);
|
||||
assertEquals(i, (int) cell2.getNumericCellValue());
|
||||
|
||||
Cell cell3 = row.getCell(2);
|
||||
assertEquals(j, (int) cell3.getNumericCellValue());
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(wb.dispose());
|
||||
xwb.close();
|
||||
wb.close();
|
||||
}
|
||||
|
||||
private static void assertWorkbookDispose(EmittingSXSSFWorkbook wb) {
|
||||
populateData(wb, 1000, 5);
|
||||
|
||||
for (Sheet sheet : wb) {
|
||||
EmittingSXSSFSheet sxSheet = (EmittingSXSSFSheet) sheet;
|
||||
assertNull(sxSheet.getSheetDataWriter());
|
||||
}
|
||||
|
||||
assertTrue(wb.dispose());
|
||||
|
||||
for (Sheet sheet : wb) {
|
||||
EmittingSXSSFSheet sxSheet = (EmittingSXSSFSheet) sheet;
|
||||
assertNull(sxSheet.getSheetDataWriter());
|
||||
}
|
||||
}
|
||||
|
||||
private static void populateData(EmittingSXSSFWorkbook wb, final int rowNum, final int sheetNum) {
|
||||
for (int i = 0; i < sheetNum; i++) {
|
||||
EmittingSXSSFSheet sheet = wb.createSheet("sheet" + i);
|
||||
int index = i;
|
||||
sheet.setRowGenerator((sh) -> {
|
||||
for (int j = 0; j < rowNum; j++) {
|
||||
Row row = sh.createRow(j);
|
||||
Cell cell1 = row.createCell(0);
|
||||
cell1.setCellValue(new CellReference(cell1).formatAsString());
|
||||
|
||||
Cell cell2 = row.createCell(1);
|
||||
cell2.setCellValue(index);
|
||||
|
||||
Cell cell3 = row.createCell(2);
|
||||
cell3.setCellValue(j);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void workbookDispose() throws IOException {
|
||||
EmittingSXSSFWorkbook wb1 = new EmittingSXSSFWorkbook();
|
||||
// the underlying writer is SheetDataWriter
|
||||
assertWorkbookDispose(wb1);
|
||||
wb1.close();
|
||||
|
||||
EmittingSXSSFWorkbook wb2 = new EmittingSXSSFWorkbook();
|
||||
wb2.setCompressTempFiles(true);
|
||||
// the underlying writer is GZIPSheetDataWriter
|
||||
assertWorkbookDispose(wb2);
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
@Ignore("currently writing the same sheet multiple times is not supported...")
|
||||
@Test
|
||||
public void bug53515() throws Exception {
|
||||
Workbook wb1 = new SXSSFWorkbook(10);
|
||||
populateWorkbook(wb1);
|
||||
saveTwice(wb1);
|
||||
Workbook wb2 = new XSSFWorkbook();
|
||||
populateWorkbook(wb2);
|
||||
saveTwice(wb2);
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
||||
@Ignore("Crashes the JVM because of documented JVM behavior with concurrent writing/reading of zip-files, "
|
||||
+ "see http://www.oracle.com/technetwork/java/javase/documentation/overview-156328.html")
|
||||
@Test
|
||||
public void bug53515a() throws Exception {
|
||||
File out = new File("Test.xlsx");
|
||||
assertTrue(!out.exists() || out.delete());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final SXSSFWorkbook wb;
|
||||
if (out.exists()) {
|
||||
wb = new SXSSFWorkbook((XSSFWorkbook) WorkbookFactory.create(out));
|
||||
} else {
|
||||
wb = new SXSSFWorkbook(10);
|
||||
}
|
||||
|
||||
try {
|
||||
FileOutputStream outSteam = new FileOutputStream(out);
|
||||
if (i == 0) {
|
||||
populateWorkbook(wb);
|
||||
} else {
|
||||
System.gc();
|
||||
System.gc();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
wb.write(outSteam);
|
||||
// assertTrue(wb.dispose());
|
||||
outSteam.close();
|
||||
} finally {
|
||||
assertTrue(wb.dispose());
|
||||
}
|
||||
wb.close();
|
||||
}
|
||||
assertTrue(out.exists());
|
||||
assertTrue(out.delete());
|
||||
}
|
||||
|
||||
private static void populateWorkbook(Workbook wb) {
|
||||
Sheet sh = wb.createSheet();
|
||||
for (int rownum = 0; rownum < 100; rownum++) {
|
||||
Row row = sh.createRow(rownum);
|
||||
for (int cellnum = 0; cellnum < 10; cellnum++) {
|
||||
Cell cell = row.createCell(cellnum);
|
||||
String address = new CellReference(cell).formatAsString();
|
||||
cell.setCellValue(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void saveTwice(Workbook wb) throws Exception {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
try {
|
||||
NullOutputStream out = new NullOutputStream();
|
||||
wb.write(out);
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
throw new Exception("ERROR: failed on " + (i + 1) + "th time calling " + wb.getClass().getName()
|
||||
+ ".write() with exception " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeDoesNotModifyWorkbook() throws IOException {
|
||||
final String filename = "SampleSS.xlsx";
|
||||
final File file = POIDataSamples.getSpreadSheetInstance().getFile(filename);
|
||||
|
||||
// Some tests commented out because close() modifies the file
|
||||
// See bug 58779
|
||||
|
||||
// String
|
||||
// wb = new SXSSFWorkbook(new XSSFWorkbook(file.getPath()));
|
||||
// assertCloseDoesNotModifyFile(filename, wb);
|
||||
|
||||
// File
|
||||
// wb = new SXSSFWorkbook(new XSSFWorkbook(file));
|
||||
// assertCloseDoesNotModifyFile(filename, wb);
|
||||
|
||||
// InputStream
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
XSSFWorkbook xwb = new XSSFWorkbook(fis);
|
||||
SXSSFWorkbook wb = new SXSSFWorkbook(xwb)) {
|
||||
assertCloseDoesNotModifyFile(filename, wb);
|
||||
}
|
||||
|
||||
// OPCPackage
|
||||
// wb = new SXSSFWorkbook(new XSSFWorkbook(OPCPackage.open(file)));
|
||||
// assertCloseDoesNotModifyFile(filename, wb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug #59743
|
||||
*
|
||||
* this is only triggered on other files apart of sheet[1,2,...].xml as those are either copied uncompressed or with
|
||||
* the use of GZIPInputStream so we use shared strings
|
||||
*/
|
||||
@Test
|
||||
public void testZipBombNotTriggeredOnUselessContent() throws IOException {
|
||||
SXSSFWorkbook swb = new SXSSFWorkbook(null, 1, true, true);
|
||||
SXSSFSheet s = swb.createSheet();
|
||||
char[] useless = new char[32767];
|
||||
Arrays.fill(useless, ' ');
|
||||
|
||||
for (int row = 0; row < 1; row++) {
|
||||
Row r = s.createRow(row);
|
||||
for (int col = 0; col < 10; col++) {
|
||||
char[] prefix = Integer.toHexString(row * 1000 + col).toCharArray();
|
||||
Arrays.fill(useless, 0, 10, ' ');
|
||||
System.arraycopy(prefix, 0, useless, 0, prefix.length);
|
||||
String ul = new String(useless);
|
||||
r.createCell(col, CellType.STRING).setCellValue(ul);
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
swb.write(bos);
|
||||
swb.dispose();
|
||||
swb.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid accident changes to the template, you should be able to create a SXSSFWorkbook from a read-only XSSF
|
||||
* one, then change + save that (only). See bug #60010 TODO Fix this to work!
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void createFromReadOnlyWorkbook() throws Exception {
|
||||
String sheetName = "Test SXSSF";
|
||||
File input = XSSFTestDataSamples.getSampleFile("sample.xlsx");
|
||||
|
||||
try (OPCPackage pkg = OPCPackage.open(input, PackageAccess.READ)) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try (XSSFWorkbook xssf = new XSSFWorkbook(pkg)) {
|
||||
try (SXSSFWorkbook wb = new SXSSFWorkbook(xssf, 2)) {
|
||||
Sheet s = wb.createSheet(sheetName);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Row r = s.createRow(i);
|
||||
r.createCell(0).setCellValue(true);
|
||||
r.createCell(1).setCellValue(2.4);
|
||||
r.createCell(2).setCellValue("Test Row " + i);
|
||||
}
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
|
||||
wb.write(bos);
|
||||
wb.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
try (XSSFWorkbook xssf = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
Sheet s = xssf.getSheet(sheetName);
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
assertTrue(s.getRow(0).getCell(0).getBooleanCellValue());
|
||||
assertEquals("Test Row 9", s.getRow(9).getCell(2).getStringCellValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test56557() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56557.xlsx");
|
||||
|
||||
// Using streaming XSSFWorkbook makes the output file invalid
|
||||
wb = new SXSSFWorkbook(((XSSFWorkbook) wb));
|
||||
|
||||
// Should not throw POIXMLException: java.io.IOException: Unable to parse xml bean when reading back
|
||||
Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
assertNotNull(wbBack);
|
||||
wbBack.close();
|
||||
|
||||
wb.close();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue