kotlinからExcelを操作する機会があったのでメモ。
コード全文はgitにあげてます。
環境
- JDK: 1.8
- kotlin: 1.3
準備
Apache POIを利用します。
build.gradleのdependenciesに以下の行を追加します。
build.gradle
compile 'org.apache.poi:poi-ooxml:4.1.0'
Workbook,Worksheetの取得
val file = Paths.get("PoiSampleWorkbook.xlsx").toFile()
val book = WorkbookFactory.create(file)
val sheet = book.getSheet("Sheet1")
シート内の全てのデータを読み込む
以下のように行、列をシーケンスとして取得できます。
sheet.rowIterator().asSequence().forEach { row ->
val values = row.cellIterator().asSequence().map { cell ->
when (cell.cellType) {
CellType.NUMERIC -> cell.numericCellValue.toString()
CellType.STRING -> cell.stringCellValue
else -> throw RuntimeException("CellType=${cell.cellType}]")
}
}
println(values.toList())
}
結果
[商品名, 価格]
[商品A, 5000.0]
[商品B, 7000.0]
[商品C, 10000.0]
ちなみに、CellTypeが数値のセルをstringCellValueで取得しようとすると以下のように怒られます。
Exception in thread "main" java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cell
シート内の任意のセルの値を読み込む
データの存在しない行、列を取得しようとするとnullが返されます。
// indexは0オリジン
val row = sheet.getRow(1)
if (row != null) {
val cell = row.getCell(0)
if (cell != null) {
println(cell.stringCellValue)
}
}
結果
商品A
またはCellUtilを利用すれば、存在しないセルを取得してもnullではなく空のセルを取得できます。
// indexは0オリジン
val row = CellUtil.getRow(1, sheet)
val cell = CellUtil.getCell(row, 0)
println(cell.stringCellValue)
// 存在しないセルを指定してもぬるぽにならず、CellType.BLANKのセルが取得できる
val row2 = CellUtil.getRow(999, sheet)
val cell2 = CellUtil.getCell(row2, 999)
println("CellType=${cell2.cellType}, value=${cell2.stringCellValue}")
結果
商品A
CellType=BLANK, value=
拡張関数でVBAっぽく
通常の使い方だとわざわざ行->列の順で取得しないといけないので面倒ですが、kotlinの拡張関数を使えばVBAのCellsっぽいことができます。
fun Sheet.cells(row: Int = 0, col: Int = 0) = CellUtil.getCell(CellUtil.getRow(row, this), col)
fun Cell.value() = when (cellType) {
CellType.NUMERIC -> numericCellValue.toString()
CellType.STRING -> stringCellValue
else -> throw RuntimeException("CellType=$cellType]")
}
println(sheet.cells(1, 0).value())
println(sheet.cells(1, 1).value())
結果
商品A
5000.0
参考