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,11 +106,13 @@ public final class SXSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator {
|
|||
// Process the sheets as best we can
|
||||
for (Sheet sheet : wb) {
|
||||
|
||||
// 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");
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,19 +61,26 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
|||
|
||||
/**
|
||||
* Streaming version of XSSFSheet implementing the "BigGridDemo" strategy.
|
||||
*/
|
||||
*/
|
||||
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;
|
||||
|
@ -90,8 +97,8 @@ public class SXSSFSheet implements Sheet
|
|||
return _writer;
|
||||
}
|
||||
|
||||
/* Gets "<sheetData>" document fragment*/
|
||||
public InputStream getWorksheetXMLInputStream() throws IOException
|
||||
/* Gets "<sheetData>" document fragment*/
|
||||
public InputStream getWorksheetXMLInputStream() throws IOException
|
||||
{
|
||||
// flush all remaining data and close the temp file writer
|
||||
flushRows(0);
|
||||
|
@ -99,7 +106,7 @@ public class SXSSFSheet implements Sheet
|
|||
return _writer.getWorksheetXMLInputStream();
|
||||
}
|
||||
|
||||
//start of interface implementation
|
||||
//start of interface implementation
|
||||
@Override
|
||||
public Iterator<Row> iterator()
|
||||
{
|
||||
|
@ -128,7 +135,7 @@ public class SXSSFSheet implements Sheet
|
|||
if(rownum <= _writer.getLastFlushedRow() ) {
|
||||
throw new IllegalArgumentException(
|
||||
"Attempting to write a row["+rownum+"] " +
|
||||
"in the range [0," + _writer.getLastFlushedRow() + "] that is already written to disk.");
|
||||
"in the range [0," + _writer.getLastFlushedRow() + "] that is already written to disk.");
|
||||
}
|
||||
|
||||
// attempt to overwrite a existing row in the input template
|
||||
|
@ -143,7 +150,7 @@ public class SXSSFSheet implements Sheet
|
|||
allFlushed = false;
|
||||
if(_randomAccessWindowSize >= 0 && _rows.size() > _randomAccessWindowSize) {
|
||||
try {
|
||||
flushRows(_randomAccessWindowSize);
|
||||
flushRows(_randomAccessWindowSize);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
|
@ -274,7 +281,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
/**
|
||||
* Get the actual column width in pixels
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Please note, that this method works correctly only for workbooks
|
||||
* with the default font size (Calibri 11pt for .xlsx).
|
||||
|
@ -283,8 +290,8 @@ public class SXSSFSheet implements Sheet
|
|||
@Override
|
||||
public float getColumnWidthInPixels(int columnIndex) {
|
||||
return _sh.getColumnWidthInPixels(columnIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default column width for the sheet (if the columns do not define their own width)
|
||||
* in characters
|
||||
|
@ -308,7 +315,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _sh.getDefaultColumnWidth();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the default row height for the sheet (if the rows do not define their own height) in
|
||||
|
@ -356,7 +363,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_sh.setDefaultRowHeightInPoints(height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the CellStyle that applies to the given
|
||||
|
@ -461,7 +468,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_sh.removeMergedRegion(index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a merged region of cells (hence letting them free)
|
||||
*
|
||||
|
@ -568,7 +575,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _sh.isDisplayZeros();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether the worksheet is displayed from right to left instead of from left to right.
|
||||
*
|
||||
|
@ -577,7 +584,7 @@ public class SXSSFSheet implements Sheet
|
|||
@Override
|
||||
public void setRightToLeft(boolean value)
|
||||
{
|
||||
_sh.setRightToLeft(value);
|
||||
_sh.setRightToLeft(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -588,7 +595,7 @@ public class SXSSFSheet implements Sheet
|
|||
@Override
|
||||
public boolean isRightToLeft()
|
||||
{
|
||||
return _sh.isRightToLeft();
|
||||
return _sh.isRightToLeft();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -733,7 +740,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_sh.setPrintGridlines(show);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether row and column headings are printed.
|
||||
*
|
||||
|
@ -841,7 +848,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _sh.getProtect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the protection enabled as well as the password
|
||||
* @param password to set for protection. Pass <code>null</code> to remove protection
|
||||
|
@ -851,7 +858,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_sh.protectSheet(password);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Answer whether scenario protection is enabled or disabled
|
||||
*
|
||||
|
@ -862,7 +869,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _sh.getScenarioProtect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Window zoom magnification for current view representing percent values.
|
||||
* Valid values range from 10 to 400. Horizontal and Vertical scale together.
|
||||
|
@ -933,7 +940,7 @@ public class SXSSFSheet implements Sheet
|
|||
*/
|
||||
@Override
|
||||
public void setForceFormulaRecalculation(boolean value) {
|
||||
_sh.setForceFormulaRecalculation(value);
|
||||
_sh.setForceFormulaRecalculation(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -942,12 +949,12 @@ public class SXSSFSheet implements Sheet
|
|||
*/
|
||||
@Override
|
||||
public boolean getForceFormulaRecalculation() {
|
||||
return _sh.getForceFormulaRecalculation();
|
||||
return _sh.getForceFormulaRecalculation();
|
||||
}
|
||||
|
||||
/**
|
||||
* <i>Not implemented for SXSSFSheets</i>
|
||||
*
|
||||
*
|
||||
* Shifts rows between startRow and endRow n number of rows.
|
||||
* If you use a negative number, it will shift rows up.
|
||||
* Code ensures that rows don't wrap around.
|
||||
|
@ -969,7 +976,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
/**
|
||||
* <i>Not implemented for SXSSFSheets</i>
|
||||
*
|
||||
*
|
||||
* Shifts rows between startRow and endRow n number of rows.
|
||||
* If you use a negative number, it will shift rows up.
|
||||
* Code ensures that rows don't wrap around
|
||||
|
@ -1236,7 +1243,7 @@ public class SXSSFSheet implements Sheet
|
|||
* Please note the rows being grouped <em>must</em> be in the current window,
|
||||
* if the rows are already flushed then groupRow has no effect.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* Correct code:
|
||||
* <pre><code>
|
||||
* Workbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory
|
||||
|
@ -1249,8 +1256,8 @@ public class SXSSFSheet implements Sheet
|
|||
* }
|
||||
*
|
||||
* </code></pre>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Incorrect code:
|
||||
* <pre><code>
|
||||
* Workbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory
|
||||
|
@ -1261,7 +1268,7 @@ public class SXSSFSheet implements Sheet
|
|||
* sh.groupRow(100, 200); // the rows in the range [100, 200] are already flushed and groupRows has no effect
|
||||
*
|
||||
* </code></pre>
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param fromRow start row (0-based)
|
||||
* @param toRow end row (0-based)
|
||||
|
@ -1280,7 +1287,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
setWorksheetOutlineLevelRow();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set row groupings (like groupRow) in a stream-friendly manner
|
||||
*
|
||||
|
@ -1308,8 +1315,8 @@ public class SXSSFSheet implements Sheet
|
|||
private void setWorksheetOutlineLevelRow() {
|
||||
CTWorksheet ct = _sh.getCTWorksheet();
|
||||
CTSheetFormatPr pr = ct.isSetSheetFormatPr() ?
|
||||
ct.getSheetFormatPr() :
|
||||
ct.addNewSheetFormatPr();
|
||||
ct.getSheetFormatPr() :
|
||||
ct.addNewSheetFormatPr();
|
||||
if(outlineLevelRow > 0) {
|
||||
pr.setOutlineLevelRow((short)outlineLevelRow);
|
||||
}
|
||||
|
@ -1346,7 +1353,7 @@ public class SXSSFSheet implements Sheet
|
|||
throw new RuntimeException("Unable to expand row: Not Implemented");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param rowIndex the zero based row index to collapse
|
||||
*/
|
||||
|
@ -1359,7 +1366,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
// Hide all the columns until the end of the group
|
||||
int lastRow = writeHidden(row, startRow);
|
||||
SXSSFRow lastRowObj = getRow(lastRow);
|
||||
SXSSFRow lastRowObj = getRow(lastRow);
|
||||
if (lastRowObj != null) {
|
||||
lastRowObj.setCollapsed(true);
|
||||
} else {
|
||||
|
@ -1368,7 +1375,7 @@ public class SXSSFSheet implements Sheet
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param rowIndex the zero based row index to find from
|
||||
*/
|
||||
|
@ -1388,7 +1395,7 @@ public class SXSSFSheet implements Sheet
|
|||
}
|
||||
return currentRow + 1;
|
||||
}
|
||||
|
||||
|
||||
private int writeHidden(SXSSFRow xRow, int rowIndex) {
|
||||
int level = xRow.getOutlineLevel();
|
||||
SXSSFRow currRow = getRow(rowIndex);
|
||||
|
@ -1412,8 +1419,8 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_sh.setDefaultColumnStyle(column, style);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Track a column in the sheet for auto-sizing.
|
||||
* Note this has undefined behavior if a column is tracked after one or more rows are written to the sheet.
|
||||
|
@ -1428,7 +1435,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_autoSizeColumnTracker.trackColumn(column);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Track several columns in the sheet for auto-sizing.
|
||||
* Note this has undefined behavior if columns are tracked after one or more rows are written to the sheet.
|
||||
|
@ -1441,7 +1448,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_autoSizeColumnTracker.trackColumns(columns);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tracks all columns in the sheet for auto-sizing. If this is called, individual columns do not need to be tracked.
|
||||
* Because determining the best-fit width for a cell is expensive, this may affect the performance.
|
||||
|
@ -1451,7 +1458,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_autoSizeColumnTracker.trackAllColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a column that was previously marked for inclusion in auto-size column tracking.
|
||||
* When a column is untracked, the best-fit width is forgotten.
|
||||
|
@ -1467,7 +1474,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _autoSizeColumnTracker.untrackColumn(column);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Untracks several columns in the sheet for auto-sizing.
|
||||
* When a column is untracked, the best-fit width is forgotten.
|
||||
|
@ -1481,7 +1488,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _autoSizeColumnTracker.untrackColumns(columns);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Untracks all columns in the sheet for auto-sizing. Best-fit column widths are forgotten.
|
||||
* If this is called, individual columns do not need to be untracked.
|
||||
|
@ -1491,7 +1498,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
_autoSizeColumnTracker.untrackAllColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if column is currently tracked for auto-sizing.
|
||||
*
|
||||
|
@ -1503,7 +1510,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _autoSizeColumnTracker.isColumnTracked(column);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the currently tracked columns for auto-sizing.
|
||||
* Note if all columns are tracked, this will only return the columns that have been explicitly or implicitly tracked,
|
||||
|
@ -1527,7 +1534,7 @@ public class SXSSFSheet implements Sheet
|
|||
* </p>
|
||||
* You can specify whether the content of merged cells should be considered or ignored.
|
||||
* Default is to ignore merged cells.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Special note about SXSSF implementation: You must register the columns you wish to track with
|
||||
* the SXSSFSheet using {@link #trackColumnForAutoSizing(int)} or {@link #trackAllColumnsForAutoSizing()}.
|
||||
|
@ -1554,7 +1561,7 @@ public class SXSSFSheet implements Sheet
|
|||
* </p>
|
||||
* You can specify whether the content of merged cells should be considered or ignored.
|
||||
* Default is to ignore merged cells.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Special note about SXSSF implementation: You must register the columns you wish to track with
|
||||
* the SXSSFSheet using {@link #trackColumnForAutoSizing(int)} or {@link #trackAllColumnsForAutoSizing()}.
|
||||
|
@ -1590,21 +1597,21 @@ public class SXSSFSheet implements Sheet
|
|||
catch (final IllegalStateException e) {
|
||||
throw new IllegalStateException("Could not auto-size column. Make sure the column was tracked prior to auto-sizing the column.", e);
|
||||
}
|
||||
|
||||
|
||||
// get the best-fit width of rows currently in the random access window
|
||||
final int activeWidth = (int) (256 * SheetUtil.getColumnWidth(this, column, useMergedCells));
|
||||
|
||||
// the best-fit width for both flushed rows and random access window rows
|
||||
// flushedWidth or activeWidth may be negative if column contains only blank cells
|
||||
final int bestFitWidth = Math.max(flushedWidth, activeWidth);
|
||||
|
||||
|
||||
if (bestFitWidth > 0) {
|
||||
final int maxColumnWidth = 255*256; // The maximum column width for an individual cell is 255 characters
|
||||
final int width = Math.min(bestFitWidth, maxColumnWidth);
|
||||
setColumnWidth(column, width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns cell comment for the specified row and column
|
||||
*
|
||||
|
@ -1615,7 +1622,7 @@ public class SXSSFSheet implements Sheet
|
|||
{
|
||||
return _sh.getCellComment(ref);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all cell comments on this sheet.
|
||||
* @return A map of each Comment in the sheet, keyed on the cell address where
|
||||
|
@ -1625,7 +1632,7 @@ public class SXSSFSheet implements Sheet
|
|||
public Map<CellAddress, XSSFComment> getCellComments() {
|
||||
return _sh.getCellComments();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Hyperlink in this sheet anchored at row, column
|
||||
*
|
||||
|
@ -1637,7 +1644,7 @@ public class SXSSFSheet implements Sheet
|
|||
public XSSFHyperlink getHyperlink(int row, int column) {
|
||||
return _sh.getHyperlink(row, column);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Hyperlink in this sheet located in a cell specified by {code addr}
|
||||
*
|
||||
|
@ -1649,7 +1656,7 @@ public class SXSSFSheet implements Sheet
|
|||
public XSSFHyperlink getHyperlink(CellAddress addr) {
|
||||
return _sh.getHyperlink(addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of Hyperlinks in this sheet
|
||||
*
|
||||
|
@ -1659,7 +1666,7 @@ public class SXSSFSheet implements Sheet
|
|||
public List<XSSFHyperlink> getHyperlinkList() {
|
||||
return _sh.getHyperlinkList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -1744,7 +1751,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
throw new RuntimeException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataValidationHelper getDataValidationHelper()
|
||||
{
|
||||
|
@ -1769,7 +1776,7 @@ public class SXSSFSheet implements Sheet
|
|||
|
||||
/**
|
||||
* Enable filtering for a range of cells
|
||||
*
|
||||
*
|
||||
* @param range the range of cells to filter
|
||||
*/
|
||||
@Override
|
||||
|
@ -1782,30 +1789,30 @@ public class SXSSFSheet implements Sheet
|
|||
public SheetConditionalFormatting getSheetConditionalFormatting(){
|
||||
return _sh.getSheetConditionalFormatting();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public CellRangeAddress getRepeatingRows() {
|
||||
return _sh.getRepeatingRows();
|
||||
return _sh.getRepeatingRows();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CellRangeAddress getRepeatingColumns() {
|
||||
return _sh.getRepeatingColumns();
|
||||
return _sh.getRepeatingColumns();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRepeatingRows(CellRangeAddress rowRangeRef) {
|
||||
_sh.setRepeatingRows(rowRangeRef);
|
||||
_sh.setRepeatingRows(rowRangeRef);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRepeatingColumns(CellRangeAddress columnRangeRef) {
|
||||
_sh.setRepeatingColumns(columnRangeRef);
|
||||
_sh.setRepeatingColumns(columnRangeRef);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//end of interface implementation
|
||||
/**
|
||||
* Specifies how many rows can be accessed at most via getRow().
|
||||
|
@ -1821,12 +1828,12 @@ public class SXSSFSheet implements Sheet
|
|||
*/
|
||||
public void setRandomAccessWindowSize(int value)
|
||||
{
|
||||
if(value == 0 || value < -1) {
|
||||
throw new IllegalArgumentException("RandomAccessWindowSize must be either -1 or a positive integer");
|
||||
}
|
||||
_randomAccessWindowSize = value;
|
||||
if(value == 0 || value < -1) {
|
||||
throw new IllegalArgumentException("RandomAccessWindowSize must be either -1 or a positive integer");
|
||||
}
|
||||
_randomAccessWindowSize = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Are all rows flushed to disk?
|
||||
*/
|
||||
|
@ -1880,7 +1887,7 @@ public class SXSSFSheet implements Sheet
|
|||
}
|
||||
public void changeRowNum(SXSSFRow row, int newRowNum)
|
||||
{
|
||||
|
||||
|
||||
removeRow(row);
|
||||
_rows.put(newRowNum,row);
|
||||
}
|
||||
|
@ -1904,7 +1911,7 @@ public class SXSSFSheet implements Sheet
|
|||
if (!allFlushed) {
|
||||
flushRows();
|
||||
}
|
||||
return _writer.dispose();
|
||||
return _writer == null || _writer.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1935,21 +1942,21 @@ public class SXSSFSheet implements Sheet
|
|||
public void setTabColor(XSSFColor color) {
|
||||
_sh.setTabColor(color);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable sheet protection
|
||||
*/
|
||||
public void enableLocking() {
|
||||
safeGetProtectionField().setSheet(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disable sheet protection
|
||||
*/
|
||||
public void disableLocking() {
|
||||
safeGetProtectionField().setSheet(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Autofilters locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -1958,7 +1965,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockAutoFilter(boolean enabled) {
|
||||
safeGetProtectionField().setAutoFilter(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Deleting columns locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -1967,7 +1974,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockDeleteColumns(boolean enabled) {
|
||||
safeGetProtectionField().setDeleteColumns(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Deleting rows locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -1976,7 +1983,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockDeleteRows(boolean enabled) {
|
||||
safeGetProtectionField().setDeleteRows(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Formatting cells locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -1985,7 +1992,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockFormatCells(boolean enabled) {
|
||||
safeGetProtectionField().setFormatCells(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Formatting columns locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -1994,7 +2001,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockFormatColumns(boolean enabled) {
|
||||
safeGetProtectionField().setFormatColumns(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Formatting rows locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2003,7 +2010,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockFormatRows(boolean enabled) {
|
||||
safeGetProtectionField().setFormatRows(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Inserting columns locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2012,7 +2019,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockInsertColumns(boolean enabled) {
|
||||
safeGetProtectionField().setInsertColumns(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Inserting hyperlinks locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2021,7 +2028,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockInsertHyperlinks(boolean enabled) {
|
||||
safeGetProtectionField().setInsertHyperlinks(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Inserting rows locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2030,7 +2037,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockInsertRows(boolean enabled) {
|
||||
safeGetProtectionField().setInsertRows(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Pivot Tables locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2039,7 +2046,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockPivotTables(boolean enabled) {
|
||||
safeGetProtectionField().setPivotTables(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Sort locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2048,7 +2055,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockSort(boolean enabled) {
|
||||
safeGetProtectionField().setSort(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Objects locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2057,7 +2064,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockObjects(boolean enabled) {
|
||||
safeGetProtectionField().setObjects(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Scenarios locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2066,7 +2073,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockScenarios(boolean enabled) {
|
||||
safeGetProtectionField().setScenarios(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Selection of locked cells locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2075,7 +2082,7 @@ public class SXSSFSheet implements Sheet
|
|||
public void lockSelectLockedCells(boolean enabled) {
|
||||
safeGetProtectionField().setSelectLockedCells(enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable or disable Selection of unlocked cells locking.
|
||||
* This does not modify sheet protection status.
|
||||
|
@ -2085,7 +2092,7 @@ public class SXSSFSheet implements Sheet
|
|||
safeGetProtectionField().setSelectUnlockedCells(enabled);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private CTSheetProtection safeGetProtectionField() {
|
||||
CTWorksheet ct = _sh.getCTWorksheet();
|
||||
if (!isSheetProtectionEnabled()) {
|
||||
|
@ -2093,12 +2100,12 @@ public class SXSSFSheet implements Sheet
|
|||
}
|
||||
return ct.getSheetProtection();
|
||||
}
|
||||
|
||||
|
||||
/* package */ boolean isSheetProtectionEnabled() {
|
||||
CTWorksheet ct = _sh.getCTWorksheet();
|
||||
return (ct.isSetSheetProtection());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set background color of the sheet tab
|
||||
*
|
||||
|
@ -2112,10 +2119,10 @@ public class SXSSFSheet implements Sheet
|
|||
color.setIndexed(colorIndex);
|
||||
pr.setTabColor(color);
|
||||
}
|
||||
|
||||
@NotImplemented
|
||||
@Override
|
||||
public void shiftColumns(int startColumn, int endColumn, int n){
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
|
||||
@NotImplemented
|
||||
@Override
|
||||
public void shiftColumns(int startColumn, int endColumn, int n){
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,23 +115,23 @@ 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
|
||||
*/
|
||||
public SXSSFWorkbook(){
|
||||
this(null /*workbook*/);
|
||||
this(null /*workbook*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Construct a workbook from a template.</p>
|
||||
*
|
||||
*
|
||||
* There are three use-cases to use SXSSFWorkbook(XSSFWorkbook) :
|
||||
* <ol>
|
||||
* <li>
|
||||
|
@ -144,7 +148,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* </li>
|
||||
* </ol>
|
||||
* All three use cases can work in a combination.
|
||||
*
|
||||
*
|
||||
* What is not supported:
|
||||
* <ul>
|
||||
* <li>
|
||||
|
@ -161,9 +165,9 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @param workbook the template workbook
|
||||
*/
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook){
|
||||
this(workbook, DEFAULT_WINDOW_SIZE);
|
||||
this(workbook, DEFAULT_WINDOW_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an workbook from an existing workbook.
|
||||
|
@ -186,7 +190,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @param rowAccessWindowSize the number of rows that are kept in memory until flushed out, see above.
|
||||
*/
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize){
|
||||
this(workbook,rowAccessWindowSize, false);
|
||||
this(workbook,rowAccessWindowSize, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,8 +214,8 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @param rowAccessWindowSize the number of rows that are kept in memory until flushed out, see above.
|
||||
* @param compressTmpFiles whether to use gzip compression for temporary files
|
||||
*/
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles){
|
||||
this(workbook,rowAccessWindowSize, compressTmpFiles, false);
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles) {
|
||||
this(workbook,rowAccessWindowSize, compressTmpFiles, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,11 +241,11 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @param compressTmpFiles whether to use gzip compression for temporary files
|
||||
* @param useSharedStringsTable whether to use a shared strings table
|
||||
*/
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable){
|
||||
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable) {
|
||||
setRandomAccessWindowSize(rowAccessWindowSize);
|
||||
setCompressTempFiles(compressTmpFiles);
|
||||
if (workbook == null) {
|
||||
_wb=new XSSFWorkbook();
|
||||
_wb = new XSSFWorkbook();
|
||||
_sharedStringSource = useSharedStringsTable ? _wb.getSharedStringSource() : null;
|
||||
} else {
|
||||
_wb=workbook;
|
||||
|
@ -273,7 +277,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @param rowAccessWindowSize the number of rows that are kept in memory until flushed out, see above.
|
||||
*/
|
||||
public SXSSFWorkbook(int rowAccessWindowSize){
|
||||
this(null /*workbook*/, rowAccessWindowSize);
|
||||
this(null /*workbook*/, rowAccessWindowSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -282,10 +286,10 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* @return The number of rows that are kept in memory at once before flushing them out.
|
||||
*/
|
||||
public int getRandomAccessWindowSize() {
|
||||
return _randomAccessWindowSize;
|
||||
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");
|
||||
}
|
||||
|
@ -323,7 +327,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
* Please note the the "compress" option may cause performance penalty.
|
||||
* </p>
|
||||
* <p>
|
||||
* Setting this option only affects compression for subsequent <code>createSheet()</code>
|
||||
* Setting this option only affects compression for subsequent <code>createSheet()</code>
|
||||
* calls.
|
||||
* </p>
|
||||
* @param compress whether to compress temp files
|
||||
|
@ -331,7 +335,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public void setCompressTempFiles(boolean compress) {
|
||||
_compressTmpFiles = compress;
|
||||
}
|
||||
|
||||
|
||||
@Internal
|
||||
protected SharedStringsTable getSharedStringSource() {
|
||||
return _sharedStringSource;
|
||||
|
@ -341,7 +345,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
if(_compressTmpFiles) {
|
||||
return new GZIPSheetDataWriter(_sharedStringSource);
|
||||
}
|
||||
|
||||
|
||||
return new SheetDataWriter(_sharedStringSource);
|
||||
}
|
||||
|
||||
|
@ -364,20 +368,20 @@ public class SXSSFWorkbook implements Workbook {
|
|||
void deregisterSheetMapping(XSSFSheet xSheet)
|
||||
{
|
||||
SXSSFSheet sxSheet=getSXSSFSheet(xSheet);
|
||||
|
||||
|
||||
// ensure that the writer is closed in all cases to not have lingering writers
|
||||
try {
|
||||
sxSheet.getSheetDataWriter().close();
|
||||
} catch (IOException e) {
|
||||
// ignore exception here
|
||||
}
|
||||
|
||||
|
||||
_sxFromXHash.remove(sxSheet);
|
||||
|
||||
_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;
|
||||
|
@ -450,58 +462,58 @@ public class SXSSFWorkbook implements Workbook {
|
|||
pos++;
|
||||
if(pos==n)
|
||||
{
|
||||
if ("<sheetData".equals(s))
|
||||
{
|
||||
c = inReader.read();
|
||||
if (c == -1)
|
||||
{
|
||||
outWriter.write(s);
|
||||
break;
|
||||
}
|
||||
if (c == '>')
|
||||
{
|
||||
// Found <sheetData>
|
||||
outWriter.write(s);
|
||||
outWriter.write(c);
|
||||
s = "</sheetData>";
|
||||
n = s.length();
|
||||
pos = 0;
|
||||
needsStartTag = false;
|
||||
continue;
|
||||
}
|
||||
if (c == '/')
|
||||
{
|
||||
// Found <sheetData/
|
||||
c = inReader.read();
|
||||
if (c == -1)
|
||||
{
|
||||
outWriter.write(s);
|
||||
break;
|
||||
}
|
||||
if (c == '>')
|
||||
{
|
||||
// Found <sheetData/>
|
||||
break;
|
||||
}
|
||||
|
||||
outWriter.write(s);
|
||||
outWriter.write('/');
|
||||
outWriter.write(c);
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
outWriter.write(s);
|
||||
outWriter.write('/');
|
||||
outWriter.write(c);
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found </sheetData>
|
||||
break;
|
||||
}
|
||||
if ("<sheetData".equals(s))
|
||||
{
|
||||
c = inReader.read();
|
||||
if (c == -1)
|
||||
{
|
||||
outWriter.write(s);
|
||||
break;
|
||||
}
|
||||
if (c == '>')
|
||||
{
|
||||
// Found <sheetData>
|
||||
outWriter.write(s);
|
||||
outWriter.write(c);
|
||||
s = "</sheetData>";
|
||||
n = s.length();
|
||||
pos = 0;
|
||||
needsStartTag = false;
|
||||
continue;
|
||||
}
|
||||
if (c == '/')
|
||||
{
|
||||
// Found <sheetData/
|
||||
c = inReader.read();
|
||||
if (c == -1)
|
||||
{
|
||||
outWriter.write(s);
|
||||
break;
|
||||
}
|
||||
if (c == '>')
|
||||
{
|
||||
// Found <sheetData/>
|
||||
break;
|
||||
}
|
||||
|
||||
outWriter.write(s);
|
||||
outWriter.write('/');
|
||||
outWriter.write(c);
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
outWriter.write(s);
|
||||
outWriter.write('/');
|
||||
outWriter.write(c);
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found </sheetData>
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -523,11 +535,10 @@ public class SXSSFWorkbook implements Workbook {
|
|||
outWriter.flush();
|
||||
if (needsStartTag)
|
||||
{
|
||||
outWriter.write("<sheetData>\n");
|
||||
outWriter.flush();
|
||||
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".
|
||||
|
@ -732,7 +743,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
{
|
||||
return _wb.getNumberOfSheets();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator of the sheets in the workbook
|
||||
* in sheet order. Includes hidden and very hidden sheets.
|
||||
|
@ -743,7 +754,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public Iterator<Sheet> sheetIterator() {
|
||||
return new SheetIterator<>();
|
||||
}
|
||||
|
||||
|
||||
private final class SheetIterator<T extends Sheet> implements Iterator<T> {
|
||||
final private Iterator<XSSFSheet> it;
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -771,7 +782,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
"Use Sheet.removeSheetAt(int) instead.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Alias for {@link #sheetIterator()} to allow
|
||||
* foreach loops
|
||||
|
@ -816,11 +827,11 @@ public class SXSSFWorkbook implements Workbook {
|
|||
// Get the sheet to be removed
|
||||
XSSFSheet xSheet = _wb.getSheetAt(index);
|
||||
SXSSFSheet sxSheet = getSXSSFSheet(xSheet);
|
||||
|
||||
|
||||
// De-register it
|
||||
_wb.removeSheetAt(index);
|
||||
deregisterSheetMapping(xSheet);
|
||||
|
||||
|
||||
// Clean up temporary resources
|
||||
try {
|
||||
sxSheet.dispose();
|
||||
|
@ -839,7 +850,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
{
|
||||
return _wb.createFont();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a font that matches the one with the supplied attributes
|
||||
*
|
||||
|
@ -905,7 +916,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
}
|
||||
|
||||
/**
|
||||
* Closes the underlying {@link XSSFWorkbook} and {@link OPCPackage}
|
||||
* Closes the underlying {@link XSSFWorkbook} and {@link OPCPackage}
|
||||
* on which this Workbook is based, if any.
|
||||
*
|
||||
* <p>Once this has been called, no further
|
||||
|
@ -918,20 +929,21 @@ 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 "
|
||||
+ sheet.getSheetName() + ".", e);
|
||||
+ sheet.getSheetName() + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tell the base workbook to close, does nothing if
|
||||
|
||||
// Tell the base workbook to close, does nothing if
|
||||
// it's a newly created one
|
||||
_wb.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out this workbook to an OutputStream.
|
||||
*
|
||||
|
@ -962,14 +974,14 @@ public class SXSSFWorkbook implements Workbook {
|
|||
throw new IOException("Could not delete temporary file after processing: " + tmplFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void flushSheets() throws IOException {
|
||||
for (SXSSFSheet sheet : _xFromSxHash.values())
|
||||
{
|
||||
sheet.flushRows();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispose of temporary files backing this workbook on disk.
|
||||
* Calling this method will render the workbook unusable.
|
||||
|
@ -1053,7 +1065,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
_wb.removeName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the printarea for the sheet provided
|
||||
* <p>
|
||||
* i.e. Reference = $A$1:$B$2
|
||||
|
@ -1188,7 +1200,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
protected boolean isDate1904() {
|
||||
return _wb.isDate1904();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@NotImplemented("XSSFWorkbook#isHidden is not implemented")
|
||||
public boolean isHidden()
|
||||
|
@ -1214,7 +1226,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
{
|
||||
return _wb.isSheetVeryHidden(sheetIx);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SheetVisibility getSheetVisibility(int sheetIx) {
|
||||
return _wb.getSheetVisibility(sheetIx);
|
||||
|
@ -1230,13 +1242,13 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public void setSheetVisibility(int sheetIx, SheetVisibility visibility) {
|
||||
_wb.setSheetVisibility(sheetIx, visibility);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <i>Not implemented for SXSSFWorkbook</i>
|
||||
*
|
||||
* Adds the LinkTable records required to allow formulas referencing
|
||||
* the specified external workbook to be added to this one. Allows
|
||||
* formulas such as "[MyOtherWorkbook]Sheet3!$A$5" to be added to the
|
||||
* formulas such as "[MyOtherWorkbook]Sheet3!$A$5" to be added to the
|
||||
* file, for workbooks not already referenced.
|
||||
*
|
||||
* Note: this is not implemented and thus currently throws an Exception stating this.
|
||||
|
@ -1251,7 +1263,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public int linkExternalWorkbook(String name, Workbook workbook) {
|
||||
throw new RuntimeException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a new toolpack in this workbook.
|
||||
*
|
||||
|
@ -1290,7 +1302,7 @@ public class SXSSFWorkbook implements Workbook {
|
|||
|
||||
/**
|
||||
* Returns the spreadsheet version (EXCLE2007) of this workbook
|
||||
*
|
||||
*
|
||||
* @return EXCEL2007 SpreadsheetVersion enum
|
||||
* @since 3.14 beta 2
|
||||
*/
|
||||
|
@ -1303,6 +1315,6 @@ public class SXSSFWorkbook implements Workbook {
|
|||
public int addOlePackage(byte[] oleData, String label, String fileName, String command) throws IOException {
|
||||
return _wb.addOlePackage(oleData, label, fileName, command);
|
||||
}
|
||||
|
||||
|
||||
//end of interface implementation
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -72,6 +72,11 @@ public class SheetDataWriter implements Closeable {
|
|||
_fd = createTempFile();
|
||||
_out = createWriter(_fd);
|
||||
}
|
||||
|
||||
public SheetDataWriter(Writer writer) throws IOException {
|
||||
_fd = null;
|
||||
_out = writer;
|
||||
}
|
||||
|
||||
public SheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException {
|
||||
this();
|
||||
|
|
|
@ -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