Skip to content

Apache POI

概要

Apache POI は、Java 環境で Microsoft Office 形式のファイルを読み書きするためのオープンソースライブラリです。 Excel、Word、PowerPoint など、複数の Office ファイル形式の作成、読み取り、変更をサポートします。

企業開発では Excel ファイルのエクスポートがよく使われるため、ここでは Excel を中心に説明します。

入門例

まず簡単な例を見ます。この技術を使って Excel ファイルを読み取り書き込みします。

第一歩:依存関係を導入する

xml
<!-- 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 表を作成し、内容を設定します。 その後、出力ストリームでディスクへ書き込みます。

java
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 を読み取る

java
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 システム上で先にテンプレートを作成しておきます。 その後、バックエンドサーバーでテンプレートを読み取り、必要な内容を埋めます。

まずデータベースの具体的な構造を見ます。

sql
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:

java
/*
HttpServletResponse オブジェクトは、レスポンス内容を構築してブラウザへ返すために使える。
ファイルダウンロードでは、ファイル内容をストリーム形式で HttpServletResponse の出力ストリームへ書き込み、ブラウザが受信して処理する。
*/
@GetMapping("/export")
public void export(HttpServletResponse response){
    bookService.export(response);
}

BookService:

java
@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();
        }
    }
}

Released under the MIT License.