]> source.dussan.org Git - poi.git/commitdiff
Bug 55280: Implement a method XSSFSheet.removeMergedRegions() to bulk remove merged...
authorDominik Stadler <centic@apache.org>
Sun, 31 Aug 2014 20:24:42 +0000 (20:24 +0000)
committerDominik Stadler <centic@apache.org>
Sun, 31 Aug 2014 20:24:42 +0000 (20:24 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1621633 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java

index 543263f7af647423b477d252fcf7ae1461383421..60ecf7bb9ff1da0be892ce5191cc748b65f0100b 100644 (file)
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 import javax.xml.namespace.QName;
@@ -43,16 +44,7 @@ import org.apache.poi.openxml4j.opc.TargetMode;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.FormulaShifter;
 import org.apache.poi.ss.formula.SheetNameFormatter;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellRange;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.DataValidation;
-import org.apache.poi.ss.usermodel.DataValidationHelper;
-import org.apache.poi.ss.usermodel.Footer;
-import org.apache.poi.ss.usermodel.Header;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
@@ -70,48 +62,7 @@ import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
 import org.apache.xmlbeans.XmlException;
 import org.apache.xmlbeans.XmlOptions;
 import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAutoFilter;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidations;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLegacyDrawing;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCells;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOutlinePr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetCalcPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTablePart;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableParts;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
 
 /**
  * High level representation of a SpreadsheetML worksheet.
@@ -1595,6 +1546,33 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
             worksheet.unsetMergeCells();
         }
     }
+    
+    /**
+     * Removes a number of merged regions of cells (hence letting them free)
+     * 
+     * This method can be used to bulk-remove merged regions in a way
+     * much faster than calling removeMergedRegion() for every single 
+     * merged region.
+     *
+     * @param indices A set of the regions to unmerge
+     */
+    public void removeMergedRegions(Set<Integer> indices) {
+        CTMergeCells ctMergeCells = worksheet.getMergeCells();
+
+        int size = ctMergeCells.sizeOfMergeCellArray();
+        CTMergeCell[] mergeCellsArray = new CTMergeCell[size - indices.size()];
+        for (int i = 0, d = 0 ; i < size ; i++) {
+            if(!indices.contains(i)) {
+                mergeCellsArray[d] = ctMergeCells.getMergeCellArray(i);
+                d++;
+            }
+        }
+        if(mergeCellsArray.length > 0){
+            ctMergeCells.setMergeCellArray(mergeCellsArray);
+        } else{
+            worksheet.unsetMergeCells();
+        }
+    }
 
     /**
      * Remove a row from this sheet.  All cells contained in the row are removed as well
index b5614082e2c23267f6ecb366fa8a2bcd0edf599d..9ec69d179526318868748cf4843329df674d1603 100644 (file)
@@ -18,7 +18,9 @@
 package org.apache.poi.xssf.usermodel.helpers;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.poi.ss.formula.FormulaParseException;
 import org.apache.poi.ss.formula.FormulaParser;
@@ -67,8 +69,10 @@ public final class XSSFRowShifter {
      */
     public List<CellRangeAddress> shiftMerged(int startRow, int endRow, int n) {
         List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
+        Set<Integer> removedIndices = new HashSet<Integer>();
         //move merged regions completely if they fall within the new region boundaries when they are shifted
-        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
+        int size = sheet.getNumMergedRegions();
+        for (int i = 0; i < size; i++) {
             CellRangeAddress merged = sheet.getMergedRegion(i);
 
             boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
@@ -85,10 +89,13 @@ public final class XSSFRowShifter {
                 merged.setLastRow(merged.getLastRow() + n);
                 //have to remove/add it back
                 shiftedRegions.add(merged);
-                sheet.removeMergedRegion(i);
-                i = i - 1; // we have to back up now since we removed one
+                removedIndices.add(i);
             }
         }
+        
+        if(!removedIndices.isEmpty()) {
+            sheet.removeMergedRegions(removedIndices);
+        }
 
         //read so it doesn't get shifted again
         for (CellRangeAddress region : shiftedRegions) {
index d7bfc2f769a19aa8fa7ee72976d67f3442b1e110..d3729e0c921b87e1d7423853a18458cb32df023d 100644 (file)
@@ -25,9 +25,11 @@ import org.apache.poi.ss.usermodel.Comment;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellUtil;
 import org.apache.poi.xssf.XSSFITestDataProvider;
 import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.junit.Test;
 
 /**
  * @author Yegor Kozlov
@@ -187,4 +189,14 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows {
         assertEquals("Amdocs", comment.getAuthor());
         assertEquals("Amdocs:\ntest\n", comment.getString().getString());
        }
+
+       @Test
+       public void testBug55280() {
+        Workbook w = new XSSFWorkbook();
+        Sheet s = w.createSheet();
+        for (int row = 0; row < 5000; ++row)
+            s.addMergedRegion(new CellRangeAddress(row, row, 0, 3));
+
+        s.shiftRows(0, 4999, 1);        // takes a long time...
+       }
 }