You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CellRangeAddressBase.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.util;
  16. import org.apache.poi.ss.SpreadsheetVersion;
  17. import org.apache.poi.ss.usermodel.Cell;
  18. /**
  19. * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
  20. *
  21. * Common superclass of 8-bit and 16-bit versions
  22. */
  23. public abstract class CellRangeAddressBase {
  24. private int _firstRow;
  25. private int _firstCol;
  26. private int _lastRow;
  27. private int _lastCol;
  28. protected CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) {
  29. _firstRow = firstRow;
  30. _lastRow = lastRow;
  31. _firstCol = firstCol;
  32. _lastCol = lastCol;
  33. }
  34. /**
  35. * Validate the range limits against the supplied version of Excel
  36. *
  37. * @param ssVersion the version of Excel to validate against
  38. * @throws IllegalArgumentException if the range limits are outside of the allowed range
  39. */
  40. public void validate(SpreadsheetVersion ssVersion) {
  41. validateRow(_firstRow, ssVersion);
  42. validateRow(_lastRow, ssVersion);
  43. validateColumn(_firstCol, ssVersion);
  44. validateColumn(_lastCol, ssVersion);
  45. }
  46. /**
  47. * Runs a bounds check for row numbers
  48. * @param row
  49. */
  50. private static void validateRow(int row, SpreadsheetVersion ssVersion) {
  51. int maxrow = ssVersion.getLastRowIndex();
  52. if (row > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow);
  53. if (row < 0) throw new IllegalArgumentException("Minumum row number is 0");
  54. }
  55. /**
  56. * Runs a bounds check for column numbers
  57. * @param column
  58. */
  59. private static void validateColumn(int column, SpreadsheetVersion ssVersion) {
  60. int maxcol = ssVersion.getLastColumnIndex();
  61. if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol);
  62. if (column < 0) throw new IllegalArgumentException("Minimum column number is 0");
  63. }
  64. //TODO use the correct SpreadsheetVersion
  65. public final boolean isFullColumnRange() {
  66. return (_firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex())
  67. || (_firstRow == -1 && _lastRow == -1);
  68. }
  69. //TODO use the correct SpreadsheetVersion
  70. public final boolean isFullRowRange() {
  71. return (_firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex())
  72. || (_firstCol == -1 && _lastCol == -1);
  73. }
  74. /**
  75. * @return column number for the upper left hand corner
  76. */
  77. public final int getFirstColumn() {
  78. return _firstCol;
  79. }
  80. /**
  81. * @return row number for the upper left hand corner
  82. */
  83. public final int getFirstRow() {
  84. return _firstRow;
  85. }
  86. /**
  87. * @return column number for the lower right hand corner
  88. */
  89. public final int getLastColumn() {
  90. return _lastCol;
  91. }
  92. /**
  93. * @return row number for the lower right hand corner
  94. */
  95. public final int getLastRow() {
  96. return _lastRow;
  97. }
  98. /**
  99. * Determines if the given coordinates lie within the bounds
  100. * of this range.
  101. *
  102. * @param rowInd The row, 0-based.
  103. * @param colInd The column, 0-based.
  104. * @return True if the coordinates lie within the bounds, false otherwise.
  105. * @see #intersects(CellRangeAddressBase) for checking if two ranges overlap
  106. */
  107. public boolean isInRange(int rowInd, int colInd) {
  108. return _firstRow <= rowInd && rowInd <= _lastRow && //containsRow
  109. _firstCol <= colInd && colInd <= _lastCol; //containsColumn
  110. }
  111. /**
  112. * Determines if the given {@link CellReference} lies within the bounds
  113. * of this range.
  114. * <p/>NOTE: It is up to the caller to ensure the reference is
  115. * for the correct sheet, since this instance doesn't have a sheet reference.
  116. *
  117. * @param ref the CellReference to check
  118. * @return True if the reference lies within the bounds, false otherwise.
  119. * @see #intersects(CellRangeAddressBase) for checking if two ranges overlap
  120. */
  121. public boolean isInRange(CellReference ref) {
  122. return isInRange(ref.getRow(), ref.getCol());
  123. }
  124. /**
  125. * Determines if the given {@link Cell} lies within the bounds
  126. * of this range.
  127. * <p/>NOTE: It is up to the caller to ensure the reference is
  128. * for the correct sheet, since this instance doesn't have a sheet reference.
  129. *
  130. * @param cell the Cell to check
  131. * @return True if the cell lies within the bounds, false otherwise.
  132. * @see #intersects(CellRangeAddressBase) for checking if two ranges overlap
  133. */
  134. public boolean isInRange(Cell cell) {
  135. return isInRange(cell.getRowIndex(), cell.getColumnIndex());
  136. }
  137. /**
  138. * Check if the row is in the specified cell range
  139. *
  140. * @param rowInd the row to check
  141. * @return true if the range contains the row [rowInd]
  142. */
  143. public boolean containsRow(int rowInd) {
  144. return _firstRow <= rowInd && rowInd <= _lastRow;
  145. }
  146. /**
  147. * Check if the column is in the specified cell range
  148. *
  149. * @param colInd the column to check
  150. * @return true if the range contains the column [colInd]
  151. */
  152. public boolean containsColumn(int colInd) {
  153. return _firstCol <= colInd && colInd <= _lastCol;
  154. }
  155. /**
  156. * Determines whether or not this CellRangeAddress and the specified CellRangeAddress intersect.
  157. *
  158. * @param other a candidate cell range address to check for intersection with this range
  159. * @return returns true if this range and other range have at least 1 cell in common
  160. * @see #isInRange(int, int) for checking if a single cell intersects
  161. */
  162. public boolean intersects(CellRangeAddressBase other) {
  163. return this._firstRow <= other._lastRow &&
  164. this._firstCol <= other._lastCol &&
  165. other._firstRow <= this._lastRow &&
  166. other._firstCol <= this._lastCol;
  167. }
  168. /**
  169. * @param firstCol column number for the upper left hand corner
  170. */
  171. public final void setFirstColumn(int firstCol) {
  172. _firstCol = firstCol;
  173. }
  174. /**
  175. * @param firstRow row number for the upper left hand corner
  176. */
  177. public final void setFirstRow(int firstRow) {
  178. _firstRow = firstRow;
  179. }
  180. /**
  181. * @param lastCol column number for the lower right hand corner
  182. */
  183. public final void setLastColumn(int lastCol) {
  184. _lastCol = lastCol;
  185. }
  186. /**
  187. * @param lastRow row number for the lower right hand corner
  188. */
  189. public final void setLastRow(int lastRow) {
  190. _lastRow = lastRow;
  191. }
  192. /**
  193. * @return the size of the range (number of cells in the area).
  194. */
  195. public int getNumberOfCells() {
  196. return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1);
  197. }
  198. @Override
  199. public final String toString() {
  200. CellReference crA = new CellReference(_firstRow, _firstCol);
  201. CellReference crB = new CellReference(_lastRow, _lastCol);
  202. return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]";
  203. }
  204. // In case _firstRow > _lastRow or _firstCol > _lastCol
  205. protected int getMinRow() {
  206. return Math.min(_firstRow, _lastRow);
  207. }
  208. protected int getMaxRow() {
  209. return Math.max(_firstRow, _lastRow);
  210. }
  211. protected int getMinColumn() {
  212. return Math.min(_firstCol, _lastCol);
  213. }
  214. protected int getMaxColumn() {
  215. return Math.max(_firstCol, _lastCol);
  216. }
  217. @Override
  218. public boolean equals(Object other) {
  219. if (other instanceof CellRangeAddressBase) {
  220. CellRangeAddressBase o = (CellRangeAddressBase) other;
  221. return ((getMinRow() == o.getMinRow()) &&
  222. (getMaxRow() == o.getMaxRow()) &&
  223. (getMinColumn() == o.getMinColumn()) &&
  224. (getMaxColumn() == o.getMaxColumn()));
  225. }
  226. return false;
  227. }
  228. @Override
  229. public int hashCode() {
  230. int code = (getMinColumn() +
  231. (getMaxColumn() << 8) +
  232. (getMinRow() << 16) +
  233. (getMaxRow() << 24));
  234. return code;
  235. }
  236. }