From a048ba2c2055c3b98328c4be96e09adee2af8a49 Mon Sep 17 00:00:00 2001 From: Javen O'Neal Date: Mon, 23 Nov 2015 09:30:53 +0000 Subject: [PATCH] bug 58637: contribution from Hannes Erven: add CellAddress class, distinct from CellReference git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1715743 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/ss/util/CellAddress.java | 160 ++++++++++++++++++ .../org/apache/poi/ss/util/CellReference.java | 11 +- .../apache/poi/ss/util/TestCellAddress.java | 110 ++++++++++++ 3 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/java/org/apache/poi/ss/util/CellAddress.java create mode 100644 src/testcases/org/apache/poi/ss/util/TestCellAddress.java diff --git a/src/java/org/apache/poi/ss/util/CellAddress.java b/src/java/org/apache/poi/ss/util/CellAddress.java new file mode 100644 index 0000000000..10dae8c11a --- /dev/null +++ b/src/java/org/apache/poi/ss/util/CellAddress.java @@ -0,0 +1,160 @@ +/* ==================================================================== + 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; + +/** + *

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.

+ * + *

Use 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). Use {@link CellReference} when the concept of + * relative/absolute does apply (such as a cell reference in a formula). + * CellAddresses do not have a concept of "sheet", while CellReferences do.

+ */ +public class CellAddress implements Comparable { + /** 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 + */ + @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); + } +} diff --git a/src/java/org/apache/poi/ss/util/CellReference.java b/src/java/org/apache/poi/ss/util/CellReference.java index cc695e92f4..cf0fa57dfd 100644 --- a/src/java/org/apache/poi/ss/util/CellReference.java +++ b/src/java/org/apache/poi/ss/util/CellReference.java @@ -26,10 +26,17 @@ import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.ss.usermodel.Cell; /** - * Common conversion functions between Excel style A1, C27 style + *

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"

+ * + *

Use CellReference 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). + * CellReferences have a concept of "sheet", while CellAddresses do not.

*/ public class CellReference { /** diff --git a/src/testcases/org/apache/poi/ss/util/TestCellAddress.java b/src/testcases/org/apache/poi/ss/util/TestCellAddress.java new file mode 100644 index 0000000000..6ca6f65be4 --- /dev/null +++ b/src/testcases/org/apache/poi/ss/util/TestCellAddress.java @@ -0,0 +1,110 @@ +/* ==================================================================== + 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()); + } +} -- 2.39.5