| /* ==================================================================== |
| 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.SpreadsheetVersion; |
| |
| |
| /** |
| * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/> |
| * |
| * Common superclass of 8-bit and 16-bit versions |
| */ |
| public abstract class CellRangeAddressBase { |
| |
| private int _firstRow; |
| private int _firstCol; |
| private int _lastRow; |
| private int _lastCol; |
| |
| protected CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) { |
| _firstRow = firstRow; |
| _lastRow = lastRow; |
| _firstCol = firstCol; |
| _lastCol = lastCol; |
| } |
| |
| /** |
| * Validate the range limits against the supplied version of Excel |
| * |
| * @param ssVersion the version of Excel to validate against |
| * @throws IllegalArgumentException if the range limits are outside of the allowed range |
| */ |
| public void validate(SpreadsheetVersion ssVersion) { |
| validateRow(_firstRow, ssVersion); |
| validateRow(_lastRow, ssVersion); |
| validateColumn(_firstCol, ssVersion); |
| validateColumn(_lastCol, ssVersion); |
| } |
| /** |
| * Runs a bounds check for row numbers |
| * @param row |
| */ |
| private static void validateRow(int row, SpreadsheetVersion ssVersion) { |
| int maxrow = ssVersion.getLastRowIndex(); |
| if (row > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow); |
| if (row < 0) throw new IllegalArgumentException("Minumum row number is 0"); |
| } |
| |
| /** |
| * Runs a bounds check for column numbers |
| * @param column |
| */ |
| private static void validateColumn(int column, SpreadsheetVersion ssVersion) { |
| int maxcol = ssVersion.getLastColumnIndex(); |
| if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol); |
| if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); |
| } |
| |
| |
| //TODO use the correct SpreadsheetVersion |
| public final boolean isFullColumnRange() { |
| return (_firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex()) |
| || (_firstRow == -1 && _lastRow == -1); |
| } |
| //TODO use the correct SpreadsheetVersion |
| public final boolean isFullRowRange() { |
| return (_firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex()) |
| || (_firstCol == -1 && _lastCol == -1); |
| } |
| |
| /** |
| * @return column number for the upper left hand corner |
| */ |
| public final int getFirstColumn() { |
| return _firstCol; |
| } |
| |
| /** |
| * @return row number for the upper left hand corner |
| */ |
| public final int getFirstRow() { |
| return _firstRow; |
| } |
| |
| /** |
| * @return column number for the lower right hand corner |
| */ |
| public final int getLastColumn() { |
| return _lastCol; |
| } |
| |
| /** |
| * @return row number for the lower right hand corner |
| */ |
| public final int getLastRow() { |
| return _lastRow; |
| } |
| |
| /** |
| * Determines if the given coordinates lie within the bounds |
| * of this range. |
| * |
| * @param rowInd The row, 0-based. |
| * @param colInd The column, 0-based. |
| * @return True if the coordinates lie within the bounds, false otherwise. |
| * @see #intersects(CellRangeAddressBase) for checking if two ranges overlap |
| */ |
| public boolean isInRange(int rowInd, int colInd) { |
| return _firstRow <= rowInd && rowInd <= _lastRow && //containsRow |
| _firstCol <= colInd && colInd <= _lastCol; //containsColumn |
| } |
| |
| /** |
| * Check if the row is in the specified cell range |
| * |
| * @param rowInd the row to check |
| * @return true if the range contains the row [rowInd] |
| */ |
| public boolean containsRow(int rowInd) { |
| return _firstRow <= rowInd && rowInd <= _lastRow; |
| } |
| |
| /** |
| * Check if the column is in the specified cell range |
| * |
| * @param colInd the column to check |
| * @return true if the range contains the column [colInd] |
| */ |
| public boolean containsColumn(int colInd) { |
| return _firstCol <= colInd && colInd <= _lastCol; |
| } |
| |
| /** |
| * Determines whether or not this CellRangeAddress and the specified CellRangeAddress intersect. |
| * |
| * @param other a candidate cell range address to check for intersection with this range |
| * @return returns true if this range and other range have at least 1 cell in common |
| * @see #isInRange(int, int) for checking if a single cell intersects |
| */ |
| public boolean intersects(CellRangeAddressBase other) { |
| return this._firstRow <= other._lastRow && |
| this._firstCol <= other._lastCol && |
| other._firstRow <= this._lastRow && |
| other._firstCol <= this._lastCol; |
| } |
| |
| /** |
| * @param firstCol column number for the upper left hand corner |
| */ |
| public final void setFirstColumn(int firstCol) { |
| _firstCol = firstCol; |
| } |
| |
| /** |
| * @param firstRow row number for the upper left hand corner |
| */ |
| public final void setFirstRow(int firstRow) { |
| _firstRow = firstRow; |
| } |
| |
| /** |
| * @param lastCol column number for the lower right hand corner |
| */ |
| public final void setLastColumn(int lastCol) { |
| _lastCol = lastCol; |
| } |
| |
| /** |
| * @param lastRow row number for the lower right hand corner |
| */ |
| public final void setLastRow(int lastRow) { |
| _lastRow = lastRow; |
| } |
| /** |
| * @return the size of the range (number of cells in the area). |
| */ |
| public int getNumberOfCells() { |
| return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1); |
| } |
| |
| @Override |
| public final String toString() { |
| CellReference crA = new CellReference(_firstRow, _firstCol); |
| CellReference crB = new CellReference(_lastRow, _lastCol); |
| return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]"; |
| } |
| |
| // In case _firstRow > _lastRow or _firstCol > _lastCol |
| protected int getMinRow() { |
| return Math.min(_firstRow, _lastRow); |
| } |
| protected int getMaxRow() { |
| return Math.max(_firstRow, _lastRow); |
| } |
| protected int getMinColumn() { |
| return Math.min(_firstCol, _lastCol); |
| } |
| protected int getMaxColumn() { |
| return Math.max(_firstCol, _lastCol); |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof CellRangeAddressBase) { |
| CellRangeAddressBase o = (CellRangeAddressBase) other; |
| return ((getMinRow() == o.getMinRow()) && |
| (getMaxRow() == o.getMaxRow()) && |
| (getMinColumn() == o.getMinColumn()) && |
| (getMaxColumn() == o.getMaxColumn())); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| int code = (getMinColumn() + |
| (getMaxColumn() << 8) + |
| (getMinRow() << 16) + |
| (getMaxRow() << 24)); |
| return code; |
| } |
| } |