超簡単Excel読み書きライブラリ xlbean のご紹介 

Excelの表データを直感的かつ簡単にJavaプログラム上で扱うためのライブラリ [**xlbean**](https://github.com/aji3/xlbean) を作成し、
オープンソースとして公開しました。

個人的には、システム開発をやっていてよく見かける作業を
ほどよくサポートできるツールになったかと思っています。

よろしければみなさんにも利用していただき、
世の中のシステム開発が少しでも楽になればうれしいです。

# 特徴をひとことで

**「Excelファイル自体に読みこみ先のデータ構造を定義する」**です。
まずは利用イメージをご覧ください。

## Excelの読み込み

以下の2ステップで、Excelの表データをList形式で取得できます。

### STEP 1. Excelファイルの定義

下記のようにシートを定義します。 (実Excelファイルは[こちら](https://github.com/aji3/xlbean/blob/master/example/presidents.xlsx)をダウンロードしてください。)

<img width="887" alt="excel_sample.PNG" src="https://user-images.githubusercontent.com/23234132/29244923-4f5cba56-8002-11e7-929d-617a9ea38d83.png">

#### TODO
1. **"表名#列名"** の形式で表の列名を指定
2. **"表名#~(チルダ)"** の形式で読み込み開始行を指定
3. **"####"** をA1に書き込み対象のシートを指定

### STEP 2. Javaコードの作成

```java:サンプルコード
InputStream in = new FileInputStream("example/presidents.xlsx");
XlBeanReader reader = new XlBeanReader();
XlBean bean = reader.read(in);

List<XlBean> list = bean.beans("presidents");
list.forEach(System.out::println);
```
### 実行結果

実行すると、こうなります！

```java:実行結果
{name=John F. Kennedy, inOfficeTo=1963-11-22T00:00:00.000, numberOfDaysInOffice=1036.0, dateOfBirth=1917-05-29T00:00:00.000, inOfficeFrom=1961-01-20T00:00:00.000, stateOfBirth=Massachusetts}
{name=Lyndon B. Johnson, inOfficeTo=1969-01-20T00:00:00.000, numberOfDaysInOffice=1886.0, dateOfBirth=1908-08-27T00:00:00.000, inOfficeFrom=1963-11-22T00:00:00.000, stateOfBirth=Texas}
{name=Richard M. Nixon, inOfficeTo=1974-08-09T00:00:00.000, numberOfDaysInOffice=2027.0, dateOfBirth=1913-01-09T00:00:00.000, inOfficeFrom=1969-01-20T00:00:00.000, stateOfBirth=California}
{name=Gerald R. Ford, inOfficeTo=1977-01-20T00:00:00.000, numberOfDaysInOffice=895.0, dateOfBirth=1913-07-14T00:00:00.000, inOfficeFrom=1974-08-09T00:00:00.000, stateOfBirth=Nebraska}
{name=Jimmy Carter, inOfficeTo=1981-01-20T00:00:00.000, numberOfDaysInOffice=1461.0, dateOfBirth=1924-10-01T00:00:00.000, inOfficeFrom=1977-01-20T00:00:00.000, stateOfBirth=Georgia}
{name=Ronald Reagan, inOfficeTo=1989-01-20T00:00:00.000, numberOfDaysInOffice=2922.0, dateOfBirth=1911-02-06T00:00:00.000, inOfficeFrom=1981-01-20T00:00:00.000, stateOfBirth=Illinois}
{name=George H. W. Bush, inOfficeTo=1993-01-20T00:00:00.000, numberOfDaysInOffice=1461.0, dateOfBirth=1924-06-12T00:00:00.000, inOfficeFrom=1989-01-20T00:00:00.000, stateOfBirth=Massachusetts}
{name=Bill Clinton, inOfficeTo=2001-01-20T00:00:00.000, numberOfDaysInOffice=2922.0, dateOfBirth=1946-08-19T00:00:00.000, inOfficeFrom=1993-01-20T00:00:00.000, stateOfBirth=Arkansas}
{name=George W. Bush, inOfficeTo=2009-01-20T00:00:00.000, numberOfDaysInOffice=2922.0, dateOfBirth=1946-07-06T00:00:00.000, inOfficeFrom=2001-01-20T00:00:00.000, stateOfBirth=Connecticut}
{name=Barack Obama, inOfficeTo=2017-01-20T00:00:00.000, numberOfDaysInOffice=2922.0, dateOfBirth=1961-08-04T00:00:00.000, inOfficeFrom=2009-01-20T00:00:00.000, stateOfBirth=Hawaii}
{name=Donald Trump, dateOfBirth=1946-06-14T00:00:00.000, inOfficeFrom=2017-01-20T00:00:00.000, stateOfBirth=New York}
```

#### ポイント

- 表データは、各列をBeanの要素とするListとして取得できる
- スプレッドシート関数も解釈してくれる（サンプルのExcelファイルを見ていただくとわかりますが、*# of days in office* 列はスプレッドシート関数で計算しています）


# もう少しご紹介

ここで興味を持っていただいた方に、もう少し特徴をご紹介します。
単なる表データだけでなく、ネストを含むさまざまな構造が表現可能です。

## さまざまなデータ構造

さきほどのExcelを、下記の通り拡張します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172112/9cb3cc35-5e89-900c-b67c-5fd03a081518.png)

Javaコードはこのようになります。

```Java
InputStream in = new FileInputStream("example/presidents.xlsx");
XlBeanReader reader = new XlBeanReader();
XlBean bean = reader.read(in);

System.out.println(bean.get("name"));// United States of America
System.out.println(bean.bean("stats").get("totalArea"));// 9833520.0
System.out.println(bean.bean("stats").get("gdp"));// 18558000000000000
```

#### ポイント

- 表だけではなく、単項目の定義が可能
- ネストされたBeanもOK

## 読み込んだ後、便利に使いたい

このExcelに対して、下記のようなDTOクラスを定義します。

```Java
public class Country {
    private String name;
    private Stats stats;
    private List<President> presidents;
    // Getter/Setter/toStringは省略
}

public class President {
    private String name;
    private LocalDate dateOfBirth;
    private String stateOfBirth;
    private Date inOfficeFrom;
    private LocalDateTime inOfficeTo;
    private int numberOfDaysInOffice;
    // Getter/Setter/toStringは省略
}

public class Stats {
    private Long totalArea;
    private BigDecimal gdp;
    // Getter/Setter/toStringは省略
}
```

この時、こんなコードが書けます。

```Java
InputStream in = new FileInputStream("example/presidents.xlsx");
XlBeanReader reader = new XlBeanReader();
XlBean bean = reader.read(in);

// 単一Beanの変換
Stats stats = bean.beanOf("stats", Stats.class);
System.out.println(stats);
// Stats [totalArea=9833520, gdp=18558000000000000]

// List単位の変換
List<President> presidents = bean.listOf("presidents", President.class);
System.out.println(presidents);
// [President [name=John F. Kennedy, dateOfBirth=1917-05-29, stateOfBirth=Massachusetts, inOfficeFrom=Fri Jan 20 00:00:00 JST 1961, inOfficeTo=1963-11-22T00:00, numberOfDaysInOffice=1036], President [name=Lyndon B. Johnson, dateOfBirth=1908-08-27, stateOfBirth=Texas, inOfficeFrom=Fri Nov 22 00:00:00 JST 1963, inOfficeTo=1969-01-20T00:00, numberOfDaysInOffice=1886], President [name=Richard M. Nixon, dateOfBirth=1913-01-09, stateOfBirth=California, inOfficeFrom=Mon Jan 20 00:00:00 JST 1969, inOfficeTo=1974-08-09T00:00, numberOfDaysInOffice=2027], President [name=Gerald R. Ford, dateOfBirth=1913-07-14, stateOfBirth=Nebraska, inOfficeFrom=Fri Aug 09 00:00:00 JST 1974, inOfficeTo=1977-01-20T00:00, numberOfDaysInOffice=895], President [name=Jimmy Carter, dateOfBirth=1924-10-01, stateOfBirth=Georgia, inOfficeFrom=Thu Jan 20 00:00:00 JST 1977, inOfficeTo=1981-01-20T00:00, numberOfDaysInOffice=1461], President [name=Ronald Reagan, dateOfBirth=1911-02-06, stateOfBirth=Illinois, inOfficeFrom=Tue Jan 20 00:00:00 JST 1981, inOfficeTo=1989-01-20T00:00, numberOfDaysInOffice=2922], President [name=George H. W. Bush, dateOfBirth=1924-06-12, stateOfBirth=Massachusetts, inOfficeFrom=Fri Jan 20 00:00:00 JST 1989, inOfficeTo=1993-01-20T00:00, numberOfDaysInOffice=1461], President [name=Bill Clinton, dateOfBirth=1946-08-19, stateOfBirth=Arkansas, inOfficeFrom=Wed Jan 20 00:00:00 JST 1993, inOfficeTo=2001-01-20T00:00, numberOfDaysInOffice=2922], President [name=George W. Bush, dateOfBirth=1946-07-06, stateOfBirth=Connecticut, inOfficeFrom=Sat Jan 20 00:00:00 JST 2001, inOfficeTo=2009-01-20T00:00, numberOfDaysInOffice=2922], President [name=Barack Obama, dateOfBirth=1961-08-04, stateOfBirth=Hawaii, inOfficeFrom=Tue Jan 20 00:00:00 JST 2009, inOfficeTo=2017-01-20T00:00, numberOfDaysInOffice=2922], President [name=Donald Trump, dateOfBirth=1946-06-14, stateOfBirth=New York, inOfficeFrom=Fri Jan 20 00:00:00 JST 2017, inOfficeTo=null, numberOfDaysInOffice=0]]

// ネストされたBeanの変換
Country usa = bean.of(Country.class);
System.out.println(usa);
// Country [name=United States of America, stats=Stats [totalArea=9833520, gdp=18558000000000000], presidents=[President [name=John F. Kennedy, dateOfBirth=1917-05-29, stateOfBirth=Massachusetts, inOfficeFrom=Fri Jan 20 00:00:00 JST 1961, inOfficeTo=1963-11-22T00:00, numberOfDaysInOffice=1036], President [name=Lyndon B. Johnson, dateOfBirth=1908-08-27, stateOfBirth=Texas, inOfficeFrom=Fri Nov 22 00:00:00 JST 1963, inOfficeTo=1969-01-20T00:00, numberOfDaysInOffice=1886], President [name=Richard M. Nixon, dateOfBirth=1913-01-09, stateOfBirth=California, inOfficeFrom=Mon Jan 20 00:00:00 JST 1969, inOfficeTo=1974-08-09T00:00, numberOfDaysInOffice=2027], President [name=Gerald R. Ford, dateOfBirth=1913-07-14, stateOfBirth=Nebraska, inOfficeFrom=Fri Aug 09 00:00:00 JST 1974, inOfficeTo=1977-01-20T00:00, numberOfDaysInOffice=895], President [name=Jimmy Carter, dateOfBirth=1924-10-01, stateOfBirth=Georgia, inOfficeFrom=Thu Jan 20 00:00:00 JST 1977, inOfficeTo=1981-01-20T00:00, numberOfDaysInOffice=1461], President [name=Ronald Reagan, dateOfBirth=1911-02-06, stateOfBirth=Illinois, inOfficeFrom=Tue Jan 20 00:00:00 JST 1981, inOfficeTo=1989-01-20T00:00, numberOfDaysInOffice=2922], President [name=George H. W. Bush, dateOfBirth=1924-06-12, stateOfBirth=Massachusetts, inOfficeFrom=Fri Jan 20 00:00:00 JST 1989, inOfficeTo=1993-01-20T00:00, numberOfDaysInOffice=1461], President [name=Bill Clinton, dateOfBirth=1946-08-19, stateOfBirth=Arkansas, inOfficeFrom=Wed Jan 20 00:00:00 JST 1993, inOfficeTo=2001-01-20T00:00, numberOfDaysInOffice=2922], President [name=George W. Bush, dateOfBirth=1946-07-06, stateOfBirth=Connecticut, inOfficeFrom=Sat Jan 20 00:00:00 JST 2001, inOfficeTo=2009-01-20T00:00, numberOfDaysInOffice=2922], President [name=Barack Obama, dateOfBirth=1961-08-04, stateOfBirth=Hawaii, inOfficeFrom=Tue Jan 20 00:00:00 JST 2009, inOfficeTo=2017-01-20T00:00, numberOfDaysInOffice=2922], President [name=Donald Trump, dateOfBirth=1946-06-14, stateOfBirth=New York, inOfficeFrom=Fri Jan 20 00:00:00 JST 2017, inOfficeTo=null, numberOfDaysInOffice=0]]]
```

#### ポイント

- 同様のネスト構造を持ったクラスに変換できます

# なにが嬉しいの？

- Apache POI を使って頑張って一つ一つのセルを読まなくてもよい
- 行1、列1を利用するということ以外にフォーマット上の制約がなく、Excelでとりあえず作った表を利用しやすい
- 定義がExcelシート上に記載されているので、行や列を追加しても読み取れなくなることがない
- ただのMapでは使いにくいというときは、さっとBeanにマッピングして使える

# ドキュメント

ほかにもいろいろな機能があります。
詳細は[GitHubのWiki](https://github.com/aji3/xlbean/wiki)をご覧ください。

# 設定方法

ひとまずMavenとGradleの参照だけ置いておきます。

**Maven**

```
<repositories>
    <repository>
        <id>xlbean</id>
        <url>http://jcenter.bintray.com</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.xlbean</groupId>
        <artifactId>xlbean</artifactId>
        <version>0.2.1</version>
    </dependency>
</dependencies>
```

**Gradle**

```
repositories {
     jcenter()
}

dependencies {
    compile group: 'org.xlbean', name: 'xlbean', version:'0.2.1'
}
```

# さいごに

システム開発では構造化できるデータと戦う機会が多く、またその構造化データを表現するツールとしてやはりExcelが一番便利かと思っています。
**xlbean** はそんなシステム開発現場でよく見かける**構造化データを迅速にプログラムに取り込むことを可能とするツールです。**

作成者としてドッグフーディングをやってきましたが、迅速にできるからこそできるようになることがいろいろあることに気づきました。
ということで、別記事で本ツールの様々な応用例をご紹介していきたいと思います。

# ライブラリ

**For Maven**

```
<repositories>
    <repository>
        <id>xlbean</id>
        <url>http://jcenter.bintray.com</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>org.xlbean</groupId>
        <artifactId>xlbean</artifactId>
        <version>0.3.0</version>
    </dependency>
</dependencies>
```

**For Gradle**

```
repositories {
     jcenter()
}
dependencies {
    compile group: 'org.xlbean', name: 'xlbean', version:'0.3.0'
}
```