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
This commit is contained in:
Yegor Kozlov 2010-05-24 05:31:48 +00:00
parent e79cc21802
commit 9f0cd544cf
2 changed files with 44 additions and 20 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.7-SNAPSHOT" date="2010-??-??"> <release version="3.7-SNAPSHOT" date="2010-??-??">
<action dev="POI-DEVELOPERS" type="add">Improved performance of XSSFWorkbook.write </action>
<action dev="POI-DEVELOPERS" type="fix">48846 - Avoid NPE when finding cell comments</action> <action dev="POI-DEVELOPERS" type="fix">48846 - Avoid NPE when finding cell comments</action>
<action dev="POI-DEVELOPERS" type="fix">49325 - Ensure that CTPhoneticPr is included in poi-ooxml jar</action> <action dev="POI-DEVELOPERS" type="fix">49325 - Ensure that CTPhoneticPr is included in poi-ooxml jar</action>
<action dev="POI-DEVELOPERS" type="fix">49191 - Fixed tests failing in non-english locales</action> <action dev="POI-DEVELOPERS" type="fix">49191 - Fixed tests failing in non-english locales</action>

View File

@ -113,7 +113,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
protected CTSheet sheet; protected CTSheet sheet;
protected CTWorksheet worksheet; protected CTWorksheet worksheet;
private TreeMap<Integer, XSSFRow> rows; private TreeMap<Integer, XSSFRow> _rows;
private List<XSSFHyperlink> hyperlinks; private List<XSSFHyperlink> hyperlinks;
private ColumnHelper columnHelper; private ColumnHelper columnHelper;
private CommentsTable sheetComments; private CommentsTable sheetComments;
@ -194,12 +194,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
} }
private void initRows(CTWorksheet worksheet) { private void initRows(CTWorksheet worksheet) {
rows = new TreeMap<Integer, XSSFRow>(); _rows = new TreeMap<Integer, XSSFRow>();
sharedFormulas = new HashMap<Integer, XSSFCell>(); sharedFormulas = new HashMap<Integer, XSSFCell>();
arrayFormulas = new ArrayList<CellRangeAddress>(); arrayFormulas = new ArrayList<CellRangeAddress>();
for (CTRow row : worksheet.getSheetData().getRowArray()) { for (CTRow row : worksheet.getSheetData().getRowArray()) {
XSSFRow r = new XSSFRow(row, this); 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) { public XSSFRow createRow(int rownum) {
CTRow ctRow; CTRow ctRow;
XSSFRow prev = rows.get(rownum); XSSFRow prev = _rows.get(rownum);
if(prev != null){ if(prev != null){
ctRow = prev.getCTRow(); ctRow = prev.getCTRow();
ctRow.set(CTRow.Factory.newInstance()); ctRow.set(CTRow.Factory.newInstance());
@ -512,7 +512,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
} }
XSSFRow r = new XSSFRow(ctRow, this); XSSFRow r = new XSSFRow(ctRow, this);
r.setRowNum(rownum); r.setRowNum(rownum);
rows.put(rownum, r); _rows.put(rownum, r);
return 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 * @return the number of the first logical row on the sheet, zero based
*/ */
public int getFirstRowNum() { 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() { public int getLastRowNum() {
return rows.size() == 0 ? 0 : rows.lastKey(); return _rows.size() == 0 ? 0 : _rows.lastKey();
} }
public short getLeftCol() { public short getLeftCol() {
@ -948,7 +948,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
* @return the number of phsyically defined rows * @return the number of phsyically defined rows
*/ */
public int getPhysicalNumberOfRows() { public int getPhysicalNumberOfRows() {
return rows.size(); return _rows.size();
} }
/** /**
@ -977,7 +977,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
* @return <code>XSSFRow</code> representing the rownumber or <code>null</code> if its not defined on the sheet * @return <code>XSSFRow</code> representing the rownumber or <code>null</code> if its not defined on the sheet
*/ */
public XSSFRow getRow(int rownum) { 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(){ private short getMaxOutlineLevelRows(){
short outlineLevel=0; short outlineLevel=0;
for(XSSFRow xrow : rows.values()){ for(XSSFRow xrow : _rows.values()){
outlineLevel=xrow.getCTRow().getOutlineLevel()>outlineLevel? xrow.getCTRow().getOutlineLevel(): outlineLevel; outlineLevel=xrow.getCTRow().getOutlineLevel()>outlineLevel? xrow.getCTRow().getOutlineLevel(): outlineLevel;
} }
return outlineLevel; return outlineLevel;
@ -1358,7 +1358,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
xcell.notifyArrayFormulaChanging(msg); 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. * Call getRowNum() on each row if you care which one it is.
*/ */
public Iterator<Row> rowIterator() { public Iterator<Row> rowIterator() {
return (Iterator<Row>)(Iterator<? extends Row>)rows.values().iterator(); return (Iterator<Row>)(Iterator<? extends Row>) _rows.values().iterator();
} }
/** /**
@ -2157,12 +2157,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
rowShifter.updateFormulas(shifter); rowShifter.updateFormulas(shifter);
rowShifter.shiftMerged(startRow, endRow, n); rowShifter.shiftMerged(startRow, endRow, n);
//rebuild the rows map //rebuild the _rows map
TreeMap<Integer, XSSFRow> map = new TreeMap<Integer, XSSFRow>(); TreeMap<Integer, XSSFRow> map = new TreeMap<Integer, XSSFRow>();
for(XSSFRow r : rows.values()) { for(XSSFRow r : _rows.values()) {
map.put(r.getRowNum(), r); map.put(r.getRowNum(), r);
} }
rows = map; _rows = map;
} }
/** /**
@ -2441,13 +2441,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
worksheet.getHyperlinks().setHyperlinkArray(ctHls); worksheet.getHyperlinks().setHyperlinkArray(ctHls);
} }
CTSheetData sheetData = worksheet.getSheetData(); for(XSSFRow row : _rows.values()){
ArrayList<CTRow> rArray = new ArrayList<CTRow>(rows.size());
for(XSSFRow row : rows.values()){
row.onDocumentWrite(); row.onDocumentWrite();
rArray.add(row.getCTRow());
} }
sheetData.setRowArray(rArray.toArray(new CTRow[rArray.size()])); ensureRowOrdering();
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
@ -2458,6 +2455,32 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
worksheet.save(out, xmlOptions); 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. * @return true when Autofilters are locked and the sheet is protected.
*/ */