独自のクラスタイプの対応方法
Excelのセルの値を任意のJavaのクラス型にマッピングする方法を説明します。
CellConverterの実装クラスの作成
CellConverterを作成するためのファクトリクラスの作成
アノテーション
@XlsConverter
による指定
CellConverterの実装クラスの作成
Excelのセルの値をJavaの任意のクラスにマッピングするには、CellConveterを実装します。
次のように、タイトルとリストが組み合わさったテキストをCustomTypeクラスにマッピングするとします。
タイトル
- リスト1
- リスト2
1public class CustomType {
2
3 /** タイトル */
4 private String title;
5
6 /** リスト */
7 private List<String> items;
8
9 /**
10 * リストの要素を追加する
11 * @param リストの要素
12 */
13 public void addItem(String item) {
14 if(items == null) {
15 this.items = new ArrayList<>();
16 }
17 this.items.add(item);
18 }
19
20 // setter, getterは省略
21
22 }
インタフェース
com.gh.mygreen.xlsmapper.cellconvert.CellConverter
を実装します。実際には、ユーティリティメソッドがそろっている、
com.gh.mygreen.xlsmapper.cellconverter.BaseCellConverter
を継承して実装します。読み込み時、書き込み時のそれぞれのメソッドを実装します。
文字列に対するマッピングの場合は、
TextFormatter
のparse/format
メソッドに委譲します。TextFormatter
の実装は、後のCellConverterFactory
の作成にて実装します。
実装のサンプルは、パッケージ
com.gh.mygreen.xlsmapper.cellconvert.impl
以下に格納されているクラスを参照してください。
1public class CustomCellConverter extends BaseCellConverter<CustomType> {
2
3 public CustomCellConverter(FieldAccessor field, Configuration config) {
4 super(field, config);
5 }
6
7 /**
8 * セルをJavaのオブジェクト型に変換します。
9 * @param evaluatedCell 数式を評価済みのセル
10 * @param formattedValue フォーマット済みのセルの値。トリミングなど適用済み。
11 * @return 変換した値を返す。
12 * @throws TypeBindException 変換に失敗した場合
13 */
14 @Override
15 protected CustomType parseCell(Cell evaluatedCell, String formattedValue) throws TypeBindException {
16
17 try {
18 // 文字列を変換するときには、TextFormatter#parseに委譲します。
19 return getTextFormatter().parse(formattedValue);
20 } catch(TextParseException e) {
21 throw newTypeBindExceptionOnParse(e, evaluatedCell, formattedValue);
22 }
23
24 }
25
26 /**
27 * 書き込み時のセルに値と書式を設定します。
28 * @param cell 設定対象のセル
29 * @param cellValue 設定対象の値。
30 * @throws TypeBindException 変換に失敗した場合
31 */
32 @Override
33 protected void setupCell(Cell cell, Optional<CustomType> cellValue) throws TypeBindException {
34
35 if(cellValue.isPresent()) {
36 // 文字列を変換するときには、TextFormatter#formatに委譲します。
37 String text = getTextFormatter().format(cellValue.get());
38 cell.setCellValue(text);
39 } else {
40 cell.setCellType(CellType.BLANK);
41 }
42 }
43
44}
CellConverterFactoryの実装クラスの作成
インタフェース
com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactory
を実装する。実際には、サポートメソッドが揃っている
com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactorySupport
を継承し作成します。実装のサンプルは、パッケージ
com.gh.mygreen.xlsmapper.cellconvert.impl
以下に格納されているクラスを参照してください。
文字列に対する処理として、
TexFormatter
を実装します。TextFromatter#parse
は、初期値を@XlsDefaltValue("<初期値>")
で与えられているときに、文字列をオブジェクトに変換する際に使用します。TextFormatter#format
は、Validationのエラーメッセージ中で値をフォーマットするときに、オブジェクトを文字列に変換する際に使用します。
1/**
2 * フィールドに対するセル変換クラスを作成する。
3 * @param accessor フィールド情報
4 * @param config システム設定
5 * @return セルの変換クラス。
6 */
7public class CustomCellConverterFactory extends CellConverterFactorySupport<CustomType>
8 implements CellConverterFactory<CustomType> {
9
10 @Override
11 public CustomCellConverter create(FieldAccessor accessor, Configuration config) {
12 final CustomCellConverter cellConverter = new CustomCellConverter(accessor, config);
13
14 // トリムなどの共通の処理を設定する
15 setupCellConverter(cellConverter, accessor, config);
16
17 return cellConverter;
18 }
19
20 @Override
21 protected void setupCustom(AbstractCellConverter<CustomType> cellConverter, FieldAccessor field, Configuration config) {
22 // 必要があれば実装する。
23 }
24
25 /**
26 * {@link TextFormatter}のインスタンスを作成する。
27 * @param field フィールド情報
28 * @param config システム情報
29 * @return {@link TextFormatter}のインスタンス
30 */
31 @Override
32 protected TextFormatter<CustomType> createTextFormatter(FieldAccessor field, Configuration config) {
33
34 return new TextFormatter<CustomType>() {
35
36 @Override
37 public CustomType parse(String text) throws TextParseException {
38
39 if(StringUtils.isEmpty(text)) {
40 return null;
41 }
42
43 // 改行で分割する
44 String[] split = text.split("\r\n|\n");
45
46 if(split.length <= 1) {
47 // 1行以下しかない場合は、例外とする
48 throw new TextParseException(text, CustomType.class);
49 }
50
51 CustomType data = new CustomType();
52 data.setTitle(split[0]);
53
54 for(int i=1; i < split.length; i++) {
55 String item = split[i];
56 if(item.startsWith("- ")) {
57 // リストの記号を削除する
58 item = item.substring(2);
59 }
60 data.addItem(item);
61 }
62
63 return data;
64 }
65
66 @Override
67 public String format(CustomType value) {
68 if(value == null) {
69 return "";
70 }
71
72 StringBuilder text = new StringBuilder();
73 text.append(value.getTitle())
74 .append("\n");
75
76 // 改行で繋げる
77 text.append(value.getItems().stream().collect(Collectors.joining("\n")));
78 return text.toString();
79 }
80
81 };
82 }
83
84}
作成したCellConverterの使用方法
作成したCellConverterを使用するには、2つの方法があります。
@XlsConverter
を使用する方法
作成した CellConverterFactoryの実装クラスをアノテーション @XlsConverter
に指定します。
1public class SampleRecord {
2
3 // 独自のCellConverterFactoryの指定
4 @XlsConverter(CustomCellConverterFactory.class)
5 @XlsColumn(columnName="TODOリスト")
6 private CustomType value;
7}
CellConverterRegistry を使用する方法
作成した CellConverterFactoryの実装クラスのインスタンスを XlsMapperConfg#getConverterRegistry()
に登録します。
1// 独自のCellConverterFactoryの登録
2XlsMapper mapper = new XlsMapper();
3CellConverterRegistry cellConverterRegistry = mapper.getConiguration().getConverterRegistry();
4cellConverterRegistry.registerConverter(CustomType.class, new CustomCellConverterFactory());