Apache POI
概要
Apache POI は、Java 環境で Microsoft Office 形式のファイルを読み書きするためのオープンソースライブラリです。 Excel、Word、PowerPoint など、複数の Office ファイル形式の作成、読み取り、変更をサポートします。
企業開発では Excel ファイルのエクスポートがよく使われるため、ここでは Excel を中心に説明します。
入門例
まず簡単な例を見ます。この技術を使って Excel ファイルを読み取り、書き込みします。
第一歩:依存関係を導入する
<!-- poi と poi-ooxml は、それぞれ .xls と .xlsx ファイルを処理するために使う -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>Excel を書き込む
処理の考え方は、まずメモリ内で Excel 表を作成し、内容を設定します。 その後、出力ストリームでディスクへ書き込みます。
main(){
// メモリ内で Excel 表を作成
XSSFWorkbook excel = new XSSFWorkbook();
// sheet ページを作成
XSSFSheet sheet = excel.createSheet("info");
// 行を作成
XSSFRow row = sheet.createRow(0);
// 行内のセルを作成
XSSFCell cell = row.createCell(0);
// このセルの内容を設定
cell.setCellValue("Name");
row.createCell(1).setCellValue("Age");
// 出力ストリームでディスクへ書き込む。ここでは IOException が発生する可能性がある
FileOutputStream file = new FileOutputStream(new File("D:\\info.xlsx"));
excel.write(file);
// リソースを閉じる
file.close();
excel.close();
}Excel を読み取る
main() {
// 入力ストリームでディスク上の Excel ファイルを読み取る。ここでは IOException が発生する可能性がある
FileInputStream in = new FileInputStream(new File("D:\\info.xlsx"));
// ストリームからこの Excel ファイルのオブジェクトを取得
XSSFWorkbook excel = new XSSFWorkbook(in);
// Excel の sheet ページを読み取る
XSSFSheet sheet = excel.getSheetAt(0);
// 現在ページ内の行を読み取る
XSSFRow row = sheet.getRow(0);
// 現在行のセルを読み取る
XSSFCell cell = row.getCell(0);
// このセルの値を取得
String stringCellValue = cell.getStringCellValue();
System.out.println(stringCellValue);
// リソースを閉じる
excel.close();
fileInputStream.close();
}完全な例
要件:データベースの book テーブル内のすべてのデータを読み取り、スタイル付きの Excel ファイルに保存して、ブラウザへ返してダウンロードさせます(1 行目は表ヘッダー、2 行目からデータベース表と一致)。
要件分析:
- レポートのエクスポートは検索操作であり、パラメータを持つ必要がありません。そのため GET リクエストが適切です。
- エクスポートファイルの本質は、バックエンドが出力ストリームでブラウザへ返し、ブラウザがファイルをダウンロードすることです。
そのため、API 設計ではリクエストパラメータも戻りデータも不要です。 ここではリクエスト URL を
localhost:8080://book/exprot GETとします。
実際の要件では、エクスポートする Excel にセル中央揃え、背景色、文字サイズなどのスタイルが必要です。 すべてを POI コードで書くと非常に面倒なので、Windows システム上で先にテンプレートを作成しておきます。 その後、バックエンドサーバーでテンプレートを読み取り、必要な内容を埋めます。
まずデータベースの具体的な構造を見ます。
CREATE TABLE `book` (
`id` int NOT NULL,
`type` varchar(20) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;データベースに合わせて SpringBoot プロジェクトを作成します(依存関係の導入に注意)。対応する Book エンティティクラス、Controller、Service、Mapper の三層構造を作成します。(簡単なのでここでは省略します)
BookController:
/*
HttpServletResponse オブジェクトは、レスポンス内容を構築してブラウザへ返すために使える。
ファイルダウンロードでは、ファイル内容をストリーム形式で HttpServletResponse の出力ストリームへ書き込み、ブラウザが受信して処理する。
*/
@GetMapping("/export")
public void export(HttpServletResponse response){
bookService.export(response);
}BookService:
@Service
public class BookService {
@Autowired
private BookMapper bookMapper;
public void export(HttpServletResponse response){
// データベース内のすべての図書データを検索
List<Book> books = bookMapper.selectAll();
// レスポンスヘッダーを設定
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("図書一覧.xlsx", "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
try {
// リフレクションでクラスローダーを取得し、クラスパス下の Excel テンプレートを取得
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/ExcelTemplate.xlsx");
// テンプレートファイルを基に新しい Excel ファイルを作成
XSSFWorkbook excel = new XSSFWorkbook(inputStream);
// テンプレートは1ページだけなので、ここでは0を指定
XSSFSheet sheet = excel.getSheetAt(0);
// 1行目は表ヘッダーなので、2行目から書き込む
int rowIndex = 1;
// 検索したすべての book オブジェクトを拡張 for で走査
for (Book book : books) {
XSSFRow row = sheet.getRow(rowIndex++);
row.getCell(0).setCellValue(book.getId());
row.getCell(1).setCellValue(book.getType());
row.getCell(2).setCellValue(book.getName());
row.getCell(3).setCellValue(book.getDescription());
}
// 出力ストリームでブラウザへダウンロードさせる
ServletOutputStream out = response.getOutputStream();
excel.write(out);
// リソースを閉じる
out.close();
inputStream.close();
excel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}