独自のクラスタイプの対応方法

Excelのセルの値を任意のJavaのクラス型にマッピングする方法を説明します。

  1. CellConverterの実装クラスの作成

  2. CellConverterを作成するためのファクトリクラスの作成

  3. アノテーション @XlsConverter による指定

CellConverterの実装クラスの作成

Excelのセルの値をJavaの任意のクラスにマッピングするには、CellConveterを実装します。

次のように、タイトルとリストが組み合わさったテキストをCustomTypeクラスにマッピングするとします。

マッピング対象の値
タイトル
- リスト1
- リスト2
マッピングするJavaクラス
 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 を継承して実装します。

    • 読み込み時、書き込み時のそれぞれのメソッドを実装します。

      • 文字列に対するマッピングの場合は、TextFormatterparse/format メソッドに委譲します。

      • TextFormatter の実装は、後の CellConverterFactory の作成にて実装します。

    • 実装のサンプルは、パッケージ com.gh.mygreen.xlsmapper.cellconvert.impl 以下に格納されているクラスを参照してください。

CellConverterの実装
 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のエラーメッセージ中で値をフォーマットするときに、オブジェクトを文字列に変換する際に使用します。

CellConverterFactoryの実装
 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 に指定します。

XlsConverterアノテーションによる指定
1public class SampleRecord {
2
3     // 独自のCellConverterFactoryの指定
4     @XlsConverter(CustomCellConverterFactory.class)
5     @XlsColumn(columnName="TODOリスト")
6     private CustomType value;
7}

CellConverterRegistry を使用する方法

作成した CellConverterFactoryの実装クラスのインスタンスを XlsMapperConfg#getConverterRegistry() に登録します。

CellConverterRegistryへの登録
1// 独自のCellConverterFactoryの登録
2XlsMapper mapper = new XlsMapper();
3CellConverterRegistry cellConverterRegistry = mapper.getConiguration().getConverterRegistry();
4cellConverterRegistry.registerConverter(CustomType.class, new CustomCellConverterFactory());