日々常々

ふつうのプログラマがあたりまえにしたいこと。

POIを使ってみる/Workbook間コピー

Excelの操作にてシートの移動で別のWorkbookを指定するような処理について。POIのバージョンは3.6です。

同じWorkbook内でのコピーは比較的単純に出来ます。これに対し、異なるWorkbook間でのコピーはそこそこに手間がかかります。単純に思いつくやり方でやってみるとあっさりエラーを返され、「POIではWorkbook間での複製は出来ない」なんていう早合点されてしまうこともしばしばあります。
Excelで扱われているドキュメントの設定項目は膨大であり、POIが「不十分で曖昧な実装」と評するように、全ての項目について完全な情報のまま扱うことは出来ませんが、特殊な書式を使用していないか、使用していてもそれに極端にこだわりを持っていなければ、十二分に扱うことは出来ます。基本的には WorkbookFactory#create で作成し、特に編集せず Workbook#write で書き出した状態において十分なドキュメント状態であれば、そのファイルはPOIで自由に扱うことが出来る可能性が高いです。


少々横道にそれましたが、POIにおけるシートの複製は Workbook#cloneSheet で行います。これは同じWorkbook内に複製を作成するだけで、残念ながらWorkbook間においてパッケージ内のメソッドでシートの複製を行うことは出来ないようです。Workbook#addSheet や Sheet#cloneFrom なんてのがあれば嬉しいのですが、現状SheetはWorkbookに強く結びついている事に加えて、FontやCellStyleなんかもWorkbookの持ち物であるから仕方ないのかもしれません。
だからと言って、Workbook間のコピーが出来ないという訳ではありません。WorkbookはSheetとFontとCellStyleの組み合わせであり、SheetはRowの集合であり、RowはCellの集合です。つまり、FontとCellStyleとCellを丁寧に複製すれば良いという事になります。Font自体の複製は出来ませんが、プロパティのコピーを行うことで、代用可能だと思います。CellStyleは CellStyle#cloneStyleFrom を使用することでWorkbook間でも複製が行えます。そしてCellに設定するのは CellType と CellValue くらいなものです。
部品の複製が出来てしまえば、残りは体裁くらいなもの。一口に体裁といっても多くの項目がありますが、本当に必要なものはそう多くはないと思います。とりあえず重要なのはセルの縦横の幅でしょうか。これらは Row#setHeight や Sheet#setColumnWidth で設定することが出来ます。行幅がRowに対し、列幅がSheetである点に注意してください。忘れていましたが、セルの結合は Sheet#addMergedRegion で行います。

他には印刷時のマージンだとか、ヘッダーやフッターだとか、罫線でないセル区切りの枠線の表示だとか、ズームだとか諸々の項目があります。つらつらと書きましたが、全項目の複製を行う処理を書くこと自体はそれほど難しいことではありません。単純なファイル同士ならば、シートを移動するような処理は実現可能です。もっとも、Workbook同士での基準Fontが違ったりなど、Workbookの項目に差があると少々手間はありますが、それでも妥協点は見つかると思います。そんな状態だとExcelを使用しても、どちらを優先する等の話になるでしょうし。

そんなわけで、文章だけで書いてみるWorkbook間コピー、でした。