Add Sheet.getMergedRegions to obtain them all as a list. Implement this for XSSF using "deprecated" methods in XMLBeans which allow the operation to be linear in the number of regions rather than n-squared.

Fixes #57893

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690661 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David North 2015-07-13 13:00:35 +00:00
parent bae4602fa6
commit 3e36081b87
6 changed files with 105 additions and 1 deletions

View File

@ -867,6 +867,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
return _sheet.getMergedRegionAt(index); return _sheet.getMergedRegionAt(index);
} }
/**
* @return the list of merged regions
*/
public List<CellRangeAddress> getMergedRegions() {
List<CellRangeAddress> addresses = new ArrayList<CellRangeAddress>();
for (int i=0; i < _sheet.getNumMergedRegions(); i++) {
addresses.add(_sheet.getMergedRegionAt(i));
}
return addresses;
}
/** /**
* @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not
* be the third row if say for instance the second row is undefined. * be the third row if say for instance the second row is undefined.

View File

@ -320,6 +320,13 @@ public interface Sheet extends Iterable<Row> {
*/ */
public CellRangeAddress getMergedRegion(int index); public CellRangeAddress getMergedRegion(int index);
/**
* Returns the list of merged regions.
*
* @return the list of merged regions
*/
public List<CellRangeAddress> getMergedRegions();
/** /**
* Returns an iterator of the physical rows * Returns an iterator of the physical rows
* *

View File

@ -431,7 +431,9 @@ public class SXSSFSheet implements Sheet, Cloneable
} }
/** /**
* Returns the merged region at the specified index * Returns the merged region at the specified index. If you want multiple
* regions, it is faster to call {@link #getMergedRegions()} than to call
* this each time.
* *
* @return the merged region at the specified index * @return the merged region at the specified index
*/ */
@ -440,6 +442,17 @@ public class SXSSFSheet implements Sheet, Cloneable
return _sh.getMergedRegion(index); return _sh.getMergedRegion(index);
} }
/**
* Returns the list of merged regions. If you want multiple regions, this is
* faster than calling {@link #getMergedRegion(int)} each time.
*
* @return the list of merged regions
*/
@Override
public List<CellRangeAddress> getMergedRegions() {
return _sh.getMergedRegions();
}
/** /**
* Returns an iterator of the physical rows * Returns an iterator of the physical rows
* *

View File

@ -1082,6 +1082,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
} }
/** /**
* Returns the merged region at the specified index. If you want multiple
* regions, it is faster to call {@link #getMergedRegions()} than to call
* this each time.
*
* @return the merged region at the specified index * @return the merged region at the specified index
* @throws IllegalStateException if this worksheet does not contain merged regions * @throws IllegalStateException if this worksheet does not contain merged regions
*/ */
@ -1095,6 +1099,27 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return CellRangeAddress.valueOf(ref); return CellRangeAddress.valueOf(ref);
} }
/**
* Returns the list of merged regions. If you want multiple regions, this is
* faster than calling {@link #getMergedRegion(int)} each time.
*
* @return the list of merged regions
* @throws IllegalStateException if this worksheet does not contain merged regions
*/
@SuppressWarnings("deprecation")
@Override
public List<CellRangeAddress> getMergedRegions() {
CTMergeCells ctMergeCells = worksheet.getMergeCells();
if(ctMergeCells == null) throw new IllegalStateException("This worksheet does not contain merged regions");
List<CellRangeAddress> addresses = new ArrayList<CellRangeAddress>();
for(CTMergeCell ctMergeCell : ctMergeCells.getMergeCellArray()) {
String ref = ctMergeCell.getRef();
addresses.add(CellRangeAddress.valueOf(ref));
}
return addresses;
}
/** /**
* Returns the number of merged regions defined in this worksheet * Returns the number of merged regions defined in this worksheet
* *

View File

@ -0,0 +1,48 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.List;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.junit.Test;
public class TestXSSFSheetMergeRegions {
@Test
public void testMergeRegionsSpeed() throws IOException {
final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57893-many-merges.xlsx");
try {
final XSSFSheet sheet = wb.getSheetAt(0);
final long start = System.currentTimeMillis();
final List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
assertEquals(50000, mergedRegions.size());
for (CellRangeAddress cellRangeAddress : mergedRegions) {
assertEquals(cellRangeAddress.getFirstRow(), cellRangeAddress.getLastRow());
assertEquals(2, cellRangeAddress.getNumberOfCells());
}
long millis = System.currentTimeMillis() - start;
// This time is typically ~800ms, versus ~7800ms to iterate getMergedRegion(int).
assertTrue("Should have taken <2000 ms to iterate 50k merged regions but took " + millis, millis < 2000);
} finally {
wb.close();
}
}
}

Binary file not shown.