diff options
Diffstat (limited to 'src/java')
-rw-r--r-- | src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java | 181 | ||||
-rw-r--r-- | src/java/org/apache/poi/ss/util/CellRangeAddressBase.java | 3 |
2 files changed, 49 insertions, 135 deletions
diff --git a/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java b/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java index b795d02288..d1532a94d6 100644 --- a/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java +++ b/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java @@ -97,45 +97,47 @@ public final class CellRangeUtil } List<CellRangeAddress> lst = new ArrayList<CellRangeAddress>(); - for(CellRangeAddress cr : cellRanges) lst.add(cr); - List temp = mergeCellRanges(lst); + for(CellRangeAddress cr : cellRanges) { + lst.add(cr); + } + List<CellRangeAddress> temp = mergeCellRanges(lst); return toArray(temp); } - private static List mergeCellRanges(List cellRangeList) + + private static List<CellRangeAddress> mergeCellRanges(List<CellRangeAddress> cellRangeList) { + // loop until either only one item is left or we did not merge anything any more + while (cellRangeList.size() > 1) { + boolean somethingGotMerged = false; - while(cellRangeList.size() > 1) - { - boolean somethingGotMerged = false; - - for( int i=0; i<cellRangeList.size(); i++) - { - CellRangeAddress range1 = (CellRangeAddress)cellRangeList.get(i); - for( int j=i+1; j<cellRangeList.size(); j++) - { - CellRangeAddress range2 = (CellRangeAddress)cellRangeList.get(j); - - CellRangeAddress[] mergeResult = mergeRanges(range1, range2); - if(mergeResult == null) { - continue; - } - somethingGotMerged = true; - // overwrite range1 with first result - cellRangeList.set(i, mergeResult[0]); - // remove range2 - cellRangeList.remove(j--); - // add any extra results beyond the first - for(int k=1; k<mergeResult.length; k++) { - j++; - cellRangeList.add(j, mergeResult[k]); - } - } - } - if(!somethingGotMerged) { - break; - } - } - + // look at all cell-ranges + for (int i = 0; i < cellRangeList.size(); i++) { + CellRangeAddress range1 = cellRangeList.get(i); + + // compare each cell range to all other cell-ranges + for (int j = i + 1; j < cellRangeList.size(); j++) { + CellRangeAddress range2 = cellRangeList.get(j); + + CellRangeAddress[] mergeResult = mergeRanges(range1, range2); + if (mergeResult == null) { + continue; + } + somethingGotMerged = true; + // overwrite range1 with first result + cellRangeList.set(i, mergeResult[0]); + // remove range2 + cellRangeList.remove(j--); + // add any extra results beyond the first + for (int k = 1; k < mergeResult.length; k++) { + j++; + cellRangeList.add(j, mergeResult[k]); + } + } + } + if (!somethingGotMerged) { + break; + } + } return cellRangeList; } @@ -144,122 +146,33 @@ public final class CellRangeUtil * @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible */ private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) { - int x = intersect(range1, range2); switch(x) { case CellRangeUtil.NO_INTERSECTION: + // nothing in common: at most they could be adjacent to each other and thus form a single bigger area if(hasExactSharedBorder(range1, range2)) { return new CellRangeAddress[] { createEnclosingCellRange(range1, range2), }; } // else - No intersection and no shared border: do nothing return null; case CellRangeUtil.OVERLAP: - return resolveRangeOverlap(range1, range2); + // commented out the cells overlap implementation, it caused endless loops, see Bug 55380 + // disabled for now, the algorithm will not detect some border cases this way currently! + //return resolveRangeOverlap(range1, range2); + return null; case CellRangeUtil.INSIDE: // Remove range2, since it is completely inside of range1 - return new CellRangeAddress[] { range1, }; + return new CellRangeAddress[] { range1 }; case CellRangeUtil.ENCLOSES: // range2 encloses range1, so replace it with the enclosing one - return new CellRangeAddress[] { range2, }; + return new CellRangeAddress[] { range2 }; } throw new RuntimeException("unexpected intersection result (" + x + ")"); } - - // TODO - write junit test for this - static CellRangeAddress[] resolveRangeOverlap(CellRangeAddress rangeA, CellRangeAddress rangeB) { - - if(rangeA.isFullColumnRange()) { - if(rangeA.isFullRowRange()) { - // Excel seems to leave these unresolved - return null; - } - return sliceUp(rangeA, rangeB); - } - if(rangeA.isFullRowRange()) { - if(rangeB.isFullColumnRange()) { - // Excel seems to leave these unresolved - return null; - } - return sliceUp(rangeA, rangeB); - } - if(rangeB.isFullColumnRange()) { - return sliceUp(rangeB, rangeA); - } - if(rangeB.isFullRowRange()) { - return sliceUp(rangeB, rangeA); - } - return sliceUp(rangeA, rangeB); - } - - /** - * @param crB never a full row or full column range - * @return an array including <b>this</b> <tt>CellRange</tt> and all parts of <tt>range</tt> - * outside of this range - */ - private static CellRangeAddress[] sliceUp(CellRangeAddress crA, CellRangeAddress crB) { - - List temp = new ArrayList(); - - // Chop up range horizontally and vertically - temp.add(crB); - if(!crA.isFullColumnRange()) { - temp = cutHorizontally(crA.getFirstRow(), temp); - temp = cutHorizontally(crA.getLastRow()+1, temp); - } - if(!crA.isFullRowRange()) { - temp = cutVertically(crA.getFirstColumn(), temp); - temp = cutVertically(crA.getLastColumn()+1, temp); - } - CellRangeAddress[] crParts = toArray(temp); - - // form result array - temp.clear(); - temp.add(crA); - - for (int i = 0; i < crParts.length; i++) { - CellRangeAddress crPart = crParts[i]; - // only include parts that are not enclosed by this - if(intersect(crA, crPart) != ENCLOSES) { - temp.add(crPart); - } - } - return toArray(temp); - } - - private static List cutHorizontally(int cutRow, List input) { - - List result = new ArrayList(); - CellRangeAddress[] crs = toArray(input); - for (int i = 0; i < crs.length; i++) { - CellRangeAddress cr = crs[i]; - if(cr.getFirstRow() < cutRow && cutRow < cr.getLastRow()) { - result.add(new CellRangeAddress(cr.getFirstRow(), cutRow, cr.getFirstColumn(), cr.getLastColumn())); - result.add(new CellRangeAddress(cutRow+1, cr.getLastRow(), cr.getFirstColumn(), cr.getLastColumn())); - } else { - result.add(cr); - } - } - return result; - } - private static List cutVertically(int cutColumn, List input) { - - List result = new ArrayList(); - CellRangeAddress[] crs = toArray(input); - for (int i = 0; i < crs.length; i++) { - CellRangeAddress cr = crs[i]; - if(cr.getFirstColumn() < cutColumn && cutColumn < cr.getLastColumn()) { - result.add(new CellRangeAddress(cr.getFirstRow(), cr.getLastRow(), cr.getFirstColumn(), cutColumn)); - result.add(new CellRangeAddress(cr.getFirstRow(), cr.getLastRow(), cutColumn+1, cr.getLastColumn())); - } else { - result.add(cr); - } - } - return result; - } - - private static CellRangeAddress[] toArray(List temp) { + + private static CellRangeAddress[] toArray(List<CellRangeAddress> temp) { CellRangeAddress[] result = new CellRangeAddress[temp.size()]; temp.toArray(result); return result; @@ -284,7 +197,7 @@ public final class CellRangeUtil } /** - * Check if the specified cell range has a shared border with the current range. + * Check if the two cell ranges have a shared border. * * @return <code>true</code> if the ranges have a complete shared border (i.e. * the two ranges together make a simple rectangular region. diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java index 12aaa6f629..ffb6e530bb 100644 --- a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java +++ b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java @@ -152,7 +152,8 @@ public abstract class CellRangeAddressBase { return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1); } - public final String toString() { + @Override + public final String toString() { CellReference crA = new CellReference(_firstRow, _firstCol); CellReference crB = new CellReference(_lastRow, _lastCol); return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]"; |