Bug 55280: Implement a method XSSFSheet.removeMergedRegions() to bulk remove merged regions and thus speed up shifting rows with many merged regions greatly.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1621633 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3eec314719
commit
a8f284d5f5
@ -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.
|
||||
@ -1596,6 +1547,33 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -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,11 +89,14 @@ 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) {
|
||||
sheet.addMergedRegion(region);
|
||||
|
@ -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...
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user