Patch 51634 - support SXSSF streaming from templates
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156544 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bde41cbbe6
commit
6663b6ea9f
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.8-beta4" date="2011-??-??">
|
<release version="3.8-beta4" date="2011-??-??">
|
||||||
|
<action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action>
|
||||||
<action dev="poi-developers" type="add">initial support for XSLF usermodel API</action>
|
<action dev="poi-developers" type="add">initial support for XSLF usermodel API</action>
|
||||||
<action dev="poi-developers" type="fix">51187 - fixed OPCPackage to correctly handle self references</action>
|
<action dev="poi-developers" type="fix">51187 - fixed OPCPackage to correctly handle self references</action>
|
||||||
<action dev="poi-developers" type="fix">51635 - Improved performance of XSSFSheet#write</action>
|
<action dev="poi-developers" type="fix">51635 - Improved performance of XSSFSheet#write</action>
|
||||||
|
@ -44,11 +44,12 @@ public class SXSSFSheet implements Sheet, Cloneable
|
|||||||
SheetDataWriter _writer;
|
SheetDataWriter _writer;
|
||||||
int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
|
int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
|
||||||
|
|
||||||
public SXSSFSheet(SXSSFWorkbook workbook,XSSFSheet xSheet) throws IOException
|
public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException
|
||||||
{
|
{
|
||||||
_workbook=workbook;
|
_workbook=workbook;
|
||||||
_sh=xSheet;
|
_sh=xSheet;
|
||||||
_writer=new SheetDataWriter();
|
_writer=new SheetDataWriter();
|
||||||
|
setRandomAccessWindowSize(_workbook.getRandomAccessWindowSize());
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Gets "<sheetData>" document fragment*/
|
/* Gets "<sheetData>" document fragment*/
|
||||||
@ -1286,7 +1287,6 @@ public class SXSSFSheet implements Sheet, Cloneable
|
|||||||
_fd = File.createTempFile("poi-sxxsf-sheet", ".xml");
|
_fd = File.createTempFile("poi-sxxsf-sheet", ".xml");
|
||||||
_fd.deleteOnExit();
|
_fd.deleteOnExit();
|
||||||
_out = new BufferedWriter(new FileWriter(_fd));
|
_out = new BufferedWriter(new FileWriter(_fd));
|
||||||
_out.write("<sheetData>\n");
|
|
||||||
}
|
}
|
||||||
public int getNumberOfFlushedRows()
|
public int getNumberOfFlushedRows()
|
||||||
{
|
{
|
||||||
@ -1306,7 +1306,6 @@ public class SXSSFSheet implements Sheet, Cloneable
|
|||||||
}
|
}
|
||||||
public InputStream getWorksheetXMLInputStream() throws IOException
|
public InputStream getWorksheetXMLInputStream() throws IOException
|
||||||
{
|
{
|
||||||
_out.write("</sheetData>");
|
|
||||||
_out.flush();
|
_out.flush();
|
||||||
_out.close();
|
_out.close();
|
||||||
return new FileInputStream(_fd);
|
return new FileInputStream(_fd);
|
||||||
|
@ -59,25 +59,67 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
*/
|
*/
|
||||||
public static final int DEFAULT_WINDOW_SIZE = 100;
|
public static final int DEFAULT_WINDOW_SIZE = 100;
|
||||||
|
|
||||||
XSSFWorkbook _wb=new XSSFWorkbook();
|
XSSFWorkbook _wb;
|
||||||
|
|
||||||
HashMap<SXSSFSheet,XSSFSheet> _sxFromXHash=new HashMap<SXSSFSheet,XSSFSheet>();
|
HashMap<SXSSFSheet,XSSFSheet> _sxFromXHash=new HashMap<SXSSFSheet,XSSFSheet>();
|
||||||
HashMap<XSSFSheet,SXSSFSheet> _xFromSxHash=new HashMap<XSSFSheet,SXSSFSheet>();
|
HashMap<XSSFSheet,SXSSFSheet> _xFromSxHash=new HashMap<XSSFSheet,SXSSFSheet>();
|
||||||
|
|
||||||
int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE;
|
private int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new workbook
|
* Construct a new workbook
|
||||||
*/
|
*/
|
||||||
public SXSSFWorkbook(){
|
public SXSSFWorkbook(){
|
||||||
|
this(null /*workbook*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SXSSFWorkbook(XSSFWorkbook workbook){
|
||||||
|
this(workbook, DEFAULT_WINDOW_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an workbook from an existing workbook.
|
||||||
|
* <p>
|
||||||
|
* When a new node is created via createRow() and the total number
|
||||||
|
* of unflushed records would exceed the specified value, then the
|
||||||
|
* row with the lowest index value is flushed and cannot be accessed
|
||||||
|
* via getRow() anymore.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* A value of -1 indicates unlimited access. In this case all
|
||||||
|
* records that have not been flushed by a call to flush() are available
|
||||||
|
* for random access.
|
||||||
|
* <p>
|
||||||
|
* <p></p>
|
||||||
|
* A value of 0 is not allowed because it would flush any newly created row
|
||||||
|
* without having a chance to specify any cells.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param rowAccessWindowSize
|
||||||
|
*/
|
||||||
|
public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize){
|
||||||
|
setRandomAccessWindowSize(rowAccessWindowSize);
|
||||||
|
if (workbook == null)
|
||||||
|
{
|
||||||
|
_wb=new XSSFWorkbook();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_wb=workbook;
|
||||||
|
for ( int i = 0; i < _wb.getNumberOfSheets(); i++ )
|
||||||
|
{
|
||||||
|
XSSFSheet sheet = _wb.getSheetAt( i );
|
||||||
|
createAndRegisterSXSSFSheet( sheet );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty workbook and specify the window for row access.
|
* Construct an empty workbook and specify the window for row access.
|
||||||
* <p>
|
* <p>
|
||||||
* When a new node is created via createRow() and the total number
|
* When a new node is created via createRow() and the total number
|
||||||
* of unflushed records would exeed the specified value, then the
|
* of unflushed records would exceed the specified value, then the
|
||||||
* row with the lowest index value is flushed and cannot be accessed
|
* row with the lowest index value is flushed and cannot be accessed
|
||||||
* via getRow() anymore.
|
* via getRow() anymore.
|
||||||
* </p>
|
* </p>
|
||||||
@ -94,6 +136,15 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
* @param rowAccessWindowSize
|
* @param rowAccessWindowSize
|
||||||
*/
|
*/
|
||||||
public SXSSFWorkbook(int rowAccessWindowSize){
|
public SXSSFWorkbook(int rowAccessWindowSize){
|
||||||
|
this(null /*workbook*/, rowAccessWindowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRandomAccessWindowSize()
|
||||||
|
{
|
||||||
|
return _randomAccessWindowSize;
|
||||||
|
}
|
||||||
|
private void setRandomAccessWindowSize(int rowAccessWindowSize)
|
||||||
|
{
|
||||||
if(rowAccessWindowSize == 0 || rowAccessWindowSize < -1) {
|
if(rowAccessWindowSize == 0 || rowAccessWindowSize < -1) {
|
||||||
throw new IllegalArgumentException("rowAccessWindowSize must be greater than 0 or -1");
|
throw new IllegalArgumentException("rowAccessWindowSize must be greater than 0 or -1");
|
||||||
}
|
}
|
||||||
@ -168,20 +219,75 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
out.write(chunk,0,count);
|
out.write(chunk,0,count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out,InputStream worksheetData) throws IOException {
|
private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out, InputStream worksheetData) throws IOException {
|
||||||
InputStreamReader inReader=new InputStreamReader(in,"UTF-8"); //TODO: Is it always UTF-8 or do we need to read the xml encoding declaration in the file? If not, we should perhaps use a SAX reader instead.
|
InputStreamReader inReader=new InputStreamReader(in,"UTF-8"); //TODO: Is it always UTF-8 or do we need to read the xml encoding declaration in the file? If not, we should perhaps use a SAX reader instead.
|
||||||
OutputStreamWriter outWriter=new OutputStreamWriter(out,"UTF-8");
|
OutputStreamWriter outWriter=new OutputStreamWriter(out,"UTF-8");
|
||||||
|
boolean needsStartTag = true;
|
||||||
int c;
|
int c;
|
||||||
int pos=0;
|
int pos=0;
|
||||||
String s="<sheetData/>";
|
String s="<sheetData";
|
||||||
int n=s.length();
|
int n=s.length();
|
||||||
//Copy from "in" to "out" up to the string "<sheetData/>" (excluding).
|
//Copy from "in" to "out" up to the string "<sheetData/>" or "</sheetData>" (excluding).
|
||||||
while(((c=inReader.read())!=-1))
|
while(((c=inReader.read())!=-1))
|
||||||
{
|
{
|
||||||
if(c==s.charAt(pos))
|
if(c==s.charAt(pos))
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
if(pos==n) break;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -198,8 +304,15 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
outWriter.flush();
|
outWriter.flush();
|
||||||
|
if (needsStartTag)
|
||||||
|
{
|
||||||
|
outWriter.write("<sheetData>\n");
|
||||||
|
outWriter.flush();
|
||||||
|
}
|
||||||
//Copy the worksheet data to "out".
|
//Copy the worksheet data to "out".
|
||||||
copyStream(worksheetData,out);
|
copyStream(worksheetData,out);
|
||||||
|
outWriter.write("</sheetData>");
|
||||||
|
outWriter.flush();
|
||||||
//Copy the rest of "in" to "out".
|
//Copy the rest of "in" to "out".
|
||||||
while(((c=inReader.read())!=-1))
|
while(((c=inReader.read())!=-1))
|
||||||
outWriter.write(c);
|
outWriter.write(c);
|
||||||
@ -348,7 +461,6 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
{
|
{
|
||||||
throw new RuntimeException(ioe);
|
throw new RuntimeException(ioe);
|
||||||
}
|
}
|
||||||
sxSheet.setRandomAccessWindowSize(_randomAccessWindowSize);
|
|
||||||
registerSheetMapping(sxSheet,xSheet);
|
registerSheetMapping(sxSheet,xSheet);
|
||||||
return sxSheet;
|
return sxSheet;
|
||||||
}
|
}
|
||||||
@ -532,6 +644,11 @@ public class SXSSFWorkbook implements Workbook
|
|||||||
*/
|
*/
|
||||||
public void write(OutputStream stream) throws IOException
|
public void write(OutputStream stream) throws IOException
|
||||||
{
|
{
|
||||||
|
for (SXSSFSheet sheet : _xFromSxHash.values())
|
||||||
|
{
|
||||||
|
sheet.flushRows();
|
||||||
|
}
|
||||||
|
|
||||||
//Save the template
|
//Save the template
|
||||||
File tmplFile = File.createTempFile("poi-sxxsf-template", ".xlsx");
|
File tmplFile = File.createTempFile("poi-sxxsf-template", ".xlsx");
|
||||||
tmplFile.deleteOnExit();
|
tmplFile.deleteOnExit();
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
package org.apache.poi.xssf;
|
package org.apache.poi.xssf;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
||||||
import org.apache.poi.ss.ITestDataProvider;
|
import org.apache.poi.ss.ITestDataProvider;
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
@ -42,7 +41,8 @@ public final class SXSSFITestDataProvider implements ITestDataProvider {
|
|||||||
// enforce singleton
|
// enforce singleton
|
||||||
}
|
}
|
||||||
public Workbook openSampleWorkbook(String sampleFileName) {
|
public Workbook openSampleWorkbook(String sampleFileName) {
|
||||||
throw new IllegalArgumentException("SXSSF cannot read files");
|
XSSFWorkbook xssfWorkbook = XSSFITestDataProvider.instance.openSampleWorkbook(sampleFileName);
|
||||||
|
return new SXSSFWorkbook(xssfWorkbook);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Workbook writeOutAndReadBack(Workbook wb) {
|
public Workbook writeOutAndReadBack(Workbook wb) {
|
||||||
|
@ -20,7 +20,12 @@
|
|||||||
package org.apache.poi.xssf.usermodel.streaming;
|
package org.apache.poi.xssf.usermodel.streaming;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
|
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.xssf.SXSSFITestDataProvider;
|
import org.apache.poi.xssf.SXSSFITestDataProvider;
|
||||||
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
public final class TestSXSSFWorkbook extends BaseTestWorkbook {
|
public final class TestSXSSFWorkbook extends BaseTestWorkbook {
|
||||||
|
|
||||||
@ -55,5 +60,81 @@ public final class TestSXSSFWorkbook extends BaseTestWorkbook {
|
|||||||
"Only XSSFCells can be evaluated.", e.getMessage());
|
"Only XSSFCells can be evaluated.", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testExistingWorkbook() {
|
||||||
|
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
|
||||||
|
xssfWorkbook.createSheet("S1");
|
||||||
|
SXSSFWorkbook wb = new SXSSFWorkbook(xssfWorkbook);
|
||||||
|
xssfWorkbook = (XSSFWorkbook) SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
|
||||||
|
wb = new SXSSFWorkbook(xssfWorkbook);
|
||||||
|
assertEquals(1, wb.getNumberOfSheets());
|
||||||
|
Sheet sheet = wb.getSheetAt(0);
|
||||||
|
assertNotNull(sheet);
|
||||||
|
assertEquals("S1", sheet.getSheetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddToExistingWorkbook() {
|
||||||
|
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
|
||||||
|
xssfWorkbook.createSheet("S1");
|
||||||
|
Sheet sheet = xssfWorkbook.createSheet("S2");
|
||||||
|
Row row = sheet.createRow(1);
|
||||||
|
Cell cell = row.createCell(1);
|
||||||
|
cell.setCellValue("value 2_1_1");
|
||||||
|
SXSSFWorkbook wb = new SXSSFWorkbook(xssfWorkbook);
|
||||||
|
xssfWorkbook = (XSSFWorkbook) SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
|
||||||
|
wb = new SXSSFWorkbook(xssfWorkbook);
|
||||||
|
|
||||||
|
// Add a row to the existing empty sheet
|
||||||
|
Sheet sheet1 = wb.getSheetAt(0);
|
||||||
|
Row row1_1 = sheet1.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
|
||||||
|
Sheet sheet2 = wb.getSheetAt(1);
|
||||||
|
Row row2_2 = sheet2.createRow(2);
|
||||||
|
Cell cell2_2_1 = row2_2.createCell(1);
|
||||||
|
cell2_2_1.setCellValue("value 2_2_1");
|
||||||
|
|
||||||
|
// Add a sheet with one row
|
||||||
|
Sheet sheet3 = wb.createSheet("S3");
|
||||||
|
Row row3_1 = sheet3.createRow(1);
|
||||||
|
Cell cell3_1_1 = row3_1.createCell(1);
|
||||||
|
cell3_1_1.setCellValue("value 3_1_1");
|
||||||
|
|
||||||
|
xssfWorkbook = (XSSFWorkbook) SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
|
||||||
|
assertEquals(3, xssfWorkbook.getNumberOfSheets());
|
||||||
|
// Verify sheet 1
|
||||||
|
sheet1 = xssfWorkbook.getSheetAt(0);
|
||||||
|
assertEquals("S1", sheet1.getSheetName());
|
||||||
|
assertEquals(1, sheet1.getPhysicalNumberOfRows());
|
||||||
|
row1_1 = sheet1.getRow(1);
|
||||||
|
assertNotNull(row1_1);
|
||||||
|
cell1_1_1 = row1_1.getCell(1);
|
||||||
|
assertNotNull(cell1_1_1);
|
||||||
|
assertEquals("value 1_1_1", cell1_1_1.getStringCellValue());
|
||||||
|
// Verify sheet 2
|
||||||
|
sheet2 = xssfWorkbook.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());
|
||||||
|
row2_2 = sheet2.getRow(2);
|
||||||
|
assertNotNull(row2_2);
|
||||||
|
cell2_2_1 = row2_2.getCell(1);
|
||||||
|
assertNotNull(cell2_2_1);
|
||||||
|
assertEquals("value 2_2_1", cell2_2_1.getStringCellValue());
|
||||||
|
// Verify sheet 3
|
||||||
|
sheet3 = xssfWorkbook.getSheetAt(2);
|
||||||
|
assertEquals("S3", sheet3.getSheetName());
|
||||||
|
assertEquals(1, sheet3.getPhysicalNumberOfRows());
|
||||||
|
row3_1 = sheet3.getRow(1);
|
||||||
|
assertNotNull(row3_1);
|
||||||
|
cell3_1_1 = row3_1.getCell(1);
|
||||||
|
assertNotNull(cell3_1_1);
|
||||||
|
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user