--- /dev/null
+/* ====================================================================
+ 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.ss.util;
+
+import java.util.Locale;
+
+/**
+ * <p>This class is a container for POI usermodel row=0 column=0 cell references.
+ * It is barely a container for these two coordinates. The implementation
+ * of the Comparable interface sorts by "natural" order top left to bottom right.</p>
+ *
+ * <p>Use <tt>CellAddress</tt> when you want to refer to the location of a cell in a sheet
+ * when the concept of relative/absolute does not apply (such as the anchor location
+ * of a cell comment). Use {@link CellReference} when the concept of
+ * relative/absolute does apply (such as a cell reference in a formula).
+ * <tt>CellAddress</tt>es do not have a concept of "sheet", while <tt>CellReference</tt>s do.</p>
+ */
+public class CellAddress implements Comparable<CellAddress> {
+ /** A constant for references to the first cell in a sheet. */
+ public static final CellAddress A1 = new CellAddress(0, 0);
+
+ private final int _row;
+ private final int _col;
+
+ /**
+ * Create a new CellAddress object.
+ *
+ * @param row Row index (first row is 0)
+ * @param column Column index (first column is 0)
+ */
+ public CellAddress(int row, int column) {
+ super();
+ this._row = row;
+ this._col = column;
+ }
+
+ /**
+ * Create a new CellAddress object.
+ *
+ * @param address a cell address in A1 format. Address may not contain sheet name or dollar signs.
+ * (that is, address is not a cell reference. Use {@link #CellAddress(CellReference)} instead if
+ * starting with a cell reference.)
+ */
+ public CellAddress(String address) {
+ int length = address.length();
+
+ int loc = 0;
+ // step over column name chars until first digit for row number.
+ for (; loc < length; loc++) {
+ char ch = address.charAt(loc);
+ if (Character.isDigit(ch)) {
+ break;
+ }
+ }
+
+ String sCol = address.substring(0,loc).toUpperCase(Locale.ROOT);
+ String sRow = address.substring(loc);
+
+ // FIXME: breaks if address contains a sheet name or dollar signs from an absolute CellReference
+ this._row = Integer.parseInt(sRow)-1;
+ this._col = CellReference.convertColStringToIndex(sCol);
+ }
+
+ /**
+ * Create a new CellAddress object.
+ *
+ * @param reference a reference to a cell
+ */
+ public CellAddress(CellReference reference) {
+ this(reference.getRow(), reference.getCol());
+ }
+
+ /**
+ * Get the cell address row
+ *
+ * @return row
+ */
+ public int getRow() {
+ return _row;
+ }
+
+ /**
+ * Get the cell address column
+ *
+ * @return column
+ */
+ public int getColumn() {
+ return _col;
+ }
+
+ /**
+ * Compare this CellAddress using the "natural" row-major, column-minor ordering.
+ * That is, top-left to bottom-right ordering.
+ *
+ * @param other
+ * @return <ul>
+ * <li>-1 if this CellAddress is before (above/left) of other</li>
+ * <li>0 if addresses are the same</li>
+ * <li>1 if this CellAddress is after (below/right) of other</li>
+ * </ul>
+ */
+ @Override
+ public int compareTo(CellAddress other) {
+ int r = this._row-other._row;
+ if (r!=0) return r;
+
+ r = this._col-other._col;
+ if (r!=0) return r;
+
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if(!(o instanceof CellAddress)) {
+ return false;
+ }
+
+ CellAddress cr = (CellAddress) o;
+ return _row == cr._row
+ && _col == cr._col
+ ;
+ }
+
+ @Override
+ public int hashCode() {
+ return this._row + this._col<<16;
+ }
+
+ @Override
+ public String toString() {
+ return formatAsString();
+ }
+
+ /**
+ * Same as {@link #toString()}
+ * @return A1-style cell address string representation
+ */
+ public String formatAsString() {
+ return CellReference.convertNumToColString(this._col)+(this._row+1);
+ }
+}
import org.apache.poi.ss.usermodel.Cell;
/**
- * Common conversion functions between Excel style A1, C27 style
+ * <p>Common conversion functions between Excel style A1, C27 style
* cell references, and POI usermodel style row=0, column=0
* style references. Handles sheet-based and sheet-free references
- * as well, eg "Sheet1!A1" and "$B$72"
+ * as well, eg "Sheet1!A1" and "$B$72"</p>
+ *
+ * <p>Use <tt>CellReference</tt> when the concept of
+ * relative/absolute does apply (such as a cell reference in a formula).
+ * Use {@link CellAddress} when you want to refer to the location of a cell in a sheet
+ * when the concept of relative/absolute does not apply (such as the anchor location
+ * of a cell comment).
+ * <tt>CellReference</tt>s have a concept of "sheet", while <tt>CellAddress</tt>es do not.</p>
*/
public class CellReference {
/**
--- /dev/null
+/* ====================================================================
+ 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.ss.util;
+
+import org.apache.poi.ss.util.CellAddress;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Arrays;
+
+/**
+ * Tests that the common CellAddress works as we need it to.
+ * Note - some additional testing is also done in the HSSF class,
+ * {@link org.apache.poi.hssf.util.TestCellAddress}
+ */
+public final class TestCellAddress {
+ @Test
+ public void testConstructors() {
+ CellAddress cellAddress;
+ final CellReference cellRef = new CellReference("Sheet1", 0, 0, true, true);
+ final String address = "A1";
+ final int row = 0;
+ final int col = 0;
+
+ cellAddress = new CellAddress(row, col);
+ assertEquals(CellAddress.A1, cellAddress);
+
+ cellAddress = new CellAddress(address);
+ assertEquals(CellAddress.A1, cellAddress);
+
+ cellAddress = new CellAddress(cellRef);
+ assertEquals(CellAddress.A1, cellAddress);
+ }
+
+ @Test
+ public void testFormatAsString() {
+ assertEquals("A1", CellAddress.A1.formatAsString());
+ }
+
+ @Test
+ public void testEquals() {
+ assertEquals(new CellReference(6, 4), new CellReference(6, 4));
+ assertNotEquals(new CellReference(4, 6), new CellReference(6, 4));
+ }
+
+ @Test
+ public void testCompareTo() {
+ final CellAddress A1 = new CellAddress(0, 0);
+ final CellAddress A2 = new CellAddress(1, 0);
+ final CellAddress B1 = new CellAddress(0, 1);
+ final CellAddress B2 = new CellAddress(1, 1);
+
+ assertEquals(0, A1.compareTo(A1));
+ assertEquals(-1, A1.compareTo(B1));
+ assertEquals(-1, A1.compareTo(A2));
+ assertEquals(-1, A1.compareTo(B2));
+
+ assertEquals(1, B1.compareTo(A1));
+ assertEquals(0, B1.compareTo(B1));
+ assertEquals(-1, B1.compareTo(A2));
+ assertEquals(-1, B1.compareTo(B2));
+
+ assertEquals(1, A2.compareTo(A1));
+ assertEquals(1, A2.compareTo(B1));
+ assertEquals(0, A2.compareTo(A2));
+ assertEquals(-1, A2.compareTo(B2));
+
+ assertEquals(1, B2.compareTo(A1));
+ assertEquals(1, B2.compareTo(B1));
+ assertEquals(1, B2.compareTo(A2));
+ assertEquals(0, B2.compareTo(B2));
+
+ CellAddress[] sorted = {A1, B1, A2, B2};
+ CellAddress[] unsorted = {B1, B2, A1, A2};
+ assumeTrue(!sorted.equals(unsorted));
+ Arrays.sort(unsorted);
+ assertArrayEquals(sorted, unsorted);
+ }
+
+ @Test
+ public void testGetRow() {
+ final CellAddress addr = new CellAddress(6, 4);
+ assertEquals(6, addr.getRow());
+ }
+
+ @Test
+ public void testGetColumn() {
+ final CellAddress addr = new CellAddress(6, 4);
+ assertEquals(4, addr.getColumn());
+ }
+}