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でゴメンナサイ
なお、数字の部分ですが、数値扱いっぽく表示されるのですが、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
とりあえず、思い通りにいくかどうかはさておき、少しは設定可能だということがわかりました。