4. セルの書式の指定方法

セルの書式を指定してマッピングする方法を説明します。

  • 読み込み時は、Excelの型とJavaの型が一致する場合、そのままマッピングします。

    • 型が一致しない場合、Excelのセルの値を文字列として取得し、その値をパースしてJavaの型に変換します。

    • 文字列をパースする書式などの指定は、型ごとの専用のアノテーションを付与します。

    • 各型の変換用アノテーションを付与しない場合は、アノテーションの初期値の設定を元に変換されます。

  • 書き込み時は、Javaの型に合ったExcelのセルの型で処理します。

    • テンプレートファイルのセルの型とJavaの型が一致すれば、そのまま書き込みます。 一致しない場合は、付与されたアノテーションに従って書式などを設定します。

    • 各型の変換用アノテーションを付与しない場合は、アノテーションの初期値の設定を元に変換されます。

  • 本ライブラリで対応していないクラスタイプの場合は、変換処理を実装すれば対応できます。

表 - 4.1 ExcelとJavaのマッピング可能な型

Excelの型

Javaの型

ブール
(TRUE/FALSE)
boolean/Boolean

文字列

String
全ての型(ブール/数値/日時/Collection・配列/URL)
数値
(数値/通貨/会計
/パーセンテージ/分数/指数)
byte/short/int/long/float/double/これらのラッパークラス
/java.math.BigDecimal/java.math.BigInteger
日時
(日付/時刻)
java.util.Date/java.util.Calendar
/java.sql.Date/Time/Timestamp
/java.time.LocalDateTime/LocalDate/LocalTime

文字列

配列
/Collection(java.util.List/java.util.Set)
ハイパーリンクを設定したセル
java.net.URI
/com.gh.mygreen.xlsmapper.cellconvert.CellLink(本ライブラリの独自の型)
表 - 4.2 書式を指定するアノテーション

アノテーション

概要

@XlsBooleanConverter

ブール型に対する書式を指定します。

@XlsNumberConverter

数値型に対する書式を指定します。

@XlsDateTimeConverter

日時型に対する書式を指定します。

@XlsEnumConverter

列挙型に対する書式を指定します。

@XlsArrayConverter

Collection型や配列型に対する書式を指定します。

@XlsCellOption

書き込み時のセルの配置位置やインデントなどの書式を指定します。

注釈

書式指定用のアノテーションは、セルをマッピングするアノテーション @XlsCell@XlsLabelledCell@XlsArrayCells@XlsLabelledArrayCells@XlsColumn@XlsMapColumns@XlsArrayColumns を付与しているプロパティに対して有効になります。

4.1. @XlsBooleanConverter

Excelのセルの種類が「ブール型」以外の場合に、Javaの「boolean/Boolean」にマッピング規則を定義します。

単純に「true、false」以外に、「○、×」とのマッピングも可能となります。

4.1.1. 読み込み時の値の指定

属性 loadForTrueloadForFalse で読み込み時のtrueまたはfalseと判断するの候補の値を指定します。

  • 属性loadForTrueとloadForFalseの値に重複がある場合、loadForTrueの定義が優先されまます。

  • 属性laodForTrueを指定しない場合、デフォルトで「"true", "1", "yes", "on", "y", "t"」が設定されます。

  • 属性loadForFalseを指定しない場合、デフォルトで「"false", "0", "no", "off", "f", "n"」が設定されます。

  • 属性 ignoreCase の値をtrueにすると、読み込み時に大文字、小文字の区別なく候補の値と比較します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class SampleRecord {

    // boolean型の読み込み時のtrueとfalseの値の変換規則を指定します。
    @XlsColumn(columnName="ステータス")
    @XlsBooleanConverter(
            loadForTrue={"○", "有効", "レ"},
            loadForFalse={"×", "無効", "-", ""})
    private boolean availaled;

    // 読み込み時の大文字・小文字の区別を行わない
    @XlsColumn(columnName="チェック")
    @XlsBooleanConverter(
          loadForTrue={"OK"},
          loadForFalse={"NO"},
          ignoreCase=true)
    private Boolean checked;
}

4.1.2. 書き込み時の値の指定

