From 53769d29ad996efcaf1c08d98535d6a073b63604 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Wed, 10 Aug 2011 17:32:38 +0000 Subject: [PATCH] Bug 51635 - Improved performance of XSSFSheet#write git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156272 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../apache/poi/xssf/usermodel/XSSFSheet.java | 52 ++++++------------- .../poi/xssf/usermodel/TestXSSFSheet.java | 18 +++---- 3 files changed, 26 insertions(+), 45 deletions(-) diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 34733a2a4..1633fdc48 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 51635 - Improved performance of XSSFSheet#write 47731 - Word Extractor considers text copied from some website as an embedded object Add Word-to-Text converter and use it as replacement for WordExtractor 51604 - replace text fails for doc ( poi 3.8 beta release from download site ) 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 573777e56..a78162917 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -570,7 +570,15 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { ctRow = prev.getCTRow(); ctRow.set(CTRow.Factory.newInstance()); } else { - ctRow = worksheet.getSheetData().addNewRow(); + if(_rows.isEmpty() || rownum > _rows.lastKey()) { + // we can append the new row at the end + ctRow = worksheet.getSheetData().addNewRow(); + } else { + // get number of rows where row index < rownum + // --> this tells us where our row should go + int idx = _rows.headMap(rownum).size(); + ctRow = worksheet.getSheetData().insertNewRow(idx); + } } XSSFRow r = new XSSFRow(ctRow, this); r.setRowNum(rownum); @@ -1496,7 +1504,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { for(XSSFCell cell : cellsToDelete) row.removeCell(cell); + int idx = _rows.headMap(row.getRowNum()).size(); _rows.remove(row.getRowNum()); + worksheet.getSheetData().removeRow(idx); } /** @@ -2355,7 +2365,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ @SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { - for (Iterator it = rowIterator() ; it.hasNext() ; ) { + for (Iterator it = rowIterator() ; it.hasNext() ; ) { XSSFRow row = (XSSFRow)it.next(); int rownum = row.getRowNum(); if(rownum < startRow) continue; @@ -2365,6 +2375,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } if (removeRow(startRow, endRow, n, rownum)) { + // remove row from worksheet.getSheetData row array + int idx = _rows.headMap(row.getRowNum()).size(); + worksheet.getSheetData().removeRow(idx); + // remove row from _rows it.remove(); } else if (rownum >= startRow && rownum <= endRow) { @@ -2689,7 +2703,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { for(XSSFRow row : _rows.values()){ row.onDocumentWrite(); } - ensureRowOrdering(); XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); @@ -2700,39 +2713,6 @@ 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. - boolean isOrdered = true; - if(sheetData.sizeOfRowArray() != _rows.size()) isOrdered = false; - else { - int i = 0; - for (XSSFRow row : _rows.values()) { - CTRow c1 = row.getCTRow(); - CTRow c2 = sheetData.getRowArray(i++); - if (c1.getR() != c2.getR()){ - isOrdered = false; - break; - } - } - } - - if(!isOrdered){ - CTRow[] cArray = new CTRow[_rows.size()]; - int i = 0; - for(XSSFRow row : _rows.values()){ - cArray[i++] = row.getCTRow(); - } - sheetData.setRowArray(cArray); - } - } - /** * @return true when Autofilters are locked and the sheet is protected. */ diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java index aebdd45a7..ad02fa69e 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -901,7 +901,7 @@ public final class TestXSSFSheet extends BaseTestSheet { /** * Rows and cells can be created in random order, - * but serialization forces strict ascending order of the CTRow and CTCell xml beans + * but CTRows are kept in ascending order */ public void testCreateRow() { XSSFWorkbook workbook = new XSSFWorkbook(); @@ -929,20 +929,20 @@ public final class TestXSSFSheet extends BaseTestSheet { CTRow[] xrow = sheetData.getRowArray(); assertEquals(3, xrow.length); - //rows are unsorted: {2, 1, 0} - assertEquals(2, xrow[0].sizeOfCArray()); - assertEquals(3, xrow[0].getR()); - assertTrue(xrow[0].equals(row1.getCTRow())); + //rows are sorted: {0, 1, 2} + assertEquals(4, xrow[0].sizeOfCArray()); + assertEquals(1, xrow[0].getR()); + assertTrue(xrow[0].equals(row3.getCTRow())); assertEquals(3, xrow[1].sizeOfCArray()); assertEquals(2, xrow[1].getR()); assertTrue(xrow[1].equals(row2.getCTRow())); - assertEquals(4, xrow[2].sizeOfCArray()); - assertEquals(1, xrow[2].getR()); - assertTrue(xrow[2].equals(row3.getCTRow())); + assertEquals(2, xrow[2].sizeOfCArray()); + assertEquals(3, xrow[2].getR()); + assertTrue(xrow[2].equals(row1.getCTRow())); - CTCell[] xcell = xrow[2].getCArray(); + CTCell[] xcell = xrow[0].getCArray(); assertEquals("D1", xcell[0].getR()); assertEquals("A1", xcell[1].getR()); assertEquals("C1", xcell[2].getR());