CLOVER🍀

That was when it all began.

Apache POIでExcelの書式を設定する

POIでExcelを出力する時に、(考えたくないですが)先頭を0埋めにした数字を入力して、セルの書式としては「文字列」設定して「0落ち」をさせたくない、という話がありまして。

よく見かける下記の表現では、書式は変わりませんしね。

cell.setCellType(Cell.CELL_TYPE_STRING);

POIで書式を設定するには、どうするのかなぁ?ということで、ちょっと調べてみました。

回答。
http://poi.apache.org/faq.html#faq-N100C7
http://poi.apache.org/spreadsheet/quick-guide.html#DataFormats

DataFormatというものを使いなさい、と。

試してみます。

Maven依存関係。

    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.11</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.11</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml-schemas</artifactId>
      <version>3.11</version>
    </dependency>

プログラム。
src/main/java/org/littlewings/poi/App.java

package org.littlewings.poi;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.IntStream;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
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.xssf.streaming.SXSSFWorkbook;

public class App {
    public static void main(String... args) {
        try (Workbook workbook = new SXSSFWorkbook();
             OutputStream os = Files.newOutputStream(Paths.get("sample.xlsx"))) {
            DataFormat dataFormat = workbook.createDataFormat();

            CellStyle textStyle = workbook.createCellStyle();
            textStyle.setDataFormat(dataFormat.getFormat("text"));
            CellStyle numberStyle = workbook.createCellStyle();
            numberStyle.setDataFormat(dataFormat.getFormat("0"));


            Sheet sheet = workbook.createSheet("NewSheet");

            IntStream.rangeClosed(0, 10).forEach(rowIndex -> {
                Row row = sheet.createRow(rowIndex);

                Cell cell1 = row.createCell(0);
                // cell1.setCellType(Cell.CELL_TYPE_STRING);
                cell1.setCellStyle(textStyle);
                cell1.setCellValue(String.format("%010d", rowIndex + 1));

                Cell cell2 = row.createCell(1);
                // cell1.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell2.setCellStyle(numberStyle);
                cell2.setCellValue(rowIndex + 1);
            });

            workbook.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Cell#setCellTypeは、なんとなくコメントアウト…。そして、なぜかSXSS形式。

ちょっと説明ですが、DataFormatを作成して

            DataFormat dataFormat = workbook.createDataFormat();

DataFormatから利用したいフォーマットを指定して対応するフォーマットの値(short)を取得し、CellStyleに指定します。

            CellStyle textStyle = workbook.createCellStyle();
            textStyle.setDataFormat(dataFormat.getFormat("text"));
            CellStyle numberStyle = workbook.createCellStyle();
            numberStyle.setDataFormat(dataFormat.getFormat("0"));

あとは、そのCellStyleをCellに適用すればOK。

                Cell cell1 = row.createCell(0);
                // cell1.setCellType(Cell.CELL_TYPE_STRING);
                cell1.setCellStyle(textStyle);
                cell1.setCellValue(String.format("%010d", rowIndex + 1));

                Cell cell2 = row.createCell(1);
                // cell1.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell2.setCellStyle(numberStyle);
                cell2.setCellValue(rowIndex + 1);

一応、テキストと数字です。

実行して、できあがったファイル。
LibreOfficeでゴメンナサイ

0埋めして数字を入れた部分の書式は、このように。

なお、数字の部分ですが、数値扱いっぽく表示されるのですが、Excelで書式を確認すると「ユーザー定義」扱いになっていました…。

DataFormat#getFormatで指定する値についてですが、BuiltinFormatsを参照すればよいでしょう。
http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/BuiltinFormats.html

「text」は、「@」のエイリアスのようです。

他にも、「0.00」や「d-mmm-yy」などが指定できるようですね。このあたりが、ユーザー定義として扱われるんだろうなぁと思ったり。「General」が標準?

HSSF形式の場合は、独自で定義しているような感じ?ですが、BuiltinFormatsとそう変わらないようにも見えます。
https://github.com/apache/poi/blob/REL_3_11_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java

とりあえず、思い通りにいくかどうかはさておき、少しは設定可能だということがわかりました。