Java POIでExcel出力後に関数を再計算させる方法
JavaのPOIでExcel出力後に関数を再計算させる方法です。
Java上で作ったExcel用の計算式をsetCellFormulaで出力したものの再計算がされていない状態だった。出来上がったセルをダブルクリックして編集すると式を変更することなく再計算がおこなわれた。どうもPOIには再計算させるメソッドが用意されているようで、そいつをコールしないといけないみたい。
ここでは JavaのPOIでExcel出力後に関数を再計算させる方法 を紹介します。
POIで再計算の設定をする
POIのドキュメントによると Sheet.setForceFormulaRecalculation(true)
で再計算してくれるようです。
複数シートを作った場合には、ブック全体を再計算させる Workbook.setForceFormulaRecalculation(true)
を使えばいいみたい。
// 全シート再計算
workbook.setForceFormulaRecalculation(true);
// シート別に再計算
sheet.setForceFormulaRecalculation(true);
計算式によっては再計算させるまでもなく計算してくれる場合もある。たとえば setCellFormula(SUM(A1:B1)) みたいな単純なものなら上記コードは書かなくても計算してくれた。実務ではIF文とVLOOKUP文を組み合わせた計算式を出力したときは計算してくれませんでした。なので setForceFormulaRecalculation
のコードを書いたら再計算してくれました。条件があるのかなー、よくわからん。
検証ソース
とりあえずこのコードは再計算されます。
package excelout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
public class PoiRecalculation {
@Test
public void poiRecalcChk() throws Exception {
// ファイルパス設定
String dir = Thread.currentThread().getContextClassLoader().getResource("").getPath();
System.out.println(dir);
String templatePath = dir + "Book1.xlsx";
String resultPath = dir + "result_Book1.xlsx";
// テンプレートファイル取得
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(templatePath));
XSSFSheet sheet = workbook.getSheet("Sheet1");
XSSFRow row = sheet.createRow(0);
// 全シート再計算
workbook.setForceFormulaRecalculation(true);
// シート別に再計算
sheet.setForceFormulaRecalculation(true);
// データセット
int colNum = 0;
row.createCell(colNum++).setCellValue(1);
row.createCell(colNum++).setCellValue(2);
row.createCell(colNum++).setCellFormula("IF(A4=\"\",\"\",SUM(A1:B1))");
// ワークブックを保存
workbook.write(new FileOutputStream(new File(resultPath)));
// クローズ
workbook.close();
}
}
まとめ
JavaのPOIでExcel出力後に関数を再計算させる方法を紹介しました。
結局、検証では setForceFormulaRecalculation
なしで再計算される条件と再計算されない条件がわかりませんでした。実務で使った時には setForceFormulaRecalculation
をしないと再計算してくれなかったので、とりあえず計算式を組み込んだら明示的に書くようにしようと思います。誰か条件を知ってる方がいればコメントお待ちしています。
おつかれさまでした。