From 453e72046dfcee0a9dbfd3b6202dbc0dd022f6b3 Mon Sep 17 00:00:00 2001
From: Yegor Kozlov
Date: Thu, 11 Aug 2011 08:54:11 +0000
Subject: [PATCH] Patch 51634 - support SXSSF streaming from templates
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156544 13f79535-47bb-0310-9956-ffa450edef68
---
src/documentation/content/xdocs/status.xml | 1 +
.../apache/poi/xssf/streaming/SXSSFSheet.java | 9 +-
.../poi/xssf/streaming/SXSSFWorkbook.java | 133 ++++++++++++++++--
.../poi/xssf/SXSSFITestDataProvider.java | 4 +-
.../streaming/TestSXSSFWorkbook.java | 83 ++++++++++-
5 files changed, 214 insertions(+), 16 deletions(-)
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index bea5040855..b1790bf74c 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -34,6 +34,7 @@
+ 51634 - support SXSSF streaming from templates
initial support for XSLF usermodel API
51187 - fixed OPCPackage to correctly handle self references
51635 - Improved performance of XSSFSheet#write
diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
index d3b62a5b65..8c1b998641 100644
--- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
+++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
@@ -44,11 +44,12 @@ public class SXSSFSheet implements Sheet, Cloneable
SheetDataWriter _writer;
int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
- public SXSSFSheet(SXSSFWorkbook workbook,XSSFSheet xSheet) throws IOException
+ public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException
{
- _workbook=workbook;
- _sh=xSheet;
+ _workbook=workbook;
+ _sh=xSheet;
_writer=new SheetDataWriter();
+ setRandomAccessWindowSize(_workbook.getRandomAccessWindowSize());
}
/* Gets "" document fragment*/
@@ -1286,7 +1287,6 @@ public class SXSSFSheet implements Sheet, Cloneable
_fd = File.createTempFile("poi-sxxsf-sheet", ".xml");
_fd.deleteOnExit();
_out = new BufferedWriter(new FileWriter(_fd));
- _out.write("\n");
}
public int getNumberOfFlushedRows()
{
@@ -1306,7 +1306,6 @@ public class SXSSFSheet implements Sheet, Cloneable
}
public InputStream getWorksheetXMLInputStream() throws IOException
{
- _out.write("");
_out.flush();
_out.close();
return new FileInputStream(_fd);
diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
index 6ba4137b54..adcc995ec6 100644
--- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
+++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
@@ -59,25 +59,67 @@ public class SXSSFWorkbook implements Workbook
*/
public static final int DEFAULT_WINDOW_SIZE = 100;
- XSSFWorkbook _wb=new XSSFWorkbook();
+ XSSFWorkbook _wb;
HashMap _sxFromXHash=new HashMap();
HashMap _xFromSxHash=new HashMap();
- int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE;
+ private int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE;
/**
* Construct a new workbook
*/
public SXSSFWorkbook(){
+ this(null /*workbook*/);
+ }
+
+ public SXSSFWorkbook(XSSFWorkbook workbook){
+ this(workbook, DEFAULT_WINDOW_SIZE);
+ }
+
+ /**
+ * Constructs an workbook from an existing workbook.
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * A value of 0 is not allowed because it would flush any newly created row
+ * without having a chance to specify any cells.
+ *
+ *
+ * @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.
*
* 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
* via getRow() anymore.
*
@@ -94,6 +136,15 @@ public class SXSSFWorkbook implements Workbook
* @param rowAccessWindowSize
*/
public SXSSFWorkbook(int rowAccessWindowSize){
+ this(null /*workbook*/, rowAccessWindowSize);
+ }
+
+ public int getRandomAccessWindowSize()
+ {
+ return _randomAccessWindowSize;
+ }
+ private void setRandomAccessWindowSize(int rowAccessWindowSize)
+ {
if(rowAccessWindowSize == 0 || rowAccessWindowSize < -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);
}
}
- 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.
OutputStreamWriter outWriter=new OutputStreamWriter(out,"UTF-8");
+ boolean needsStartTag = true;
int c;
int pos=0;
- String s="";
+ String s="" (excluding).
+//Copy from "in" to "out" up to the string "" or "" (excluding).
while(((c=inReader.read())!=-1))
{
if(c==s.charAt(pos))
{
pos++;
- if(pos==n) break;
+ if(pos==n)
+ {
+ if ("')
+ {
+ // Found
+ outWriter.write(s);
+ outWriter.write(c);
+ s = "";
+ n = s.length();
+ pos = 0;
+ needsStartTag = false;
+ continue;
+ }
+ if (c == '/')
+ {
+ // Found ')
+ {
+ // Found
+ 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
+ break;
+ }
+ }
}
else
{
@@ -198,8 +304,15 @@ public class SXSSFWorkbook implements Workbook
}
}
outWriter.flush();
+ if (needsStartTag)
+ {
+ outWriter.write("\n");
+ outWriter.flush();
+ }
//Copy the worksheet data to "out".
copyStream(worksheetData,out);
+ outWriter.write("");
+ outWriter.flush();
//Copy the rest of "in" to "out".
while(((c=inReader.read())!=-1))
outWriter.write(c);
@@ -348,7 +461,6 @@ public class SXSSFWorkbook implements Workbook
{
throw new RuntimeException(ioe);
}
- sxSheet.setRandomAccessWindowSize(_randomAccessWindowSize);
registerSheetMapping(sxSheet,xSheet);
return sxSheet;
}
@@ -532,6 +644,11 @@ public class SXSSFWorkbook implements Workbook
*/
public void write(OutputStream stream) throws IOException
{
+ for (SXSSFSheet sheet : _xFromSxHash.values())
+ {
+ sheet.flushRows();
+ }
+
//Save the template
File tmplFile = File.createTempFile("poi-sxxsf-template", ".xlsx");
tmplFile.deleteOnExit();
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/SXSSFITestDataProvider.java b/src/ooxml/testcases/org/apache/poi/xssf/SXSSFITestDataProvider.java
index 50e1fdb686..d5d7026b7a 100755
--- a/src/ooxml/testcases/org/apache/poi/xssf/SXSSFITestDataProvider.java
+++ b/src/ooxml/testcases/org/apache/poi/xssf/SXSSFITestDataProvider.java
@@ -20,7 +20,6 @@
package org.apache.poi.xssf;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Workbook;
@@ -42,7 +41,8 @@ public final class SXSSFITestDataProvider implements ITestDataProvider {
// enforce singleton
}
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) {
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/streaming/TestSXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/streaming/TestSXSSFWorkbook.java
index a1ef9c1bdf..c8b5b61787 100755
--- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/streaming/TestSXSSFWorkbook.java
+++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/streaming/TestSXSSFWorkbook.java
@@ -20,7 +20,12 @@
package org.apache.poi.xssf.usermodel.streaming;
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.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public final class TestSXSSFWorkbook extends BaseTestWorkbook {
@@ -55,5 +60,81 @@ public final class TestSXSSFWorkbook extends BaseTestWorkbook {
"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());
+ }
}
--
2.39.5