Index: trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java =================================================================== --- trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java (revision 1783971) +++ trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java (working copy) @@ -70,14 +70,23 @@ private int outlineLevelRow = 0; private int lastFlushedRowNumber = -1; private boolean allFlushed = false; + private SXSSFRow firstRowsArray[] = null; public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException { _workbook = workbook; _sh = xSheet; _writer = workbook.createSheetDataWriter(); setRandomAccessWindowSize(_workbook.getRandomAccessWindowSize()); + setRandomAccessAtTop(_workbook.getRandomAccessAtTop()); _autoSizeColumnTracker = new AutoSizeColumnTracker(this); } + + private void setRandomAccessAtTop(int randomAccessAtTop) { + if (randomAccessAtTop > 0) { + firstRowsArray = new SXSSFRow[randomAccessAtTop]; + for (int i = 0; i < firstRowsArray.length; i++) firstRowsArray[i] = null; + } + } /** * for testing purposes only @@ -185,7 +194,10 @@ @Override public SXSSFRow getRow(int rownum) { - return _rows.get(rownum); + if (firstRowsArray != null && rownum < firstRowsArray.length && firstRowsArray[rownum] != null) + return firstRowsArray[rownum]; + else + return _rows.get(rownum); } /** @@ -1901,6 +1913,7 @@ if (firstRowNum!=null) { int rowIndex = firstRowNum.intValue(); SXSSFRow row = _rows.get(firstRowNum); + if (firstRowsArray != null && rowIndex < firstRowsArray.length) firstRowsArray[rowIndex] = row; // Update the best fit column widths for auto-sizing just before the rows are flushed _autoSizeColumnTracker.updateColumnWidths(row); _writer.writeRow(rowIndex, row); Index: trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java =================================================================== --- trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java (revision 1783971) +++ trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java (working copy) @@ -103,7 +103,8 @@ private final Map _xFromSxHash = new HashMap(); private int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE; - + private int _randomAccessAtTop = 0; + /** * whether temp files should be compressed. */ @@ -272,6 +273,34 @@ } /** + * Construct an empty workbook and specify the window for row access. + * First rows will be held in memory for later reference, for example to construct pivot table. + *

+ * When a new node is created via {@link SXSSFSheet#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 {@link SXSSFSheet#getRow} anymore. + * First rows are kept in memory according to rowAccessFixedTop parameter. + *

+ *

+ * 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 the number of rows that are kept in memory until flushed out, see above. + * @param rowAccessFixedTop the number of first rows that are kept in memory permanently. + */ + public SXSSFWorkbook(int rowAccessWindowSize, int rowAccessFixedTop){ + this(null /*workbook*/, rowAccessWindowSize); + setRandomAccessAtTop(rowAccessFixedTop); + } + + /** * See the constructors for a more detailed description of the sliding window of rows. * * @return The number of rows that are kept in memory at once before flushing them out. @@ -507,6 +536,14 @@ return _wb; } + public int getRandomAccessAtTop() { + return _randomAccessAtTop; + } + + private void setRandomAccessAtTop(int _randomAccessAtTop) { + this._randomAccessAtTop = _randomAccessAtTop; + } + //start of interface implementation /** @@ -1363,6 +1400,6 @@ public int addOlePackage(byte[] oleData, String label, String fileName, String command) throws IOException { return _wb.addOlePackage(oleData, label, fileName, command); } - + //end of interface implementation }