From 9f0cd544cf702c31cbcbc0ea944a22b38784f213 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Mon, 24 May 2010 05:31:48 +0000 Subject: [PATCH] Improved performance of XSSFSheet.write, avoid unnecessary re-ordering of CTRow beans if they are already ordered git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@947542 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../apache/poi/xssf/usermodel/XSSFSheet.java | 63 +++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index bb66430073..102f6cb529 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + Improved performance of XSSFWorkbook.write 48846 - Avoid NPE when finding cell comments 49325 - Ensure that CTPhoneticPr is included in poi-ooxml jar 49191 - Fixed tests failing in non-english locales diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 14fcd81f3b..4600553690 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -113,7 +113,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { protected CTSheet sheet; protected CTWorksheet worksheet; - private TreeMap rows; + private TreeMap _rows; private List hyperlinks; private ColumnHelper columnHelper; private CommentsTable sheetComments; @@ -194,12 +194,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } private void initRows(CTWorksheet worksheet) { - rows = new TreeMap(); + _rows = new TreeMap(); sharedFormulas = new HashMap(); arrayFormulas = new ArrayList(); for (CTRow row : worksheet.getSheetData().getRowArray()) { XSSFRow r = new XSSFRow(row, this); - rows.put(r.getRowNum(), r); + _rows.put(r.getRowNum(), r); } } @@ -503,7 +503,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ public XSSFRow createRow(int rownum) { CTRow ctRow; - XSSFRow prev = rows.get(rownum); + XSSFRow prev = _rows.get(rownum); if(prev != null){ ctRow = prev.getCTRow(); ctRow.set(CTRow.Factory.newInstance()); @@ -512,7 +512,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } XSSFRow r = new XSSFRow(ctRow, this); r.setRowNum(rownum); - rows.put(rownum, r); + _rows.put(rownum, r); return r; } @@ -707,7 +707,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * @return the number of the first logical row on the sheet, zero based */ public int getFirstRowNum() { - return rows.size() == 0 ? 0 : rows.firstKey(); + return _rows.size() == 0 ? 0 : _rows.firstKey(); } /** @@ -820,7 +820,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } public int getLastRowNum() { - return rows.size() == 0 ? 0 : rows.lastKey(); + return _rows.size() == 0 ? 0 : _rows.lastKey(); } public short getLeftCol() { @@ -948,7 +948,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * @return the number of phsyically defined rows */ public int getPhysicalNumberOfRows() { - return rows.size(); + return _rows.size(); } /** @@ -977,7 +977,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * @return XSSFRow representing the rownumber or null if its not defined on the sheet */ public XSSFRow getRow(int rownum) { - return rows.get(rownum); + return _rows.get(rownum); } /** @@ -1158,7 +1158,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { private short getMaxOutlineLevelRows(){ short outlineLevel=0; - for(XSSFRow xrow : rows.values()){ + for(XSSFRow xrow : _rows.values()){ outlineLevel=xrow.getCTRow().getOutlineLevel()>outlineLevel? xrow.getCTRow().getOutlineLevel(): outlineLevel; } return outlineLevel; @@ -1358,7 +1358,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { xcell.notifyArrayFormulaChanging(msg); } } - rows.remove(row.getRowNum()); + _rows.remove(row.getRowNum()); } /** @@ -1380,7 +1380,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * Call getRowNum() on each row if you care which one it is. */ public Iterator rowIterator() { - return (Iterator)(Iterator)rows.values().iterator(); + return (Iterator)(Iterator) _rows.values().iterator(); } /** @@ -2157,12 +2157,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { rowShifter.updateFormulas(shifter); rowShifter.shiftMerged(startRow, endRow, n); - //rebuild the rows map + //rebuild the _rows map TreeMap map = new TreeMap(); - for(XSSFRow r : rows.values()) { + for(XSSFRow r : _rows.values()) { map.put(r.getRowNum(), r); } - rows = map; + _rows = map; } /** @@ -2441,13 +2441,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { worksheet.getHyperlinks().setHyperlinkArray(ctHls); } - CTSheetData sheetData = worksheet.getSheetData(); - ArrayList rArray = new ArrayList(rows.size()); - for(XSSFRow row : rows.values()){ + for(XSSFRow row : _rows.values()){ row.onDocumentWrite(); - rArray.add(row.getCTRow()); } - sheetData.setRowArray(rArray.toArray(new CTRow[rArray.size()])); + ensureRowOrdering(); XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); @@ -2458,6 +2455,32 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { worksheet.save(out, xmlOptions); } + /** + * ensure that the array of CTRow written to CTSheetData is ordered by row index + */ + private void ensureRowOrdering(){ + CTSheetData sheetData = worksheet.getSheetData(); + // check if row indexes in CTSheetData match the internal model: + // rows in the internal model (_rows) are always ordered while + // CTRow beans held by CTSheetData may be not, for example, user can + // insert rows in random order, shift rows after insertion, etc. + Integer [] curRows = new Integer[sheetData.sizeOfRowArray()]; + int i = 0; + for(CTRow ctrow : sheetData.getRowArray()){ + curRows[i++] = (int)(ctrow.getR() - 1); + } + Integer [] ordRows = _rows.keySet().toArray(new Integer[_rows.size()]); + if(!Arrays.equals(curRows, ordRows)){ + // The order of rows in CTSheetData and internal model does not match + CTRow[] orderedCTRows = new CTRow[_rows.size()]; + i = 0; + for(XSSFRow row : _rows.values()){ + orderedCTRows[i++] = row.getCTRow(); + } + sheetData.setRowArray(orderedCTRows); + } + } + /** * @return true when Autofilters are locked and the sheet is protected. */ -- 2.39.5