mirror of https://github.com/apache/poi.git
bug 61730: add iterator interface to CellRangeAddressBase for iterating over CellAddresses
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1814448 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ca53a08a90
commit
cbb82add8f
|
@ -17,7 +17,12 @@
|
||||||
|
|
||||||
package org.apache.poi.ss.util;
|
package org.apache.poi.ss.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
|
@ -29,7 +34,7 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||||
*
|
*
|
||||||
* Common superclass of 8-bit and 16-bit versions
|
* Common superclass of 8-bit and 16-bit versions
|
||||||
*/
|
*/
|
||||||
public abstract class CellRangeAddressBase {
|
public abstract class CellRangeAddressBase implements Iterable<CellAddress> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a cell or range is in the given relative position in a range.
|
* Indicates a cell or range is in the given relative position in a range.
|
||||||
|
@ -160,6 +165,20 @@ public abstract class CellRangeAddressBase {
|
||||||
return isInRange(ref.getRow(), ref.getCol());
|
return isInRange(ref.getRow(), ref.getCol());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given {@link CellAddress} lies within the bounds
|
||||||
|
* of this range.
|
||||||
|
* <p>NOTE: It is up to the caller to ensure the reference is
|
||||||
|
* for the correct sheet, since this instance doesn't have a sheet reference.
|
||||||
|
*
|
||||||
|
* @param ref the CellAddress to check
|
||||||
|
* @return True if the reference lies within the bounds, false otherwise.
|
||||||
|
* @see #intersects(CellRangeAddressBase) for checking if two ranges overlap
|
||||||
|
*/
|
||||||
|
public boolean isInRange(CellAddress ref) {
|
||||||
|
return isInRange(ref.getRow(), ref.getColumn());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the given {@link Cell} lies within the bounds
|
* Determines if the given {@link Cell} lies within the bounds
|
||||||
* of this range.
|
* of this range.
|
||||||
|
@ -264,10 +283,82 @@ public abstract class CellRangeAddressBase {
|
||||||
return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1);
|
return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CellAddress> getCellAddresses(boolean rowMajorOrder) {
|
||||||
|
List<CellAddress> addresses = new ArrayList<>();
|
||||||
|
if (rowMajorOrder) {
|
||||||
|
for (int r = _firstRow; r <= _lastRow; r++) {
|
||||||
|
for (int c = _firstCol; c <= _lastCol; c++) {
|
||||||
|
addresses.add(new CellAddress(r, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int c = _firstCol; c <= _lastCol; c++) {
|
||||||
|
for (int r = _firstRow; r <= _lastRow; r++) {
|
||||||
|
addresses.add(new CellAddress(r, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public Iterator<CellAddress> iterator() {
|
||||||
CellReference crA = new CellReference(_firstRow, _firstCol);
|
return new RowMajorCellAddressIterator(this);
|
||||||
CellReference crB = new CellReference(_lastRow, _lastCol);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the cell addresses in a cell range in row major order
|
||||||
|
*
|
||||||
|
* The iterator is unaffected by changes to the CellRangeAddressBase instance
|
||||||
|
* after the iterator is created.
|
||||||
|
*/
|
||||||
|
private static class RowMajorCellAddressIterator implements Iterator<CellAddress> {
|
||||||
|
private final int firstRow, firstCol, lastRow, lastCol;
|
||||||
|
private int r, c;
|
||||||
|
|
||||||
|
public RowMajorCellAddressIterator(CellRangeAddressBase ref) {
|
||||||
|
r = firstRow = ref.getFirstRow();
|
||||||
|
c = firstCol = ref.getFirstColumn();
|
||||||
|
lastRow = ref.getLastRow();
|
||||||
|
lastCol = ref.getLastColumn();
|
||||||
|
|
||||||
|
// whole row and whole column ranges currently not supported
|
||||||
|
if (firstRow < 0) throw new IllegalStateException("First row cannot be negative.");
|
||||||
|
if (firstCol < 0) throw new IllegalStateException("First column cannot be negative.");
|
||||||
|
|
||||||
|
// avoid infinite iteration
|
||||||
|
if (firstRow > lastRow) throw new IllegalStateException("First row cannot be greater than last row.");
|
||||||
|
if (firstCol > lastCol) throw new IllegalStateException("First column cannot be greater than last column.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return r <= lastRow && c <= lastCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CellAddress next() {
|
||||||
|
if (hasNext()) {
|
||||||
|
final CellAddress addr = new CellAddress(r, c);
|
||||||
|
// row major order
|
||||||
|
if (c < lastCol) {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else { //c >= lastCol, end of row reached
|
||||||
|
c = firstCol; //CR
|
||||||
|
r++; //LF
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String toString() {
|
||||||
|
CellAddress crA = new CellAddress(_firstRow, _firstCol);
|
||||||
|
CellAddress crB = new CellAddress(_lastRow, _lastCol);
|
||||||
return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]";
|
return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,17 @@ package org.apache.poi.ss.util;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
||||||
import org.apache.poi.util.LittleEndianOutputStream;
|
import org.apache.poi.util.LittleEndianOutputStream;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public final class TestCellRangeAddress {
|
public final class TestCellRangeAddress {
|
||||||
|
@ -263,6 +265,39 @@ public final class TestCellRangeAddress {
|
||||||
assertFalse(region.containsColumn(6));
|
assertFalse(region.containsColumn(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iterator() {
|
||||||
|
final CellRangeAddress A1_B2 = new CellRangeAddress(0, 1, 0, 1);
|
||||||
|
|
||||||
|
// the cell address iterator iterates in row major order
|
||||||
|
final Iterator<CellAddress> iter = A1_B2.iterator();
|
||||||
|
assertEquals("A1", new CellAddress(0, 0), iter.next());
|
||||||
|
assertEquals("B1", new CellAddress(0, 1), iter.next());
|
||||||
|
assertEquals("A2", new CellAddress(1, 0), iter.next());
|
||||||
|
assertEquals("B2", new CellAddress(1, 1), iter.next());
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException");
|
||||||
|
} catch (final NoSuchElementException e) {
|
||||||
|
//expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
iter.remove();
|
||||||
|
fail("Expected UnsupportedOperationException");
|
||||||
|
} catch (final UnsupportedOperationException e) {
|
||||||
|
//expected
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each interface
|
||||||
|
int count = 0;
|
||||||
|
for (final CellAddress addr : A1_B2) {
|
||||||
|
assertNotNull(addr);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
assertEquals(4, count);
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertIntersects(CellRangeAddress regionA, CellRangeAddress regionB) {
|
private static void assertIntersects(CellRangeAddress regionA, CellRangeAddress regionB) {
|
||||||
if (!(regionA.intersects(regionB) && regionB.intersects(regionA))) {
|
if (!(regionA.intersects(regionB) && regionB.intersects(regionA))) {
|
||||||
final String A = regionA.formatAsString();
|
final String A = regionA.formatAsString();
|
||||||
|
|
Loading…
Reference in New Issue