読者です 読者をやめる 読者になる 読者になる

ひっそりとGExcelAPI v0.2をリリースしました

はじめに

みんな大好きExcelのファイルに超簡単にアクセスしまくれるGroovy用ライブラリです。


名前がGExcelAPIなのに使ってるライブラリはApache POIです。JExcelAPIじゃないのでご注意。
だって語呂がいいだもん。


元々暖めてたアイデアを某書籍のサンプル用として実装しはじめたんですけど、案外使い勝手のよいプロダクトになったんじゃないかと思います。


JGGUG合宿のG100Pon企画*1でのExcel操作のお題に回答としてサンプルを公開したので、一部の人は既に知ってたりしますが、たぶん正式なアナウンス(?)としてはこれが最初になりますね。

v0.2正式版リリース

というわけで、ひっそりと、本当にひっそりとGithubにpushしていたv0.1とは違い、やさぐれ番長というユーザも付いたことだし、v0.2の今回ははてダでアナウンスをしてみます。


ソースコード自体はgithubにおいてあるので、よかったら。
割と力業というか、そんなエレガントなものでもないですけど。


githubのrawを使ったオレオレMavenリポジトリにデプロイ済みなので、Grapeを使って簡単に取得することができます。

つまり、後述のサンプルを適当なファイルに保存して、適当なExcelファイルを引数に指定して実行するだけで、Grapeによるjarの取得のためにちょっと待たされますが、そのまま実行することができます。何も足さない、何も引かない。大人のスクリプト。

$ groovy sample.groovy TEST.xls


というわけでサンプルコード。なんとなく雰囲気が伝わりますかね。

@GrabResolver(name="kobo-maven-repo", root="https://github.com/kobo/maven-repo/raw/master/release")
@GrabConfig(systemClassLoader=true) // ★GroovyServで実行する場合はこれが必須!
@Grab("org.jggug.kobo:gexcelapi:0.2")
import org.jggug.kobo.gexcelapi.GExcel

// Excelファイルの読み込み
def book = GExcel.open(args[0])

// シートの取得
def sheet = book[0] // 第1シート
//def sheet = book[1] // 第2シート
//def sheet = book["Sheet3"] // シート名で指定も可能

// セルの値の取得
println sheet.A1.value // -> "value of A1"
println sheet.B2.value // -> "value of B3"

println "="*20

// セルの値の書き換え
sheet.A1.value = "New value of A1"
sheet.B2.value = "New value of B3"

// イテレータ各種
def dump = { cell -> println "${cell.label}: ${cell.value}" }
sheet.A_.each{ cell -> dump cell }
println "-"*20
sheet.B_.each{ cell -> dump cell }
println "-"*20
sheet._1.each{ cell -> dump cell }
println "-"*20
sheet._2.each{ cell -> dump cell }
println "-"*20
sheet.A1_B6.each{ row -> row.each { cell -> dump cell } }

println "="*20

// XML出力との組合せ
def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)
xml.excel() {
    columnA {
        sheet.A_.each {
            "${it.label}" (value:it.value)
        }
    }
    columnB {
        B1 (value: sheet.B1.value)
        B2 (value: sheet.B2.value)
    }
}
println writer.toString()

TEST.xlsの中身は明かさないままに結果の出力を貼っておくと、こんな感じです。

Sheet1
B2の内容
====================
A1: New value of A1
A2: あいうえお
A3: 1234.0
A4: 40108.0
A5: true
A6: false
--------------------
B1: B1の内容
B2: New value of B3
B3: null
B4: null
B5: null
B6: null
--------------------
A1: New value of A1
B1: B1の内容
--------------------
A2: あいうえお
B2: New value of B3
--------------------
A1: New value of A1
B1: B1の内容
A2: あいうえお
B2: New value of B3
A3: 1234.0
B3: null
A4: 40108.0
B4: null
A5: true
B5: null
A6: false
B6: null
====================
<excel>
  <columnA>
    <A1 value='New value of A1' />
    <A2 value='あいうえお' />
    <A3 value='1234.0' />
    <A4 value='40108.0' />
    <A5 value='true' />
    <A6 value='false' />
  </columnA>
  <columnB>
    <B1 value='B1の内容' />
    <B2 value='New value of B3' />
  </columnB>
</excel>


これらは全部本日リリースのv0.2で利用可能な機能です。

GroovyServで使う場合の注意事項

GroovyServで実行すると本当にサクサク動くのでやみつきになるんですけど、このサンプルの場合は★の部分のGrabConfigを忘れずに指定しましょう。

@GrabResolver(name="kobo-maven-repo", root="https://github.com/kobo/maven-repo/raw/master/release")
@GrabConfig(systemClassLoader=true) // ★GroovyServで実行する場合はこれが必須!
@Grab("org.jggug.kobo:gexcelapi:0.2")
import org.jggug.kobo.gexcelapi.GExcel

// ...snip...

Grapeを使った依存ライブラリの解決の場合、クラスローダの扱いが通常のスクリプトと違うようで、上記の設定がないと何回か繰り返し実行してるウチにPermGenが枯渇してOutOfMemoryになります。ご注意を。

[実験的機能] HTML出力 (ただし、v0.3-SNAPSHOT)

v0.2リリース時のサンプル用に、Excelの中身をある程度良い感じにHTMLにしてくれるというGroovyスクリプトを書いてたんですね。まあ、あんまり凝ったことはできないし、まだどんな場合もうまく表示できる、ってわけじゃないんですけど、割とそれっぽく動くし、せっかくなのでとりあえず実験的機能としてGExcelAPIのプロダクトコードにマージすることにしてみました。ただ、すでにv0.2をgithubにpushした後だったので、潔くあきらめてv0.3向けの(実験的)機能という扱いにしてます。


とりあえずは、v0.3-SNAPSHOTとしてオレオレMavenリポジトリにデプロイしておいたので、以下のようにGrapeの指定をすれば今すぐ試すこともできます。


よかったらお試しください。

@GrabConfig(systemClassLoader=true) // for workaround a permgen problem with GroovyServ
@GrabResolver(name="kobo-maven-repo", root="https://github.com/kobo/maven-repo/raw/master/snapshot")
@Grab("org.jggug.kobo:gexcelapi:0.3-SNAPSHOT")
import org.jggug.kobo.gexcelapi.*

def excelFile = args[0]
def book = GExcel.open(excelFile)
def sheet = book[0]
def range = sheet.A1_F10

def tempFile = File.createTempFile("excel2html", "temp.html")
tempFile.text = range.toHtml()
"open $tempFile".execute() // for on Terminal in Mac


f:id:nobeans:20101217001651p:image

まとめ

Excelをごにょごにょしたかったら、もうみんなGroovyやれば良いと思いますよ。ホント。

*1:Groovyで色々なお題を100本斬りするという企画