Groovy では、クロージャを使って若干の下準備(下例では TableBuilder)をしておくと、以下のようなコードが書ける。
static void main(args) { new TableBuilder().with { sheet( "test" )( style(header) )( "No" )( "名前" )( nextRow )( style(normal) )( 1 )( "琵琶湖" )( nextRow )( 2 )( "多来加湖" )( nextRow )( 3 )( "富内湖" )( endTable ) }.write(new FileOutputStream("sample.xls")); }
TableBuilder の中では、Apache POI を使っていて、実行すると 下のような Excel ファイルが sample.xls に書き出される。
カッコの開き方が気に入らないが、しょうがないらしい。下の A、B は等価だけど、C は別ものに解釈される。上例を C のようなカッコのに直すと、動作しない。
A | B | C |
---|---|---|
("A1")("B1")( "A2")("B2") | ("A1")("B1" )("A2")("B2") | ("A1")("B1") ("A2")("B2") |
TableBuilder は下のコードのようになる。
class TableBuilder { def book TableBuilder() { book = new HSSFWorkbook() } def nextRow = { cell, style -> cursor.curry(cell.offset(1, -cell.columnIndex), style) } def endTable = { cell, style -> book } def cursor = { cell, style, arg -> if (arg instanceof Closure) { arg(cell, style) } else { cell.setCellValue(arg) if (null != style) cell.cellStyle = style cursor.curry(cell.next(), style) } } def start(sheet){ cursor.curry(sheet.cellAt(0, 0), null) } def sheet(name) { start(book.createSheet(name)) } def style(styleClosure) { { cell, style-> cursor.curry(cell, styleClosure(book))}} }
また、POI の API が Groovy コードの中で馴染むように、Mixin でメソッドを追加した。
class CellMix { def next() { offset(0, 1) } def offset(r, c) { sheet.cellAt(rowIndex + r, columnIndex + c) } } class RowMix { def cellAt(c) { getCell(c) ?: createCell(c) } } class SheetMix { def rowAt(r) { getRow(r) ?: createRow(r) } def cellAt(r, c) { rowAt(r).cellAt(c); } } class CellStyleMix { def borderMethodName = { s-> "setBorder" + s.capitalize() } def setBorder = { arg, edge -> owner."${borderMethodName(edge)}"(arg."$edge" ?:BORDER_NONE); setBorder.curry(arg) } def setBorder(Map arg) { setBorder.curry(arg)("top")("left")("bottom")("right") } }
カッコを連鎖させるやり方にしたのは、単にクロージャとカリー化を試したかっただけで、実は、普通のクラスと leftShift() のオーバライドだけで、 下のような C++風の書き方もできて、こっちの方がむしろスッキリしたコードになる。
sheet("test") << "A1" << "B1" << endRow << "A2" << "B2" << endTable
0 件のコメント:
コメントを投稿