読者です 読者をやめる 読者になる 読者になる

Apache POI Excel 入力規則の読み込み(2)

Apache POI Excel の入力規則を参照するのに、前の記事、
Apache POI Excel入力規則の読み込み(1) - Oboe吹きプログラマの黙示録
このように毎回書いてはいられない。

そこで、XSSFSheetオブジェクトを渡して後から何回でも問い合わせするクラスを書いてみた。
プルダウン-リストによる Excel 入力規則 という限定したものなる。プルダウンリストの入力リストが記述されるのは、必ず縦方向、横方向のどちらかになる。
リストの入力規則の時、Excel は、エリア指定で入力リストはないはずだ。

public final class ExcelListValidaionParser{
	private XSSFSheet sheet;
	private Map<String, XSSFDataValidation> cellToValidateKeyMap;
	private Map<String, List<String>> cellToExplictMap;

	public ExcelListValidaionParser(XSSFSheet sheet){
		this.sheet = sheet;

		cellToValidateKeyMap = sheet.getDataValidations().stream().filter(e->e.getValidationConstraint()
		.getValidationType()==ValidationType.LIST)
		.collect(()->new HashMap<String, XSSFDataValidation>(), (r, validation)->{
			List<String> cellnameList = Arrays.stream(validation.getRegions().getCellRangeAddresses())
			.collect(()->new ArrayList<String>(), (a, b)->{
				for(int row=b.getFirstRow();row <= b.getLastRow(); row++){
					for(int col=b.getFirstColumn();col <= b.getLastColumn(); col++){
						a.add(sheet.getRow(row).getCell(col).getReference());
					}
				}
			}, (a, b)->{ a.addAll(b); });
			cellnameList.stream().distinct().forEach(s->r.put(s, validation));
		}, (r, t)->r.putAll(t));

		cellToExplictMap = cellToValidateKeyMap.keySet().stream()
		.collect(()->new HashMap<String, List<String>>(), (r, s)->{
			String[] exp = cellToValidateKeyMap.get(s).getValidationConstraint().getExplicitListValues();
			String[] ary = exp[0].replaceAll("\\$", "").split(":");
			int startRow = Integer.parseInt(ary[0].replaceAll("[A-Z]+", "")) - 1;
			int endRow   = Integer.parseInt(ary[1].replaceAll("[A-Z]+", "")) - 1;
			int startCol = CellReference.convertColStringToIndex(ary[0].replaceAll("[0-9]+", ""));
			int endCol   = CellReference.convertColStringToIndex(ary[1].replaceAll("[0-9]+", ""));
			if (startRow==endRow){
				r.put(s, IntStream.rangeClosed(startCol, endCol).mapToObj(i->{
						XSSFCell cell = sheet.getRow(startRow).getCell(i);
						if (cell.getCellType()==Cell.CELL_TYPE_NUMERIC){
							Integer data = new Double(cell.getNumericCellValue()).intValue();
							return data.toString();
						}else if(cell.getCellType()==Cell.CELL_TYPE_STRING){
							return cell.getStringCellValue();
						}
						return "";
					}).collect(Collectors.toList())
				);
			}else{
				r.put(s, IntStream.rangeClosed(startRow, endRow).mapToObj(i->{
						XSSFCell cell = sheet.getRow(i).getCell(startCol);
						if (cell.getCellType()==Cell.CELL_TYPE_NUMERIC){
							Integer data = new Double(cell.getNumericCellValue()).intValue();
							return data.toString();
						}else if(cell.getCellType()==Cell.CELL_TYPE_STRING){
							return cell.getStringCellValue();
						}
						return "";
					}).collect(Collectors.toList())
				);
			}
		}, (r, v)->r.putAll(v));
	}

	public List<String> getValidationStringList(String cellstring){
		return cellToExplictMap.containsKey(cellstring) ? cellToExplictMap.get(cellstring) : new ArrayList();
	}
	/**
	 * 入力規則のセルへ格納しようとする値が格納可能であるか否かを返す。
	 * @param cellstring セル名 'A1'書式
	 * @param checkValue 格納しようとする値
	 * @return true=可能、入力規則が無い時も可能
	 */
	public boolean acceptValue(String cellstring, String checkValue){
		List<String> list = getValidationStringList(cellstring);
		if (list.size()==0) return true;
		return list.stream().filter(e->e.equals(checkValue)).findFirst().orElse(null) != null;
	}

	public DataValidationConstraint getDataValidationConstraint(String cellstring){
		XSSFCell cell = sheet.getRow(Integer.parseInt(cellstring.replaceAll("[A-Za-z]+", ""))-1)
		.getCell(CellReference.convertColStringToIndex(cellstring.replaceAll("[0-9]+", "")));
		XSSFDataValidation validation = cellToValidateKeyMap.get(cell.getReference());
		if (validation==null) return null;
		return validation.getValidationConstraint();
	}
}
||