GradleでExcelを読み込んでなにかを作る

Gradle の社内勉強会をやることになったので、ネタ集めをしています。

「Gradle、実はこういうこともできるよ」ネタを考えてたら
私がよくやるのを紹介したらいいかもと思いつきました。

Gradle はスクリプトベースのビルドツールなので、
極端な話、ガリガリとスクリプトを書けば何でもできます。

ちょっとした Excel 読み込みからの→ファイル生成を個人的によくやります。
自分用の作業テンプレートを作っておく意味もあって、まとめておきたいと思います。

Gradleタスクを作る

build.gradle は以下のような感じです。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.apache.poi:poi:3.13'
        classpath 'org.apache.poi:poi-ooxml:3.13'
    }
}

import org.apache.poi.ss.usermodel.*

task generateMessageIdJava << {

    Workbook workbook = WorkbookFactory.create(
                                  new File("メッセージマスタ.xls"))
    Sheet sheet = workbook.getSheetAt(0)

    new File("MessageId.java").withWriter("UTF-8") { writer ->

        writer << "package sample.constants;\n\n"
        writer << "public class MessageId {\n\n"

        (3 .. sheet.getLastRowNum()).each { rownum ->
            Row row = sheet.getRow(rownum)

            String messageId = row.getCell(0).getStringCellValue()

            // メッセージIDが記載されていない行は書き出さない
            if (messageId?.length() == 0) return

            String message = row.getCell(1).getStringCellValue()

            writer << "    /** $message */\n"
            writer << "    public static final String $messageId"
            writer <<                             " = \"$messageId\";\n"
            writer << "\n"
        }

        writer << "}"
    }
}

やっていること
・buildscript ブロックで Apache POI を使えるように依存関係を設定します。
・同様に、Apache POI が使えるように import 文を追加します。
Excel を1行ずつ読み込みながら、出力ファイルに1行ずつ書き出します。

build.gradle と読み込む Excel ファイルは同じフォルダにある想定です。
出力ファイルも同じフォルダに生成します。

Excel ファイルの中身はこんな感じです。
よくあるマスタ定義ファイルです。

f:id:hideoku:20151111010422p:plain

build.gradle と同じディレクトリに Excel ファイルを配置しておきます。

[とあるフォルダ]
├build.gradle
├メッセージマスタ.xls
└(MessageId.java

タスクを実行してファイルを生成する

gradle generateMessageIdJava

タスクを実行すると、以下のようなファイルが出力されます。
よくみる定数定義ファイルです*1

package sample.constants;

public class MessageId {

    /** 検索しました。検索結果は{0}件です。 */
    public static final String MSG001 = "MSG001";

    /** 登録しました。 */
    public static final String MSG002 = "MSG002";

    /** ユーザIDとパスワードを入力してログインしてください。 */
    public static final String MSG003 = "MSG003";

    /** {0}は入力必須です。 */
    public static final String MSG004 = "MSG004";

    /** {0}は{1}以下の数値で入力してください。 */
    public static final String MSG005 = "MSG005";

}

応用例

このような Gradle タスクを Jenkins などの CI に組み込めば、
設計書が SCM(Subversion, Git etc)にコミットされたのを検知して
自動的に設計書に対応したソースコードを生成して、コミットする
…なんてこともできます。
面倒なルーチンタスクからの解放です。

Gradle Wrapper を使えば、Gradle インストールしていない人にも
使ってもらうことができますね。

*1:こういう定数定義ファイルに意味があるのかどうかは横に置いておきます。そういうものが必要とされる職場があるのだということで。