CellFinder.java
- package com.gh.mygreen.xlsmapper.util;
- import java.util.Optional;
- import org.apache.poi.ss.usermodel.Cell;
- import org.apache.poi.ss.usermodel.Row;
- import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
- import org.apache.poi.ss.usermodel.Sheet;
- import com.gh.mygreen.xlsmapper.Configuration;
- import com.gh.mygreen.xlsmapper.fieldprocessor.CellNotFoundException;
- /**
- * 指定したラベルを持つセルを検索するクラス。
- *
- * @since 2.0
- * @author T.TSUCHIE
- *
- */
- public class CellFinder {
-
-
- /**
- * シート情報
- */
- private final Sheet sheet;
-
- /**
- * システム設定
- */
- private final Configuration config;
-
- /**
- * 検索対象のラベル
- */
- private final String label;
-
- /**
- * 起点となる行番号
- * ・指定しない場合は、-1を指定する
- */
- private int startRow = -1;
-
- /**
- * 起点となる列番号
- * ・指定しない場合は、-1を指定する
- */
- private int startColumn = -1;
-
- /**
- * 起点となる位置を除外するかどうか
- */
- private boolean excludeStartPoisition = false;
-
- /**
- * 検索する際の条件を組み立てる
- * @param sheet 検索対象のシート
- * @param label 検索するセルのラベル
- * @param config システム設定。
- * 設定値 {@link Configuration#isNormalizeLabelText()}、{@link Configuration#isRegexLabelText()}の値によって、
- * 検索する際にラベルを正規化、または正規表現により一致するかで判定を行う。
- */
- public static CellFinder query(final Sheet sheet, final String label, final Configuration config) {
- return new CellFinder(sheet, label, config);
- }
-
- private CellFinder(final Sheet sheet, final String label, final Configuration config) {
-
- ArgUtils.notNull(sheet, "sheet");
- ArgUtils.notEmpty(label, "label");
- ArgUtils.notNull(config, "config");
-
- this.sheet = sheet;
- this.label = label;
- this.config = config;
- }
-
- /**
- * 起点なる位置を指定する。
- * @param column 列番号(0から始まる)
- * @param row 行番号(0から始まる)
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- * @throws IllegalArgumentException {@literal column < 0 or row < 0}
- */
- public CellFinder startPosition(final int column, final int row) {
- ArgUtils.notMin(column, 0, "column");
- ArgUtils.notMin(row, 0, "row");
-
- this.startColumn = column;
- this.startRow = row;
-
- return this;
- }
-
- /**
- * 起点なる位置を指定する。
- * @param cell 起点とうなるセル
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- * @throws NullPointerException {@literal cell == null.}
- */
- public CellFinder startPosition(final Cell cell) {
- ArgUtils.notNull(cell, "cell");
-
- return startPosition(cell.getColumnIndex(), cell.getRowIndex());
- }
-
- /**
- * 起点なる位置を指定する。
- * @param address セルのアドレス
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- * @throws NullPointerException {@literal address == null.}
- */
- public CellFinder startPosition(final CellPosition address) {
- ArgUtils.notNull(address, "address");
-
- return startPosition(address.getColumn(), address.getRow());
- }
-
- /**
- * 起点となる列を指定する。
- * ただし、行は先頭から検索する。
- * @param column 列番号(0から始まる)
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- * @throws IllegalArgumentException {@literal column < 0}
- */
- public CellFinder startColumn(final int column) {
- ArgUtils.notMin(column, 0, "column");
-
- this.startColumn = column;
- this.startRow = -1;
-
- return this;
- }
-
- /**
- * 起点となる行を指定する。
- * ただし、列は先頭から検索する。
- * @param row 行番号(0から始まる)
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- * @throws IllegalArgumentException {@literal row < 0}
- */
- public CellFinder startRow(final int row) {
- ArgUtils.notMin(row, 0, "row");
-
- this.startColumn = -1;
- this.startRow = row;
-
- return this;
- }
-
- /**
- * 起点となる位置を除外するかどうか。
- * @param excludeStartPosition trueの場合、起点となる位置を除外する
- * @return 自身のインスタンス。メソッドチェーンとして続ける。
- */
- public CellFinder excludeStartPosition(final boolean excludeStartPosition) {
- this.excludeStartPoisition = excludeStartPosition;
- return this;
- }
-
- /**
- * 一致する条件のセルを探す。
- * @return 見つからない場合は、空を返す。
- */
- public Optional<Cell> findOptional() {
-
- return Optional.ofNullable(findCell());
-
- }
-
- /**
- * 一致する条件のセルを探す。
- * ただし、指定したセルが見つからない場合は、例外{@link CellNotFoundException}をスローする。
- * @return
- * @throws CellNotFoundException 指定したセルが見つからない場合
- */
- public Cell findWhenNotFoundException() {
-
- final Cell cell = findCell();
- if(cell == null) {
- throw new CellNotFoundException(sheet.getSheetName(), label);
- }
-
- return cell;
-
- }
-
- /**
- * 一致する条件のセルを探す。
- * @param optional セルが見つからない場合に、nullを返すかどうか。
- * @return 一致したセルを返す。
- * @throws CellNotFoundException 引数「optional=false」のときに、一致するセルが見つからない場合にスローする。
- */
- public Cell find(final boolean optional) {
- if(optional) {
- return findOptional().orElse(null);
- } else {
- return findWhenNotFoundException();
- }
- }
-
- /**
- * 条件に一致するセルを探す
- * @return 見つからない場合は、nullを返す。
- */
- private Cell findCell() {
-
- final int rowStart = startRow < 0 ? 0 : startRow;
- final int columnStart = startColumn < 0 ? 0 : startColumn;
-
- final int maxRow = POIUtils.getRows(sheet);
- for(int i=rowStart; i < maxRow; i++) {
- final Row row = sheet.getRow(i);
- if(row == null) {
- continue;
- }
-
- final int maxCol = row.getLastCellNum();;
- for(int j=columnStart; j < maxCol; j++) {
-
- if(excludeStartPoisition && includeInStartPosition(j, i)) {
- // 開始位置を除外する場合
- continue;
- }
-
- final Cell cell = row.getCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK);
- final String cellValue = POIUtils.getCellContents(cell, config.getCellFormatter());
- if(Utils.matches(cellValue, label, config)) {
- return cell;
- }
- }
- }
-
- return null;
-
- }
-
- /**
- * 現在の位置が検索対象の開始位置を含むかどうか判定します。
- * @param currentColumn 現在の列番号
- * @param currentRow 現在の行番号
- * @return trueの場合含みます。
- */
- private boolean includeInStartPosition(final int currentColumn, final int currentRow) {
-
- if(startColumn >=0 && startRow >= 0
- && currentColumn == startColumn && currentRow == startRow) {
- // 行と列の両方の指定がある場合
- return true;
-
- } else if(startColumn >= 0 && startRow < 0 && currentColumn == startColumn) {
- // 列の指定のみ
- return true;
-
- } else if(startColumn < 0 && startRow >= 0 && currentRow == startRow) {
- // 行の指定のみ
- return true;
-
- }
-
- return false;
-
- }
-
- }