属性 saveAsTruesaveAsFalse で書き込み時のtrueまたはfalse値に該当する文字を指定します。

  • 属性saveAsTrueを指定しない場合は、デフォルトで"true"が設定され、セルのタイプもブール型になります。

  • 属性saveAsFalseを指定しない場合は、デフォルトで"false"が設定され、セルのタイプもブール型になります。

  • 読み込みと書き込みの両方を行う場合、属性loadForTrueとloadForFalseの値に属性saveAsTrueとsaveAsFalseの値を含める必要があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class SampleRecord {

    // boolean型の書き込み時のtrueとfalseの値の変換規則を指定します。
    @XlsColumn(columnName="ステータス")
    @XlsBooleanConverter(
            loadForTrue={"○", "有効", "レ"}, // 読み書きの両方を行う場合、書き込む値を含める必要がある。
            loadForFalse={"×", "無効", "-", ""},
            saveAsTrue="○",
            saveAsFalse="-")
    )
    private boolean availaled;

}

4.1.3. 変換に失敗した際の処理

読み込み時にtrueまたはfalseに変換できない場合、例外TypeBindExceptionが発生します。

  • 属性 failToFalse をtrueに設定することで、変換できない場合に強制的に値をfalseとして読み込み、例外を発生しなくできます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class SampleRecord {

    // 読み込み時に変換できない場合に、強制的に値をfalseとして読み込みます。
    @XlsColumn(columnName="ステータス")
    @XlsBooleanConverter(
            loadForTrue={"○", "有効", "レ"},
            loadForFalse={"×", "無効", "-", ""},
            failToFalse=true)
    private boolean availaled;

}

4.2. @XlsNumberConverter

数値型に対する変換規則を指定する際に利用するアノテーションです。

対応するJavaの型は次の通り。

  • byte/short/int/long/float/doubleのプリミティブ型とそのラッパークラス。

  • java.math.BigDecimal / java.math.BigInteger

4.2.1. 読み込み時の書式の指定

読み込み時にセルの種類が数値(通貨、会計、パーセンテージ、分数、指数)ではない場合、 文字列として値を取得し、その値を属性 javaPattern で指定した書式に従いパースし、Javaの数値型に変換します。

  • 属性 javaPattern で読み込み時の書式を指定します。 [ver1.1+]

    • Javaのクラス java.text.DecimalFormat で解釈可能な書式を設定します。

    • ver1.0以前は、属性patternを使っていましたが、廃止になりました。

  • 属性 locale でロケールを指定します。

    • 言語コードのみを指定する場合、'ja'の2桁で指定します。

    • 言語コードと国コードを指定する場合、'ja _JP'のようにアンダーバーで区切り指定します。

  • 属性 currency で通貨コード(ISO-4217コード)を指定します。

    • Javaのクラス java.util.Currency で解釈可能なコードを指定します。

  • 書式に合わない値をパースした場合、例外 TypeBindException が発生します。

コード - 4.2.1 読み込み時の指定方法
1
2
3
4
5
6
7
public class SampleRecord {

    @XlsColumn(columnName="給与")
    @XlsNumberConverter(javaPattern="\u00A4\u00A4 #,##0.0000", locale="ja_JP", currency="USD")
    private double salary;

}

4.2.2. 書き込み時の書式の指定

書き込み時の書式は、基本的にテンプレートファイルに設定してある値を使用します。 また、アノテーションでも直接指定することができます。

  • 属性 excelPattern で書き込み時の書式を指定します。 [ver1.1+]

    • Excelの書式を指定する場合は、 ユーザ定義 の形式で指定する必要があります。

コード - 4.2.2 書き込み時の指定方法
1
2
3
4
5
6
7
public class SampleRecord {

    @XlsColumn(columnName="給与")
    @XlsNumberConverter(javaPattern="[$-411]\"¥\"#,##0.0000")
    private double salary;

}

注釈

テンプレートファイルのセルの書式を「標準」に設定している場合に書き込むと、 書式が「標準」設定の全てのセルの書式が書き換わってしまいます。

そのため、日付や数値などの書式が必要な場合は、テンプレートファイルで予め書式を設定しておくか、 アノテーションの属性excelPatternで書式を指定しておいてください。

