「WEB+DB PRESS vol.17」/「Jakartaプロジェクト徹底攻略2 本格活用編」掲載
2003年11月13日
1.はじめに
Javaに関するさまざまなソフトウェアをオープンソースで開発しているJakartaプロジェクトもかなり広まってきて、最近では、プログラムを組むときに、Jakartaプロジェクトのサイトをチェックしてから作り方や作るものを決める、という方も多いのではないでしょうか。
そのJakartaプロジェクトのサブプロジェクトの1つに、Microsoft OfficeのExcel、Wordファイルを読み書きするための、POI注1というライブラリがあります。
現状ではまだ、Excelファイルの読み書きができるようになったばかりですが、プログラムを組むときにExcelが使えると、さまざまな便利な機能を実装することができます。
Webアプリケーションの場合は、データの一括登録やデータ一覧のダウンロード、また、帳票向けの印刷用整形ファイルなどとして、Excelファイルを使うことができるようになります。
本章では、Webシステムを前提として、POIを利用するための基礎知識と活用ノウハウを紹介します。
1.1.POIのバージョン原稿執筆時点のPOIの正式リリース版は1.5.1です。
しかし、これはすでに1年以上前に開発されたバージョンです。といっても、開発が止まっているわけではなく、1.7-devで計算式が使えるようになったり、1.8-devで日本語が扱えるようになったりと、開発版のバージョンは着実に上がっています。現在は、グラフ出力にも対応したバージョン2.0の開発が進められているようです。
余談ですが、1.8-devが出たときに、日本語が使えるようになったということを筆者の日記サイトに書いていたら、POIのサイトからリンクが貼られていました。いまだにリンクされているようです。もっとちゃんとサイトでとりあげようと思いつつ、とりあげないまま今に至ります。
2.Webアプリケーションで利用するための準備
それではまず、WebアプリケーションでPOIを使うための環境を準備することにしましょう。
本稿の内容は、以下の環境で動作を確認しています。以降の解説も、この環境を前提として進めさせていただきます。
OS:Windows 2000
JDK:Java 2 SE 1.4.2
サーブレットコンテナ:Tomcat 4.1.27
OSはWindows 2000を使っていますが、Linuxなど他のOSでも動作すると思います。Excelがインストールされている必要はありません。
対応JDKに関しては、POIのドキュメント中での記述を見つけられませんでしたがJDK 1.4.0での動作を確認しています。サーブレットコンテナはTomcat 4.0.6での動作を確認しています。また記事中サンプルのURLではTomcatへ8080番ポートでアクセスできることを前提としています。
2.1.POIのダウンロードまず、次のURLからPOIをダウンロードします。
http://www.apache.org/dist/jakarta/poi/dev/bin/
本稿では、バージョン2.0の開発版を使用することにします。ダウンロードしたのは、原稿執筆時点で最新の開発版であるpoi-bin-2.0-RC1-20031102.zipです。
開発版とはいえ、簡単な処理では問題なく利用できます。一方正式版でも、「不十分であいまいな」Excelフォーマットを扱うというライブラリの性格上、仕様ともバグともとれる挙動が多く見られます。
開発版にしても正式版にしても、利用範囲での動作確認は必要です。安定性や信頼性が大きく求められる場合には、Windows上でExcelをインストールしてOLEオートメーションを利用するのがやはり一番確実です。
2.2.JSP/サーブレットコンテナの準備以降、筆者が作ったサンプルアプリケーションを使って解説していきます。本誌Webサイトhttp://www.gihyo.co.jp/magazines/wdpress/からサンプルアプリケーションをダウンロードしてご覧いただくとわかりやすいかと思います。なお、誌面の都合でソースコードのすべてを掲載することはできませんのでご了承ください。サンプルアプリケーションのディレクトリ構成は、図1のようになります。
図1 ディレクトリ構成
たとえばC:\java\poiにファイルを置いた場合は、server.xmlにリスト1のようなContextタグを追加します。以降は、ファイルを置いたディレクトリをSAMPLE_HOMEと表します。
リスト1 Contextタグに追加する内容(server.xml)
本稿で作成するサーブレットのマッピングを含んだweb.xmlは、リスト2のようなものになります。
リスト2 本稿で作成するサーブレットのマッピング(web.xml)
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
poi-bin-2.0-RC1-20031102.zipを解凍してできたpoi-2.0-RC1-20031102.jarは、WEB-INFディレクトリの下のlibディレクトリに置きます。これによってこのJARファイルは、実行時のクラスパスに自動的に加えられます。また、JSPをコンパイルするときにも利用されます。JSPだけを使うときには、利用するライブラリのJARファイルをこのlibディレクトリに入れておけばクラスパスなどの設定をする必要はありません。サーブレットをコンパイルするときには、クラスパスにこのJARファイルを含んでおく必要があります。
通常のアプリケーションでは、コンパイル時や実行時のクラスパスにこのJARファイルが含まれるようにしてください。本記事では触れていませんが、contribパッケージのクラスを使うときにはpoi-contrib-2.0-RC1-20031102.jarがクラスパスに含まれるようにする必要があります。org.apache.poi.generatorパッケージのクラスやorg.apache.poi.hdf パッケージのクラス、org.apache.poi.hssf.usermodel.HSSFChartクラスを利用するときにはpoi-scratchpad-2.0-RC1-20031102.jarがクラスパスに含まれるようにする必要があります。
3.Excelファイルの読み込み
3.1.Excelファイル読み込みの基本それではとりあえず、Excelファイルを読み込んでみましょう(リスト3)。
リスト3 read.jsp
とりあえず読み込み
read.jspをブラウザで読み込む前に、図2のような、A1セルに何かしらの値を記述したExcelファイルを作成してSAMPLE_HOME\xls\simple.xlsに保存します。
図2 読み込みテスト用Excelファイル
その上でhttp://localhost:8080/poi/read.jspを開くと、ExcelファイルのA1セルの値が読み込まれていることがわかります(図3)。
図3 読み込みテストJSPの実行結果
Excel ファイルを読み込むときには、POIFSFileSystemクラスのコンストラクタに読み込み先のInputStreamを指定して生成したオブジェクトを使います(JAR圧縮されたリソースではうまく動かないようです)(1)。
このとき渡したInputStreamオブジェクトは、このコンストラクタ中でしか使われないので、すぐにclose()しても構いません(2)。また、close()を行わないと、読み込んだExcelファイルが上書き保存できなくなることがあります。
エクセルファイルを読み込むには、まずPOIFSFileSystemオブジェクトをコンストラクタに渡してHSSFWorkbookオブジェクトを生成します(3)。このオブジェクトが1つのExcelファイルを表します。
あとは、そこからgetSheetAtメソッドでワークシートをHSSFSheetオブジェクトとして取得して(4)、getRowメソッドでシートの行をHSSFRowオブジェクトとして取得して(5)、getCellメソッドでセルをHSSFCellオブジェクトとして取得します(6)。
セルの値を得るには、取得する値の型によって、getStringCellValueメソッドやgetNumericCellValueメソッドなどを使い分けます(7)。
本稿で使用している主なメソッドは、表1~4のとおりです。
org.apache.poi.hssf.usermodel.HSSFWorkbook
エクセルファイル全体
コンストラクタ HSSFWorkbook(POIFSFileSystem fs) POIFSFileSystemからワークブックオブジェクトを生成する
byte ENCODING_UTF_16 日本語を指定するときの値
void write(OutputStream stream) OutputStreamにワークブックを出力する
HSSFSheet getSheetAt(int index) インデックスを与えてシートを得る
HSSFSheet createSheet() シートを生成する
String setSheetName(int sheet) インデックスを与えてシート名を得る
HSSFCellStyle createCellStyle() セル書式を生成する
HSSFFont createFont() フォントを生成する
HSSFWorkbookの主なメンバ
org.apache.poi.hssf.usermodel.HSSFWorksheet
エクセルシート
HSSFRow getRow(int rownum) 行を取得する
HSSFRow createRow(int rownum) 行を生成する
Iterator rowIterator() 行を走査するイテレータを得る
void setColumnWidth(short column,short width) 行幅を設定する
short getColumnWidth(short column) 列幅を得る
void setDefaultRowHeight(short value) デフォルトの行の高さの設定・取得
short getDefaultRowHeight()
void setDefaultCellWidth(short value) デフォルトの列幅の設定・取得
short getDefaultCellWidth()
HSSFWorksheetの主なメンバ
org.apache.poi.hssf.usermodel.HSSFRow
行
HSSFCell getCell(short cell) セルを取得する
void createCell(short cell) セルを生成する
Iterator cellIterator() セルを走査するイテレータを得る
void setHeight(short value) 行の高さの設定・取得
short getHeight()
HSSFRowの主なメンバ
org.apache.poi.hssf.usermodel.HSSFCell
セル
short ENCODING_UTF_16 日本語を指定するときの値
int CELL_TYPE_STRING 文字列のセルを示す値
int CELL_TYPE_NUMERIC 数値のセルを示す値
int CELL_TYPE_FORMULA 数式のセルを示す値
String getCellFormula() セルの数式を得る
Date getDateCellValue() セルの日付を得る
double getNumericCellValue() セルの数値を得る
String getStringCellValue() セルの文字列を得る
void setCellFormula(String) セルに数式を設定する
void setCellValue(String) セルに文字列を設定する
void setCellStyle(HSSFCellStyle value) セルの書式の設定・取得
HSSFCellStyle getCellStyle()
void setCellType(int value) 値の種類の設定・取得
int getCellType()
void setEncoding(short value) エンコーディングの設定・取得
short getEncoding()
HSSFCellの主なメンバ
3.2.表形式データの読み込み次に、Excelで作成した一覧データを読み込んでみます。業務において、データを一括登録する際のデータ形式としてよく使われるものにCSVがありますが、これは素のままでは、一般の人には編集しにくいものです。結局は、Excelでデータを作成したものをCSVとして保存して使うことが多いと思います。
そうであれば、XLS形式のデータをそのままWebアプリケーション上で読み込めるようにしたほうが手軽です(リスト4)。
リスト4 readlist.jsp
データ読み込み
ここではまず、図4 のようなExcel ファイルをSAMPLE_HOME\xls\data.xlsとして作成します。D列には「=C3*1.05」という計算式が入力されています。
図4 読み込み用Excelファイル
http://localhost:8080/poi/readlist.jsp(リスト4)を開くと、各データが読み込まれています(図5)。
図5 読み込んだデータの出力
ここでは、データ取得用のメソッドを使い分けて値を取得しています(5)(6)(7)。またD列の計算式のセルは、計算結果をgetNumericCellValueメソッドで(8)、計算式をgetCellFormulaメソッドで取得しています(9)。
またこのプログラムでは、データの各行の取得にHSSFSheet#rowIteratorメソッドで取得したIteratorを利用しています(1)。背景色が黒い行の次からデータを取得して、次に背景色が黒い行が来たら読み込みを終わるようにしています(4)。
背景色の取得では、まずHSSFCell#getCellStyleメソッドでHSSFCellStyleオブジェクトを取得して(2)、getFillForegroundColorメソッドで背景色の色番号を得ています(3)。HSSFCellStyle、HSSFColorのメソッドには、表5、6のようなものがあります。
ここではデータを表示しているだけですが、Excelから読み込んだデータをデータベースに登録するようにすれば、データの一括登録がExcelデータを使って行えるようになります。
org.apache.poi.hssf.usermodel.HSSFCellStyle
セルの書式
short BORDER_DOUBLE 2重線を示す値
short BORDER_THIN 普通の線を示す値
short BORDER_MEDIUM 太線を示す値
void setBorderBottom(short value) 下の罫線の設定・取得
short getBorderBottom()
void setBorderLeft(short value) 左の罫線の設定・取得
short getBorderLeft()
void setBorderRight(short value) 右の罫線の設定・取得
short getBorderRight()
void setBorderTop(short value) 上の罫線の設定・取得
short getBorderTop()
void setDataFormat(short value) 表示形式の設定・取得
short getDataFormat()
void setFillForegroundColor(short value) 塗りつぶし色の設定・取得
short getFillForegroundColor()
HSSFCellStyleの主なメンバ
org.apache.poi.hssf.util.HSSFColor
色
String getHexString() 色の16進数表現を得る
short getIndex() 色番号を得る
short[] getTriplet() RGB値を配列で得る
HSSFColorの主なメンバ
3.3.データ種別の判別先ほどのサンプルでは、読み込むExcelファイルに記述されているデータの形式を決めて処理していました。不定形のデータを読み込むときには、セルのデータ種別を判別する必要があります。(リスト5)
リスト5 readstyle.jsp
データ種別
まず、図6のようなExcelファイルをSAMPLE_HOME\xls\color.xlsとして作成します。C2セルには「=CONCATENATE(B2,"aa")」、C3セルには「=B3*2」という計算式が入力されています。また、いくつかのセルには「塗りつぶしの色」が設定されています。
図6 読み込み用Excelファイル
http://localhost:8080/poi/readstyle.jsp(リスト5)を開くと、各セルが読み込まれています(図7)。
図7 読み込み結果
セルの種別はHSSFCell#getCellTypeメソッドで取得します(2)。
この値がHSSFCell.CELL_TYPE_STRINGのときは文字列です(3)。そのままgetStringCellValue()メソッドで文字列が取得できます。
HSSFCell.CELL_TYPE_NUMERICのときは、数値か日付です(4)。getCellStyleメソッドでHSSFCellStyleオブジェクトを得て、getDataFormatメソッドでデータ形式を得ます(5)。このデータ形式に対してHSSFDateUtil.isInternalDateFormatメソッドで日付であるかどうか判別します(6)。このメソッドがfalseのときは数値形式です。trueのときは日付の形式ですが、その中でも値が22か176のときには日付時刻の形式になっています(7)。
また、HSSFCell.CELL_TYPE_FORMULAのときは計算式です(8)。getCellFormulaメソッドで計算式が得られます。getNumericCellValueメソッドで値が得られますが、Double.isNaNメソッドで数値がどうか判定して、trueのときが数値です(9)。falseのときは文字列などですが、うまく値を取得することができませんでした。
また、このサンプルではHSSFSheet#rowIteratorメソッドやHSSFRow#cellIteratorメソッドを使ってすべてのセルの操作をしていますが(1)、何もない行・セルは無視されてしまっています。実行結果をみるとcellIteratorメソッドで取得したイテレータでは右から左へ処理が進んでいますね。通常の処理ではcellIteratorを使わない方がよさそうです。
3.4.色の判別色の判別には、ちょっと面倒なコードを記述する必要があります。(リスト6)
リスト6 readstyle.jsp(色の判別)
データ種別
改めてhttp://localhost:8080/poi/readstyle.jsp(リスト6)を開くと、各セルの色が読み込まれています(図8)。
図8 色を反映した出力
セルの「塗りつぶしの色」のインデックスは、HSSFCellStyle#getFillForegroundColorメソッドで得ることが出来ます(4)。このインデックスからHSSFColorクラスを継承した、それぞれの色に対応したクラスのオブジェクトを取得するには、サンプル中のgetColorFromIndexメソッドのような処理を行う必要があります(1)。このサンプルでは、必要な色しか判定していませんが、どんな色にも対応できるようにするためには、HSSFColorクラスを継承した50個弱の色クラスについて判定を行う必要があります。どのような色のクラスがあるかはPOIに付属のドキュメントをご覧ください。
また、セルのフォントをあらわすHSSFFontオブジェクトを得るには、HSSFCellStyle#getFontIndexメソッドで得たインデックスをHSSFWorkbook#getFontAtメソッドに渡します(5)。
このサンプルでは、全セルの処理をforループで行っていますが(2)(3)、行に関してはHSSFSheet#getLastRowNumメソッドの戻り値が示す行番号まで処理をする必要があるのに対して、セルに関してはHSSFRow#getLastCellNumメソッドの戻り値が示すセル番号の直前までしか処理をする必要がないので注意が必要です。
3.5.Excelデータのアップロード先ほどの例では静的なファイルを直接指定して読み込んでみましたが、Webアプリケーションでは、ExcelファイルをHTMLフォームからアップロードすることが多いと思います。
Javaには標準ではファイルアップロードの機能が用意されていないので、これまたJakartaプロジェクトの成果物であるCommons FileUploadを使って、この機能を実現することにしましょう。
FileUploadのダウンロードは次に示すJakartaのダウンロードサイトから行います。
http://jakarta.apache.org/site/binindex.cgi
「Commons FileUpload」の「1.0 zip」をクリックし、commons-fileupload-1.0.zipをダウンロードします。また、FileUploadはBeanUtilsを利用するので,同じくJakartaのダウンロードサイトで「Commons Beanutils」の「1.6.1 zip」をクリック、commons-beanutils-1.6.1.zipをダウンロードします。
それぞれ解凍後に生成されるcommons-fileupload-1.0.jarとcommons-beanutils.jarをWEB-INFディレクトリの下のlibディレクトリにコピーします。今回はJSPからの利用だけなので、とくにクラスパスの設定などは必要ありません。
アップロード用のフォームは、リスト7のようなものを用意します。
ファイルの受け取り側(リスト8)は、ファイル読み込みプログラム(リスト4)の読み込み部分を、アップロードデータを取得するように変更したものです。
リスト8 readlist.jsp(アップロード対応版)
データ読み込み
Javaでは入力先が変わっても、処理が同じであれば、入力先だけを変えればよいので便利ですね。
HTMLフォーム(リスト7、図9)で先ほど読み込んだファイル(図4)を指定します。送信ボタンを押すと、先ほどと同じ画面(図5)が表示されて、データが読み込まれていることがわかります。
リスト7 upload.html
アップロード
ファイル:
図9 ファイル指定画面
ファイルアップロードに関する詳しい説明はここでは割愛しますが、DiskFileUpload#parseRequestメソッドでFileItemオブジェクトなどが格納されたListオブジェクトを取得して(1)、その中のFileItemオブジェクトからgetInputStreamメソッドでInputStreamオブジェクトを取得して処理をする(2)という流れになっています。
4.Excelファイルの作成
次に、Excelファイルの生成をしてみましょう。まず、単純なファイルを生成してみます(リスト9)。
リスト9 generate.jsp
Excel生成
生成しました
http://localhost:8080/poi/generate.jspを開くと、ブラウザ画面に図10のような表示が出て、SAMPLE_HOME\xls\generated.xlsとして図11のようなExcelファイルが生成されているはずです。
図10 生成後のメッセージ
図11 生成されたExcelデータ
Excelファイルの作成を行うにはまず、HSSFWorkbookオブジェクトを生成します(1)。それからcreateSheetメソッドでワークシートとしてHSSFSheetオブジェクトを生成(2)、createRowメソッドで行としてHSSFRowオブジェクトを作成(3)、そしてcreateCellメソッドでセルとしてHSSFCellオブジェクトを作成することになります(4)。
あとはそのHSSFCellオブジェクトにsetCellValueメソッドで値を設定することになります(6)。setCellValueメソッドはStringやdoubleを引数として受け取るものがそれぞれ用意されているので、あまり型を意識することはありません。
2バイト文字を設定する場合には、setEncodingメソッドでセルのエンコーディングとしてHSSFCell.ENCODING_UTF_16を指定しておく必要があります(5)。
計算式を設定する場合にはsetCellFormulaメソッドを使います(7)。このとき、「=」をつける必要はないので注意してください(セルの計算自体は、Excelで開いたときに行われるので、直後にgetNumericCellValueメソッドなどで計算結果を得ることはできません)。
値の設定などが終わったら、HSSFWorkbookオブジェクトのwriteメソッドを呼び出して、OutputStreamに出力します(8)。ここではファイルに書き込むのでFileOutputStreamオブジェクトを引数として渡しています。
4.1.動的Excelファイルのダウンロードそれでは次に、Webアプリケーションらしく、動的に生成したExcelファイルをブラウザからダウンロードできるようにしてみましょう。Excelファイルのようなバイナリデータの生成をJSPで行うことはできないため、サーブレットを使います(リスト10)。
リスト10 ExcelGenerateServlet.java
package poisample;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.hssf.usermodel.*;
public class ExcelGenerateServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0,
"ダウンロード",HSSFWorkbook.ENCODING_UTF_16);
//文字列の書き込み
HSSFCell cell = sheet.createRow(0).createCell((short)1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("ダウンロードサンプル");
//送信
response.setHeader("Content-Disposition",
"attachment;filename=download.xls");
response.setContentType("application/vnd.ms-excel");
wb.write(response.getOutputStream());
}
}
このサーブレットは、web.xmlに記述したマッピングによってhttp://localhost:8080/poi/ExcelGenereteにアクセスすることで実行されるようになっています。アクセスすると、ダウンロードが始まります(図12)。
図12 「ファイルのダウンロード」ダイアログ
保存すると、図13のようなExcelファイルが生成されています。
図13 生成されたExcelファイル
ダウンロード時のContentTypeは「application/vnd.ms-excel」としています(1)。また、初期ファイル名を指定するためにContent-Dispositionヘッダでファイル名を指定しています(2)。
サーブレットからの送信は、HSSFWorkbookオブジェクトのwriteメソッドにHttpServletResponse#getOutputStreamメソッドの戻り値を渡すことで行われています(3)。
4.2.書式の設定単純な出力ができるようになったので、次はさまざまな書式を設定してみます(リスト11)。
リスト11 StyleServlet.java
package poisample;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
public class StyleServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0,"書式",HSSFWorkbook.ENCODING_UTF_16);
//セル幅
sheet.setColumnWidth((short)0,(short)5120);//140ピクセル
sheet.setColumnWidth((short)1,(short)7680);//210ピクセル
sheet.setColumnWidth((short)2,(short)7680);//210ピクセル
HSSFRow row;
HSSFCell cell;
HSSFCellStyle style;
HSSFFont font;
//背景・罫線
row = sheet.createRow((short)1);
cell = row.createCell((short)0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("背景色");
style = wb.createCellStyle();
style.setFillForegroundColor(HSSFColor.BRIGHT_GREEN.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderTop(HSSFCellStyle.BORDER_DOUBLE);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
cell.setCellStyle(style);
//日付
cell = row.createCell((short)1);
cell.setCellValue(new java.util.Date());
style = wb.createCellStyle();
style.setDataFormat((short)22);
cell.setCellStyle(style);
//フォント
row = sheet.createRow((short)2);
String[] fonts = {
"MS Pゴシック","MS P明朝","HG創英角ポップ体"};
for(short col = 0; col < 3; ++col){
cell = row.createCell(col);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(fonts[col]);
font = wb.createFont();
font.setFontName(fonts[col]);
font.setFontHeight((short)320);//16ポイント
style = wb.createCellStyle();
style.setFont(font);
cell.setCellStyle(style);
}
//送信
response.setHeader("Content-Disposition",
"attachment;filename=style.xls");
response.setContentType("application/vnd.ms-excel");
wb.write(response.getOutputStream());
}
}
このサーブレットは/StyleというURLにマッピングするようにweb.xmlに記述しています。http://localhost:8080/poi/Styleにアクセスすることでサーブレットによって生成されたExcelファイルのダウンロードが始まります。保存すると図14のようなファイルになります。
図14 生成されたExcelファイル
このサンプルでは、セル幅・背景色・罫線・日付・フォントサイズ・フォントの種類を設定しています。
セル幅は、HSSFSheetオブジェクトのsetColumnWidthメソッドで指定します(1)。このとき指定する数値は2560が70ピクセルにあたります。
セルの書式はHSSFCellStyleクラスが管理します。
日付を設定する際に、setDataFormatメソッドで日付のフォーマットを指定する必要があります(2)。日付のフォーマットとして引数に渡すことができる値には表7のようなものがあります。
フォントはHSSFFontクラスで管理しています(表8)。フォントサイズはsetFontHeightメソッドで指定しますが(4)、このとき指定する数値は20が1ポイントにあたります。
フォントの種類はsetFontNameメソッドで指定します(3)。図14を見ると、MSゴシックとMS明朝はうまく設定できているのですが、HG創英角ポップ体はうまく設定できていません。MSゴシックとMS明朝以外の日本語名のフォントはうまく設定できないようです。
日付フォーマット
14 2002/11/2
31 2002年11月2日
55 2002年11月
56 11月2日
57 H14.11.2
58 平成14年11月2日
177 11/2
22 2002/11/2 0:00
176 2002/11/2 12:00 AM
org.apache.poi.hssf.usermodel.HSSFFont
フォント
short BOLDWEIGHT_BOLD ボールド体を示す値
void setBoldweight(short value) 太さの設定・取得
short getBoldweight()
void setFontHeight(short value) フォントサイズの設定・取得
short getFontHeight()
void setFontName(String value) フォント名の設定・取得
String getFontName()
void setStrikeout(boolean value) 打ち消し線の設定・取得
boolean getStrikeout()
void setUnderline(boolean value) 下線の設定・取得
boolean getUnderline()
HSSFFontの主なメンバ
4.3.書式テンプレートプログラムでいちいち書式を設定するのも面倒なので、書式を指定したファイル(図15)をあらかじめ用意するようにしてみましょう(リスト12)。
リスト12 RyoshuServlet.java
package poisample;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.*;
public class RyoshuServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String path = getServletContext().getRealPath(
"/xls/ryoshu-template.xls");
InputStream is = new FileInputStream(path);
POIFSFileSystem fs = new POIFSFileSystem(is);
is.close();
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(0);
HSSFCell cell;
//宛名
cell = sheet.getRow((short)3).getCell((short)1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("評論工務店様");
//日付
cell = sheet.getRow((short)2).getCell((short)5);
cell.setCellValue(new java.util.Date());
//金額
cell = sheet.getRow((short)7).getCell((short)1);;
cell.setCellValue(15000);
//送信
response.setHeader("Content-Disposition",
"attachment;filename=ryoshu.xls");
response.setContentType("application/vnd.ms-excel");
wb.write(response.getOutputStream());
}
}
図15 リスト表示用のテンプレート
図15のファイルは、あらかじめSAMPLE_HOME\xls\ryoshu-template.xlsとして用意しておきます。この中の宛名・日付・金額の部分をサーブレットで変更して送信するようにします。
このサーブレットは/RyoshuというURLにマッピングするようにweb.xmlに記述しています。http://localhost:8080/poi/Ryoshuにアクセスすることでサーブレットによって生成されたExcelファイルのダウンロードが始まります。保存すると図16のようなファイルになります。
図16 作成されたファイル
このようにすると、Excelを書式エディタとして使うことができます。PDFの場合は柔軟なレイアウトができますが、PDF作成ツールは普及率が低く、また、操作も煩雑になりがちです。その点、Excelはレイアウトの制限は大きいのですが、普及率も高くレイアウト作成の操作も簡単です。
また、テンプレートファイルで用意しておけば、日本語名のフォントなどPOIでは扱えないものも問題なく扱えるようです。簡単な印刷フォームとして利用すると便利なのではないでしょうか。
4.4.書式付リストの出力最後に、書式テンプレートを元にリストを出力するサンプルをご紹介します(リスト13)。あらかじめ、図17のようなファイルを用意しておきます。
リスト13 ListServlet.java
package poisample;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.*;
public class ListServlet extends HttpServlet {
String[][] sampledata = {
{"なかやま","モツ鍋","大橋","4000"},
{"ショッパイヤ","ブラジル料理","西通り","3000"},
{"九ちゃん","ラーメン","大宰府","500"}};
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String path = getServletContext().getRealPath("/list-template2.xls");
InputStream is = new FileInputStream(path);
POIFSFileSystem fs = new POIFSFileSystem(is);
is.close();
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(0);
//スタイル取得
HSSFCellStyle[] styles = new HSSFCellStyle[sampledata[0].length];
HSSFRow row = sheet.getRow((short)3);
for(short i = 0; i < styles.length; ++i){
styles[i] = row.getCell(i).getCellStyle();
}
for(int i = 0; i < sampledata.length; ++i){
//行作成
if(i > 0){
//2行目以降
sheet.shiftRows(i + 3,i + 3 ,1);
row = sheet.createRow(i + 3);
for(short j = 0; j < sampledata[i].length; ++j) row.createCell(j);
}
else{
//最初のデータ
row = sheet.getRow(i + 3);
}
for(short j = 0; j < sampledata[i].length; ++j){
HSSFCell cell = row.getCell(j);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(styles[j]);
if(j < 3){
cell.setCellValue(sampledata[i][j]);
}else{
cell.setCellValue(Integer.parseInt(sampledata[i][j]));
}
}
}
//平均の計算式
row = sheet.getRow(sampledata.length + 3);
if(row != null){
HSSFCell cell = row.getCell((short)3);
if(cell != null){
String f = "average(d4:d" + (3 + sampledata.length) + ")";
cell.setCellFormula(f);
}
}
//送信
response.setHeader("Content-Disposition", "attachment;filename=list.xls");
response.setContentType("application/vnd.ms-excel");
wb.write(response.getOutputStream());
}
}
図17 テンプレート用のExcelファイル
図17のファイルを、SAMPLE_HOME\xls\listtemplate.xlsとして用意します。
このサーブレットは/ListというURLにマッピングするようにweb.xmlに記述しています。http://localhost:8080/poi/Listにアクセスすることでサーブレットによって生成されたExcelファイルのダウンロードが始まります。保存すると図18のようなファイルになります。
図18 生成されたExcelファイル
書式テンプレートの4行めの書式を元に、各行が書式設定されています。
行を挿入するメソッドは無いようなので、HSSFSheet#shiftRowsメソッドで下部の行をシフトさせています(1)。このとき、こうやって行をシフトさせても「=sum(d3:d4)」など計算式で示されているセルは変わらないので注意が必要です。
5.まとめ
以上のように、Excelファイルを扱うことができれば、アプリケーションの幅も広がります。また、今回は試していませんが、POI 2.0からはグラフを扱うこともできるようになるようです。グラフの扱いがうまくできるようになれば、また、POIを使った応用がさらにいろいろ考えられそうです。
--------------------------------------------------------------------------------
Copyright (c) 2001-2004 Naoki Kishida All Rights Reserved.
http://www.fk.urban.ne.jp/home/kishida/