apache POIって名前可愛いと思いませんか?

可愛いですよね。

デモコード

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ApachePOITest {

	private File file = new File("file.xls");
	
	public static void main(String[] args) {
		new ApachePOITest();
	}

	public ApachePOITest() {
		Workbook workbook = create();
		write(workbook);
		Workbook workbook2 = read();
	}

	private Workbook create() {
		Workbook workbook = new XSSFWorkbook();

		Sheet sheet0 = workbook.createSheet();
		Sheet sheet1 = workbook.createSheet("mySheet");

		Row row0 = sheet0.createRow(0);
		Row row1 = sheet0.createRow(1);

		Cell cell0_0 = row0.createCell(0);
		Cell cell1_0 = row1.createCell(0);

		cell0_0.setCellValue("hoge");
		cell1_0.setCellValue("huga");

		row0.createCell(0);

		row1.getCell(0);

		return workbook;
	}

	private void write(Workbook workbook) {
		try (FileOutputStream stream = new FileOutputStream(file)){
			workbook.write(stream);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	private Workbook read() {
		try {
			return  WorkbookFactory.create(file);
		} catch (EncryptedDocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

この、それなりに短いコードでエクセルデータの生成、データ編集、ファイル出力、ファイル読み込みが全てできています。

create //データ生成

	private Workbook create() {
		Workbook workbook = new XSSFWorkbook();

		Sheet sheet0 = workbook.createSheet();
		Sheet sheet1 = workbook.createSheet("mySheet");

		Row row0 = sheet0.createRow(0);
		Row row1 = sheet0.createRow(1);

		Cell cell0_0 = row0.createCell(0);
		Cell cell1_0 = row1.createCell(0);

		cell0_0.setCellValue("hoge");
		cell1_0.setCellValue("huga");

		row0.createCell(0);

		row1.getCell(0);

		return workbook;
	}

このメソッドではエクセルデータを生成し、シートを作成、セル2箇所にデータを書き込んで戻り値にしています。

		Workbook workbook = new XSSFWorkbook();

ブック(エクセルファイル一つ分のデータ)を生成します。
XSSFはざっくりいうとエクセルのバージョンのことだそうで、XSSFは新しいやつです。
ざっくりですが、特別古いバージョンを使うこともあまりないと思うので、とりあえずXSSFを使っておけばいいのかと思います。

Workbook型は全てのブックに実装されるインタフェースです。

		Sheet sheet0 = workbook.createSheet();
		Sheet sheet1 = workbook.createSheet("mySheet");

シートを合わせて2つ生成しています。
引数なしの場合はデフォルトでシート名が付けられるようです。
引数に文字列を指定するとその名前が付けられます。

		Row row0 = sheet0.createRow(0);
		Row row1 = sheet0.createRow(1);

今度はrowです。
rowはエクセル表の横一列を扱います。
引数に指定されている番号は行番号です。

		Cell cell0_0 = row0.createCell(0);
		Cell cell1_0 = row1.createCell(0);

続いてセルです。
これが"A1"とか"E8"とかのセルになります。
引数に指定されているのは左からの列番号です。
0はA、1はBと順になっています。

		cell0_0.setCellValue("hoge");
		cell1_0.setCellValue("huga");

セルに対してsetCellValueメソッドを呼び出しています。
名前からして想像がつくかと思いますが、セルに対して文字列を書き込んでいます。
書き込みできる型は文字列、プリミティブ型、カレンダーなどがあります。

		row0.createCell(0);

		row1.getCell(0);

ここで一つ注意をしておきます。
上の部分では既にcreateしているA1に対してもう一度createCellを呼び出しています。
この場合どうなるのでしょうか。
createCellを呼び出すことで、先ほどA1に書き込んだ"hoge"がなくなり、新しくA1セルが作り直されてしまうのです。
createRowでも同じです。1行目をもう一度createRowしてしまうと、せっかく作ったデータが1行丸ごと消えてしまいます。

既にcreateしてあるセルや行をもう一度手元に欲しい場合はgetCell,getRowを使うようにしましょう。
ただし、まだ生成していないセルや行をgetしようとした場合はnullが帰ってくるので、まずgetCellしてみて、nullが帰ってきたらcreateCellするというのが正しいやり方です。

write //ファイル書き込み

	private void write(Workbook workbook) {
		try (FileOutputStream stream = new FileOutputStream(file)){
			workbook.write(stream);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

ファイルに書き込みます。
ほとんどが例外処理になっていますね。
やっているのはファイルストリームを作成してブックに渡しているだけです。
これだけでエクセルファイルが出力されているなんてとても楽ですね。

read //ファイル読み込み

	private Workbook read() {
		try {
			return  WorkbookFactory.create(file);
		} catch (EncryptedDocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

エクセルファイルを読み込みます。
読み込みに至ってはファイルストリームの生成すらしていません。
ただ読み込みたいFileを渡すだけです。

まとめ

もちろん手抜きプログラムなので例外処理はもう少しきちんとする方が良いのでしょうが、
エクセルを編集する手軽さは伝わったのではないかと思います。
他にもワードやパワーポイントを編集するライブラリもあるらしいので、必要があればそちらも使ってみたいものです。