4.2.3. 有効桁数の指定

Excel内部とJavaの数値は、表現可能な有効桁数が異なります。

そのため、特に読み込み時などExcelの仕様に合わせてJavaのクラスに指定することが可能です。

  • 属性 precision で有効桁数を指定します。 [ver0.5+]

    • 0以下の値を設定すると、桁数の指定を省略したことになり、無制限になります。

注釈

Excelでは有効桁数が15桁であるため、Javaのlong型など15桁を超える表現が可能な数値を書き込んだ場合、数値が丸められるため注意してください。

  • 例えば、long型の19桁の数値 1234567890123456789 を書き込んだ場合、16桁以降の値が丸められ 1234567890123450000 として書き込まれます。

  • Excelの仕様については、Excel の仕様と制限 を参照してください。

4.3. @XlsDateTimeConverter

日時型に対する変換規則を指定する際に利用するアノテーションです。

対応するJavaのクラスタイプと、アノテーションを付与していないときに適用されるの標準の書式は以下の通りです。

表 - 4.3.1 対応する日時のクラスタイプと標準の書式

クラスタイプ

標準の書式

java.util.Date

yyyy-MM-dd HH:mm:ss

java.util.Calendar

yyyy-MM-dd HH:mm:ss

java.sql.Date

yyyy-MM-dd

java.sql.Time

HH:mm:ss

java.sql.Timestamp

yyyy-MM-dd HH:mm:ss.SSS

java.time.LocalDateTime

uuuu-MM-dd HH:mm:ss

java.time.LocalDate

uuuu-MM-dd

java.time.LocalTime

HH:mm:ss

4.3.1. 読み込み時の書式の指定

読み込み時にセルの種類が日付、時刻ではない場合、文字列として値を取得し、 その値を属性 javaPattern で指定した書式に従いパースし、Javaの日時型に変換します。

  • 属性 javaPattern で書式を指定します。 [ver1.1+]

  • 属性 locale でロケールを指定します。

    • 言語コードのみを指定する場合、'ja'の2桁で指定します。

    • 言語コードと国コードを指定する場合、'ja _JP'のようにアンダーバーで区切り指定します。

  • 属性 lenient で、日付/時刻の解析を厳密に行わないか指定します。

    • trueの厳密に解析を行いません。falseの場合厳密に解析を行います。

  • 属性 timezone でタイムゾーンを指定します。

    • Asia/Tokyo, GMT, GMT+09:00などの値を指定します。

    • ただし、オフセットを持たないクラスタイプ「LocalDateTime, LocalDate, LocalTime」の時は、指定しても意味がありません。

  • 書式に合わない値をパースした場合、例外 TypeBindException が発生します。

コード - 4.3.1 読み込み時の書式の指定
1
2
3
4
5
6
7
8
public class SampleRecord {

    @XlsColumn(columnName="有効期限")
    @XlsDateTimeConverter(javaPattern="yyyy年MM月dd日 HH時mm分ss秒", locale="ja_JP",
            lenient=true)
    private Date expired;

}

注釈

読み込み時のセルの値が属性javaPatternで指定した書式に一致していなくても、セルのタイプが日付または時刻の場合は、例外の発生なく読み込むことができます。 セルの表示形式の分類が文字列の場合は、アノテーション @XlsDateTimeConverter(javaPattern="<書式>") で指定した書式に従い処理されます。

ただし、型変換用のアノテーション @XlsDateTimeConverter を付与しない場合は、Javaの型ごとに上記の書式が標準で適用されます。[ver0.5+]

4.3.2. 書き込み時の書式の指定

書き込み時の書式は、基本的にテンプレートファイルに設定してある値を使用します。 また、アノテーションでも直接指定することができます。

  • 属性 excelPattern で書き込み時の書式を指定します。 [ver1.1+]

    • Excelの書式を指定する場合は、 ユーザ定義 の形式で指定する必要があります。

コード - 4.3.2 書き込み時の書式の指定
1
2
3
4
5
6
7
public class SampleRecord {

    @XlsColumn(columnName="有効期限")
    @XlsDateTimeConverter(excelPattern="[$-411]yyyy\"年\"mm\"月\"dd\"日\" hh\"時\"mm\"分\"ss\"秒\"")
    private Date expired;

}

注釈

テンプレートファイルのセルの書式を「標準」に設定している場合に書き込むと、 書式が「標準」設定の全てのセルの書式が書き換わってしまいます。

そのため、日付や数値などの書式が必要な場合は、テンプレートファイルで予め書式を設定しておくか、 アノテーションの属性excelPatternで書式を指定しておいてください。

4.4. @XlsEnumConverter

列挙型の変換規則の設定を行います。

4.4.1. 基本的な使い方

セルの値と列挙型の要素の値をマッピングさせます。

要素の値とは、 Enum#name() の値です。

  • 属性 ignoreCase の値をtrueにすると、読み込み時に大文字/小文字の区別なく変換します。

コード - 4.4.1 列挙型の変換規則の指定方法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class SampleRecord {

    // 列挙型のマッピング
    @XlsColumn(columnName="権限")
    @XlsEnumConverter(ignoreCase=true)
    private RoleType role;

}

// 列挙型の定義
public enum RoleType {
    Normal, Admin;
}

4.4.2. 別名でマッピングする場合

別名でマッピングする場合、属性 aliasMethod で列挙型の要素の別名を取得するメソッド名を指定します。

コード - 4.4.2 列挙型を別名でマッピングする方法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SampleRecord {

    // 別名による列挙型のマッピング
    @XlsColumn(columnName="権限")
    @XlsEnumConverter(aliasMethod="localeName")
    private RoleType role;

}

// 列挙型の定義
public enum RoleType {
    Normal("一般権限"), Admin("管理者権限");

    // 別名の設定
    private String localeName;

    private RoleType(String localeName) {
        this.localeName = localeName;
    }

    // 別名の取得用メソッド
    public String localeName() {
        return this.localeName;
    }

}

4.5. @XlsArrayConverter

配列またはCollection型(List, Set)の変換規則の設定を行います。

4.5.1. 基本的な使い方

Collection型のインタフェースを指定している場合、読み込み時のインスタンスは次のクラスが指定されます。

  • java.util.List の場合、java.util.ArrayList がインスタンスのクラスとなります。

  • java.util.Set の場合、java.util.LinkedHashSet がインスタンスのクラスとなります。

配列、またはCollection型の要素で指定可能なクラス型は、次の通りです。 任意のクラス型に対応する場合は、属性 elementConverter で変換処理クラスを指定してください。

  • String型

  • プリミティブ型「boolean/char/byte/short/int/long/float/double」と、そのラッパークラス。

  • java.math.BigDecimal / java.math.BigInteger

文字列のセルに対して、任意の区切り文字を指定し、配列やListに対してマッピングします。

  • 属性 separator で区切り文字を指定します。

    • 区切り文字の初期値は、半角カンマ(,)です。

  • トリム用アノテーション @XlsTrim を付与し、トリム処理を有効にしている設定の場合、区切った項目にもトリム処理が適用されます。 [ver0.5+]

  • 属性 ignoreEmptyElement の値をtrueに設定していると、トリム処理によって項目が空文字となった場合、その項目は無視されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class SampleRecord {

    // 区切り文字の指定
    @XlsColumn(columnName="リスト")
    @XlsArrayConverter(separator="\n")
    private List<String> list;

    // 要素のトリム処理を指定する
    @XlsColumn(columnName="配列")
    @XlsTrim    // 区切った配列の要素にもトリムが適用されます。
    @XlsArrayConverter(separator=",")
    private int[] array;

}

4.5.2. 空の要素を無視する場合

属性 ignoreEmptyElement で、区切った項目の値が空文字の場合、無視するか指定します。

例えば、区切り文字","のとき、セルの値が "a,,b" の場合、trueを設定すると ["a", "b"] として読み込みます。

書き込み時も同様に、値が空またはnullの項目を無視します。

1
2
3
4
5
6
7
8
public class SampleRecord {

    // 空の要素を無視する場合
    @XlsColumn(columnName="集合")
    @XlsArrayConverter(ignoreEmptyElement=true)
    private Set<Integer> set;

}

4.5.3. 要素の値を変換するクラスを指定する

属性 elementConverter で要素の値を変換するクラスを指定することができます。 [ver1.1+]

変換するクラスは、インタフェース com.gh.mygreen.xlsmapper.cellconvert.ElementConverter を実装している必要があります。 標準では、com.gh.mygreen.xlsmapper.cellconvert.DefaultElementConverter が使用され、基本的な型のみサポートしています。

インスタンスは、システム設定「beanFactory」経由で作成されるため、SpringFrameworkのコンテナからインスタンスを取得 することもできます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 変換用クラス
public class CustomElementConverter implements ElementConverter<User> {

    @Override
    public User convertToObject(final String str, final Class<User> targetClass) throws ConversionException {
        //TODO: 文字列 => オブジェクトに変換する処理
    }

    @Override
    public String convertToString(final User value) {
        //TODO: オブジェクト => 文字列に変換する処理
    }

}

// レコード用クラス
public class SampleRecord {

    // 任意のクラス型の要素の値を変換するElementConverterを指定します。
    @XlsColumn(columnName="リスト")
    @XlsArrayConverter(elementConverter=CustomElementConverter.class)
    private List<User> list;

}

4.6. @XlsCellOption

書き込み時のセルの配置位置やインデントなどの書式を指定します。

書き込み時は、テンプレート側のシートでセルの位置などを指定しておけば、それらの設定が引き継がれます。

ただし、アノテーションを付与することで、テンプレート側のシートと異なる設定に変更することもできます。

  • 属性 wrapText の値がtrueの場合、強制的にセルの内の文字表示の設定「折り返して全体を表示する」が有効になります。

    • falseの場合、テンプレートとなるセルの設定を引き継ぎます。

  • 属性 shrinkToFit の値がtrueの場合、強制的にセル内の文字表示の設定「縮小して全体を表示する」が有効になります。

    • falseの場合、テンプレートとなるセルの設定を引き継ぎます。

  • 属性 indent でインデントを指定することができます。

    • インデントが指定可能な横位置(左詰め/右詰め/均等割り付け)のときのみ有効になります。

    • -1 以下の時は、現在の設定を引き継ぎます。

  • 属性 horizontalAlign でセルの横位置を指定することができます。

  • 属性 verticalAlign でセルの縦位置を指定することができます。

コード - 4.6.1 セルの配置の指定
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class SampleRecord {

    // 「縮小して全体を表示する」が有効になる。
    @XlsColumn(columnName="ID")
    @XlsCellOption(wrapText=true)
    private int id;

    //「折り返して全体を表示する」が有効になる。
    @XlsColumn(columnName="名前")
    @XlsCellOption(shrinkToFit=true)
    private String name;

    // セルの横位置、縦位置の指定
    @XlsColumn(columnName="備考")
    @XlsCellOption(horizontalAlign=HorizontalAlign.Center, verticalAlign=VerticalAlign.Top)
    private String comment;
}

注釈

Excelの仕様上、設定「折り返して全体を表示する」と「縮小して全体を表示する」は、二者択一であるため、両方の設定を有効にすることはできません。 もし、属性wrapTextとshrinkToFitの値をtrueに設定した場合、shrinkToFitの設定が優先され、「縮小して全体を表示する」が有効になります。

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

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

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

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

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

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

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

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

コード - 4.7.1 マッピング対象の値
タイトル
- リスト1
- リスト2
コード - 4.7.2 マッピングするJavaクラス
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CustomType {

     /** タイトル */
     private String title;

     /** リスト */
     private List<String> items;

     /**
      * リストの要素を追加する
      * @param リストの要素
      */
     public void addItem(String item) {
         if(items == null) {
             this.items = new ArrayList<>();
         }
         this.items.add(item);
     }

     // setter, getterは省略

 }
  • インタフェース com.gh.mygreen.xlsmapper.cellconvert.CellConverter を実装します。

    • 実際には、ユーティリティメソッドがそろっている、com.gh.mygreen.xlsmapper.cellconverter.BaseCellConverter を継承して実装します。

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

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

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

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

