ExcelのUI操作だと行を右クリックでコピーして挿入とかする訳ですが、それと同じことをScalaでやる方法です。
「コピーした行を挿入」みたいな便利メソッドはないので(もしくは、見つけられなかった)、以下の手順を踏みます。
- コピー元の行を取得
- ワークシートに新しい行を追加
- 行を追加する位置以降の行を追加行分ずらす
- 追加した行の各セルに、コピー元セルの
- スタイルをコピー
- セル値をコピー
- マージ状態をコピー
準備
- POIの導入と基本的な読み書きについてはこちらを参照
コピー元の行を取得
import java.io.{File, FileOutputStream}
import org.apache.poi.ss.usermodel._
import org.apache.poi.ss.util.CellRangeAddress
val workbook = WorkbookFactory.create(new File("/path/to/excel"))
val sheet = workbook.getSheetAt(0)
val originalRow = sheet.getRow(0)
新しい行を追加
シート末尾に1行追加します。
val lastRowNum = sheet.getLastRowNum
sheet.createRow(lastRowNum + 1)
行を追加する位置以降の行を下にずらす
行を追加したい位置をstartRowNumber
とすると、そこから下の全行を1行下にずらします。
val startRowNumber = 5
sheet.shiftRows(startRowNumber, lastRowNum + 1, 1)
追加した行のスタイル・セル値を設定
今回はスタイルとタイプ、値のみコピーしていますが、他にもセルのコメントなども必要ならば同じようにコピー&設定します。
val newRow = sheet.getRow(startRowNumber)
for{
index <- 0 until originalRow.getLastCellNum
} {
val originalCell = originalRow.getCell(index)
val newCell = newRow.createCell(index)
// セルのスタイルのコピー
val newCellStyle = workbook.createCellStyle
newCellStyle.cloneStyleFrom(originalCell.getCellStyle)
newCell.setCellStyle(newCellStyle)
// セルタイプのコピー
newCell.setCellType(originalCell.getCellType)
// セル値のコピー
originalCell.getCellType match {
case Cell.CELL_TYPE_BLANK =>
newCell.setCellValue(originalCell.getStringCellValue)
case Cell.CELL_TYPE_BOOLEAN =>
newCell.setCellValue(originalCell.getBooleanCellValue)
case Cell.CELL_TYPE_ERROR =>
newCell.setCellErrorValue(originalCell.getErrorCellValue)
case Cell.CELL_TYPE_FORMULA =>
newCell.setCellFormula(originalCell.getCellFormula)
case Cell.CELL_TYPE_NUMERIC =>
newCell.setCellValue(originalCell.getNumericCellValue)
case Cell.CELL_TYPE_STRING =>
newCell.setCellValue(originalCell.getStringCellValue)
}
}
追加した行にマージ状態を設定
val newRow = sheet.getRow(startRowNumber)
for{
index <- 0 until originalRow.getLastCellNum
} {
// 略
for {
index <- 0 until sheet.getNumMergedRegions
cellRangeAddress <- Option(sheet.getMergedRegion(index)) if cellRangeAddress.getFirstRow == originalRow.getRowNum
} {
sheet.addMergedRegion(new CellRangeAddress(
newRow.getRowNum,
newRow.getRowNum + (cellRangeAddress.getLastRow - cellRangeAddress.getFirstRow),
cellRangeAddress.getFirstColumn,
cellRangeAddress.getLastColumn
))
}
// ファイルに書き出す
val out = new FileOutputStream("/path/to/output")
workbook.write(out)
out.close
}
以上で、行を追加したい位置にコピー元と同じ行が追加されていると思います。
これをちょっとアレンジすれば複数行のコピーもいけます。