Excel大好き日本企業にシステムを納めるJava大好きSIerとして働いている以上、避けては通れないのがApache POI。POIはExcelのセルを抽象化したCell
というクラス(インタフェース)を持つのですが、このCell
から値を取り出すのが意外と面倒。とりわけ__セルの表示形式(CellType
)に合わせてメソッドを呼び分ける必要があり、かつCellType
に合致しないメソッドを呼び出した場合は即座に例外を投げる__という仕様には何度苦しめられたことか(´・ω・`)
そこで__CellType
を問わず、透過的にセルの値を取得できるユーティリティメソッド__を準備しておくことにしました。なお簡単な仕様としては以下の通りです。
- POIがサポートする
CellType
のうちBLANK
,BOOLEAN
,NUMERIC
,STRING
のみを対象とする。ただし日付についてもサポートする。 - 戻り値は
Object
型とする。キャストするなりString#valueOf
なり好きにすること。 - サポートしない
ERROR
とFORMULA
の場合は例外を送出する- 以下はサンプルのため
RuntimeException
を投げているが、実際に利用する場合はちゃんとした例外(?)をスローすること。
- 以下はサンプルのため
-
null
安全ではない。つまり引数がnull
の場合はNullPointerException
を投げる。また万が一に備えてPOIがサポートしていないCellType
のセルが引数と渡された場合も例外とする。
package my.excel;
import java.util.Objects;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
final public class CellUtils {
public static Object getCellValue(Cell cell) {
Objects.requireNonNull(cell, "cell is null");
CellType cellType = cell.getCellTypeEnum();
if (cellType == CellType.BLANK) {
return null;
} else if (cellType == CellType.BOOLEAN) {
return cell.getBooleanCellValue();
} else if (cellType == CellType.ERROR) {
throw new RuntimeException("Error cell is unsupported");
} else if (cellType == CellType.FORMULA) {
throw new RuntimeException("Formula cell is unsupported");
} else if (cellType == CellType.NUMERIC) {
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
} else {
return cell.getNumericCellValue();
}
} else if (cellType == CellType.STRING) {
return cell.getStringCellValue();
} else {
throw new RuntimeException("Unknow type cell");
}
}
}
では実際に利用してみましょう(´・ω・`) まずは次のようなsample.xlsx
を用意します。
あとは次のようなコードを書いて、正しく読み込めるかどうかを確認してみます。
package my.excel;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
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;
public class Main {
public static void main(String ... args) {
Path path = Paths.get("C:\\hogehoge\\sample.xlsx");
try (Workbook workbook = WorkbookFactory.create(Files.newInputStream(path))) {
Sheet sheet = workbook.getSheetAt(0);
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
Cell cell = row.getCell(1); // B列のセルを取得する。
Object value = CellUtils.getCellValue(cell);
System.out.println(value);
}
} catch (IOException
| InvalidFormatException
| EncryptedDocumentException e) {
e.printStackTrace();
}
}
}
コンパイルして実行した結果を確認してみると――確かに想定通り機能していることがわかります。やったね(´・ω・`)
ABC
true
100.0
Mon Jan 02 00:00:00 JST 2017