mirror of https://github.com/apache/poi.git
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:
parent
e79cc21802
commit
9f0cd544cf
|
@ -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>
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue