XLSBeansはアノテーションを付与してJavaBeansとExcelをマッピングするライブラリ(プロトタイプ)です。 以下のアノテーションが利用可能です。
読み込むシートをシート番号、シート名、シート名に対する正規表現のいずれかで指定します。クラスに付与します。
/** シート番号で指定する場合 */
@Sheet(number=0)
public class SheetObject {
...
}
/** シート名で指定する場合 */
@Sheet(name="Users")
public class SheetObject {
...
}
/** 正規表現で指定する場合 */
@Sheet(regex="Sheet_[0-9]+")
public class SheetObject {
...
}
正規表現で指定する場合はXLSBeans#loadMultiple()メソッドを用いることでマッチしたシートの情報を一度に取得することができます。
セルの列、行を指定してBeanのプロパティにマッピングします。setterメソッドに対して付与します。
@Sheet(name="Users")
public class SheetObject {
@Cell(column=0, row=0)
public void setTitle(String title){
...
}
}
セルの文字列を指定し、その左右もしくは下側のセルの値をマッピングします。setterメソッドに対して付与します。
@Sheet(name="Users")
public class SheetObject {
@LabelledCell(label="Title", type=LabelledCellType.Right)
public void setTitle(String title){
...
}
}
rangeパラメータを指定すると、typeパラメータの方向に向かって指定したセル数分を検索し、
最初に発見した空白以外のセルの値を取得します。
@Sheet(name="Users")
public class SheetObject {
@LabelledCell(label="Title", type=LabelledCellType.Right, range=3)
public void setTitle(String title){
...
}
}
同じラベルのセルが複数ある場合は、領域の見出しをheaderLabelパラメータで指定します。
headerLabelパラメータで指定されたセルからlabelパラメータで指定されたセルを下方向に検索し、
最初に見つかったセルをラベルセルとして使用します。
@LabelledCell(label="クラス名", type=LabelledCellType.Right, headerLabel="アクション")
public void setActionClassName(String actionClassName){
...
}
@LabelledCell(label="クラス名", type=LabelledCellType.Right, headerLabel="アクションフォーム")
public void setFormClassName(String formClassName){
...
}
セルが見つからなかった場合はエラーとなりますが、optionalパラメータに
trueを指定しておくと、無視して処理を続行します。
シート名をString型のプロパティにマッピングします。
@Sheet(name="Users")
public class SheetObject {
@SheetName
public void setSheetName(String sheetName){
...
}
}
水平方向に連続する行をListまたは配列にマッピングします。
表には最上部にテーブルの名称と列名を記述した行が必要になります。
tableLabelパラメータでテーブルの名称を指定します。
List型または配列の引数を1つだけ取るsetterメソッドに対して付与します。
@Sheet(name="Users")
public class SheetObject {
@HorizontalRecords(tableLabel="ユーザ一覧", recordClass=Record.class)
public void setRecords(List<Record> records){
...
}
}
デフォルトでは行に1つもデータが存在しない場合、そのテーブルの終端となります。
行の一番左側の列のボーダーによってテーブルの終端を検出する方法もあります。
この場合は@HorizontalRecordsのterminalパラメータに
RecordTerminal.Borderを指定してください。
@Sheet(name="Users")
public class SheetObject {
@HorizontalRecords(tableLabel="Horizontal Records", recordClass=Record.class,
terminal=RecordTerminal.Border)
public void setRecords(List<Record> records){
...
}
}
テーブルが他のテーブルと連続しておりterminalパラメータでBorder、
Emptyのいずれを指定しても終端を検出できない場合があります。
このような場合はterminateLabelパラメータで終端を示すセルの文字列を指定します。
@Sheet(name="Users")
public class SheetObject {
@HorizontalRecords(tableLabel="Horizontal Records", recordClass=Record.class,
terminateLabel="Terminate")
public void setRecords(List<Record> records){
...
}
}
セルが見つからなかった場合はエラーとなりますが、optionalパラメータに
trueを指定しておくと、無視して処理を続行します。
垂直方向に連続する列をListまたは配列にマッピングします。
要するに@HorizontalRecordsを縦方向にしたものです。
@HorizontalRecordsと同じくList型の引数を1つだけ取るsetterメソッドに対して付与します。
@Sheet(name="Users")
public class SheetObject {
@VerticalRecords(tableLabel="Vertical Records", recordClass=Record.class)
public void setRecords(List<Record> records){
...
}
}
@HorizontalRecordsと同じくterminalパラメータ、
およびoptionalパラメータを指定することもできます。
@HorizontalRecordsまたは@VerticalRecordsで指定されたクラスのプロパティをカラム名にマッピングします。
setterメソッドに対して付与します。
public class Record {
@Column(columnName="ID")
public void setId(String id){
...
}
}
同じ値がグループごとに結合されているカラムの場合はmergedパラメータをtrueに設定します。
こうしておくと、前の列の値が引き継がれて設定されます。
public class Record {
@Column(columnName="Gender", merged=true)
public void setId(String id){
...
}
}
見出し行が結合され、1つの見出しに対して複数の列が存在する場合はheaderMergedプロパティを使用します。
headerMergedの値には列見出しから何セル分離れているかを指定します。
public class User {
@Column(columnName="連絡先")
public void setMailAddress(String mailAddress){
...
}
@Column(columnName="連絡先", headerMerged=1)
public void setTel(String tel){
...
}
}
@HorozintalRecordもしくは@VerticalRecordでカラム数が可変の場合に、
それらのカラムをMapとして設定します。BeanにはMapを引数に取る
セッターメソッドを用意し、このアノテーションを記述します。
@MapColumns(previousColumnName="名前")
public void setAttributes(Map attributes){
this.attributes = attributes
}
previousColumnNameパラメータで指定された次のカラム以降、カラム名をキーとした
Mapが生成され、Beanにセットされます。
@Sheetを付与したクラス、もしくは@HorizontalRecordsや@VerticalRecords
で指定したレコードクラスのメソッドに付与しておくと、シートの読み込みが終了した時点で呼び出されます。
なお、このアノテーションを付与するメソッドは引数を取らないpublicメソッドである必要があります。
@Sheet(name="Users")
public class SheetObject {
@PostProcess
public void postProcess(){
...
}
}
同一の構造の表がシート内で繰り返し出現する場合に使用します。
tableLabelプロパティで繰り返し部分の見出しラベル、
tableClassプロパティで繰り返し部分の情報を格納するJavaBeanを指定します。
また、bottomプロパティは@IterateTables内で
@HorizontalRecordを使用する場合に、
テーブルの開始位置が@IterateTablesの見出しセルからどれだけ離れているかを指定します。
@Sheet(name="シート名")
public class SheetObject {
@IterateTables(tableLabel="部門情報", tableClass=Unit.class, bottom=2)
public void setUnits(List<Unit> units){
...
}
}
繰り返し部分に対応するJavaBeanでは以下のように@LabelledCellや
@HorizontalRecordなどのアノテーションを使用することができます。
@HorizontalRecordを使用する場合、tableLabelプロパティには
@IterateTablesのtableLabelプロパティで指定したラベルと
同じラベルを指定する必要がある点に注意してください。
public class Unit {
@LabelledCell(label="部門名", type=LabelledCellType.Right)
public void setUnitName(String unitName) {
...
}
@HorizontalRecords(tableLabel="部門情報", recordClass=UnitUser.class)
public void setUnitUsers(List<UnitUser> unitUsers) {
this.unitUsers = unitUsers;
}
}
繰り返し部分に対応するJavaBeanで@HorizontalRecordを使用した場合、
通常の場合と同じく@Columnで列とのマッピングを行います。
public class UnitUser {
@Column(columnName="ID")
public void setId(String id) {
...
}
@Column(columnName="名前")
public void setName(String name) {
...
}
}
以下のようにして読み込みを行います。
SheetObject sheet = new XLSBeans.load(
new FileInputStream("example.xls"), SheetObject.class);
なお、@Cell, @LabelledCell, @Columnアノテーションで
マッピングするプロパティに関しては、現時点ではString型、プリミティブ型、プリミティブ型の
ラッパー型のいずれかである必要があります。より具体的な使用例はexampleフォルダ内のソースコードをご覧ください。
アノテーションだけではなく、外部XMLファイルでマッピングを行うことも可能です。 これはダイナミック・アノテーションという、アノテーションと同様の情報をXMLファイルで定義することで行います。 以下にクラスに対してアノテーションを付与するXMLファイルの例を示します。
<?xml version="1.0" encoding="utf-8"?>
<annotations>
<class name="net.java.amateras.xlsbeans.example.SheetObject">
<annotation name="net.java.amateras.xlsbeans.annotation.Sheet">
<attribute name="name">'Users'</attribute>
</annotation>
</class>
</annotations>
アノテーションの属性値の指定にはOGNL式を使用します。メソッドにアノテーションを付与する場合は次のようになります。
<?xml version="1.0" encoding="utf-8"?>
<annotations>
<class name="net.java.amateras.xlsbeans.example.SheetObject">
<annotation name="net.java.amateras.xlsbeans.annotation.Sheet">
<attribute name="name">'Users'</attribute>
</annotation>
<method name="setTitle">
<annotation name="net.java.amateras.xlsbeans.annotation.LabelledCell">
<attribute name="label">'Title'</attribute>
<attribute name="type">@net.java.amateras.xlsbeans.annotation.LabelledCellType@Right</attribute>
</annotation>
</method>
</class>
</annotations>
XLSBeansでは使用しませんが、フィールドにアノテーションを付与することも可能です。
<?xml version="1.0" encoding="utf-8"?>
<annotations>
<class name="net.java.amateras.xlsbeans.example.SheetObject">
<field name="setTitle">
<annotation name="...">
...
</annotation>
</field>
</class>
</annotations>
外部XMLファイルを使う場合、ハードコードされたアノテーションを外部XMLファイルの内容でオーバーライドすることが可能です。 読み込み時は以下のようにExcelファイルとXMLファイルの両方をXMLBeans#load()メソッドに渡します。
SheetObject sheet = XLSBeans.load(
new FileInputStream("example.xls"),
new FileInputStream("example.xml"), SheetObject.class);
なお、AnnotationReaderクラスを使用することで、XLSBeansのダイナミック・アノテーション 機能を別のプログラムでも利用することが可能です。
// XMLファイルの読み込み
XMLInfo info = XMLLoader.load(new FileInputStream("example.xml"));
// AnnotationReaderのインスタンスを作成
AnnotationReader reader = new AnnotationReader(info);
// SheetObjectクラスに付与されたSheetアノテーションを取得
Sheet sheet = reader.getAnnotation(SheetObject.class, Sheet.class);
ClassやMethod、Fieldオブジェクトから直接アノテーションを
取得する代わりにAnnotationReaderを使えば、XMLで宣言されたアノテーションと、クラスに
埋め込まれているアノテーションを区別せずに取得することができます。AnnotationReaderには
この他にもメソッド、フィールドに付与されたアノテーションを取得するためのメソッドも用意されています。
XLSBeansではFieldProcessorインターフェースを実装したクラスによってアノテーションの処理を行います。
デフォルトではこのドキュメントに記述されているアノテーション用のFieldProcessorが用意されていますが、
独自アノテーションを定義しこれに対応したFieldProcessorをXLSBeansに追加することが可能です。
独自のアノテーションおよび、FieldProcessorをXLSBeansに登録するにはクラスパスのルートに
xlsbeans.properties というプロパティファイルを作成し、
アノテーションのクラス名とFieldProcessor実装クラスのクラス名を以下のように列挙します。
なお、この方法で登録を行う場合、FieldProcessor実装クラスは引数なしのコンストラクタを持っている必要がある点に注意してください。
# アノテーションのクラス名 = FieldProcessorのクラス名 xlsbeans.sample.SampleAnnotation = xlsbeans.sample.SampleFieldProcessor
また、Javaソースコード中で直接ファクトリにFieldProcessor実装クラスを登録することも可能です。
FieldProcessorFactory.registerProcessor(
SampleAnnotation.class, new SampleFieldProcessor());