コード - 4.7.3 CellConverterの実装
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class CustomCellConverter extends BaseCellConverter<CustomType> {

    public CustomCellConverter(FieldAccessor field, Configuration config) {
        super(field, config);
    }

    /**
     * セルをJavaのオブジェクト型に変換します。
     * @param evaluatedCell 数式を評価済みのセル
     * @param formattedValue フォーマット済みのセルの値。トリミングなど適用済み。
     * @return 変換した値を返す。
     * @throws TypeBindException 変換に失敗した場合
     */
    @Override
    protected CustomType parseCell(Cell evaluatedCell, String formattedValue) throws TypeBindException {

        try {
            // 文字列を変換するときには、TextFormatter#parseに委譲します。
            return getTextFormatter().parse(formattedValue);
        } catch(TextParseException e) {
            throw newTypeBindExceptionOnParse(e, evaluatedCell, formattedValue);
        }

    }

    /**
     * 書き込み時のセルに値と書式を設定します。
     * @param cell 設定対象のセル
     * @param cellValue 設定対象の値。
     * @throws TypeBindException 変換に失敗した場合
     */
    @Override
    protected void setupCell(Cell cell, Optional<CustomType> cellValue) throws TypeBindException {

        if(cellValue.isPresent()) {
            // 文字列を変換するときには、TextFormatter#formatに委譲します。
            String text = getTextFormatter().format(cellValue.get());
            cell.setCellValue(text);
        } else {
            cell.setCellType(CellType.BLANK);
        }
    }

}

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

コード - 4.7.4 CellConverterFactoryの実装
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
 * フィールドに対するセル変換クラスを作成する。
 * @param accessor フィールド情報
 * @param config システム設定
 * @return セルの変換クラス。
 */
public class CustomCellConverterFactory extends CellConverterFactorySupport<CustomType>
            implements CellConverterFactory<CustomType> {

    @Override
    public CustomCellConverter create(FieldAccessor accessor, Configuration config) {
        final CustomCellConverter cellConverter = new CustomCellConverter(accessor, config);

        // トリムなどの共通の処理を設定する
        setupCellConverter(cellConverter, accessor, config);

        return cellConverter;
    }

    @Override
    protected void setupCustom(AbstractCellConverter<CustomType> cellConverter, FieldAccessor field, Configuration config) {
        // 必要があれば実装する。
    }

    /**
     * {@link TextFormatter}のインスタンスを作成する。
     * @param field フィールド情報
     * @param config システム情報
     * @return {@link TextFormatter}のインスタンス
     */
    @Override
    protected TextFormatter<CustomType> createTextFormatter(FieldAccessor field, Configuration config) {

        return new TextFormatter<CustomType>() {

            @Override
            public CustomType parse(String text) throws TextParseException {

                if(StringUtils.isEmpty(text)) {
                    return null;
                }

                // 改行で分割する
                String[] split = text.split("\r\n|\n");

                if(split.length <= 1) {
                    // 1行以下しかない場合は、例外とする
                    throw new TextParseException(text, CustomType.class);
                }

                CustomType data = new CustomType();
                data.setTitle(split[0]);

                for(int i=1; i < split.length; i++) {
                    String item = split[i];
                    if(item.startsWith("- ")) {
                        // リストの記号を削除する
                        item = item.substring(2);
                    }
                    data.addItem(item);
                }

                return data;
            }

            @Override
            public String format(CustomType value) {
                if(value == null) {
                    return "";
                }

                StringBuilder text = new StringBuilder();
                text.append(value.getTitle())
                    .append("\n");

                // 改行で繋げる
                text.append(value.getItems().stream().collect(Collectors.joining("\n")));
                return text.toString();
            }

        };
    }

}

4.7.3. 作成したCellConverterの使用方法

作成したCellConverterを使用するには、2つの方法があります。

4.7.3.1. @XlsConverter を使用する方法

作成した CellConverterFactoryの実装クラスをアノテーション @XlsConverter に指定します。

コード - 4.7.5 XlsConverterアノテーションによる指定
1
2
3
4
5
6
7
public class SampleRecord {

     // 独自のCellConverterFactoryの指定
     @XlsConverter(CustomCellConverterFactory.class)
     @XlsColumn(columnName="TODOリスト")
     private CustomType value;
}

4.7.3.2. CellConverterRegistry を使用する方法

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

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