LoginSignup
0
1

More than 5 years have passed since last update.

poiでCreateCellStyleを連発するのは辞めた方が良い話

Posted at

poiでセルにスタイルを作る場合、大抵CreateCellStyleを行います。

が・・・

ちょっとトラップがあります。

Excelの仕様

知っている方は知っていますが、Excelの仕様として
1Bookで作れるスタイルには上限があります。

最大スタイル数 最大行数
2003 4000 65,536
2007 64000 1,048,576
2010 64000 1,048,576
2016,2013 64000 1,048,576

2003だけ最大スタイル数も行数も違います。
相手がどのバージョンのエクセルで開くかわからない場合上記に注意して作った方がいいかも知れません。

これだけ見るとpoiで作る場合でも
2003だったら、4000を超えるcreateCellStyle()を
2007以上だったら、64000を超えるcreateCellStyle()をしなければいいんだ:bulb:

と思い勝ちですが、ここに大きな落とし穴があります。

ループの中で回した場合の挙動 ~XSSF~

では検証してみます。
通常ループの中でcreateCellStyle()をnewする事は少ないと思いますが
独自のキャッシュ機構を入れたり、処理上どうしても入れたいって事がない事もないと思います。

for (int i = 0; i < 100; i++){
    CellStyle cs  = workbook.createCellStyle();
    Cell cell = row.createCell(i);
    cs.setBorderLeft(BorderStyle.THIN);
    cs.setBorderTop(BorderStyle.THIN);
    cs.setBorderRight(BorderStyle.THIN);
    cs.setBorderBottom(BorderStyle.THIN);
    cell.setCellStyle(cs);
}

これを実行すると・・・
image.png

はい、まぁ予想通りです。

ループの中で回した場合の挙動 ~HSSF~

問題はこっちです。HSSFはxls形式に対応している為
古いプロジェクトやxlsx形式だと不都合がある場合に良く使われます。

for (int i = 0; i < 100; i++){
    HSSFCellStyle cs  = workbook.createCellStyle();
    HSSFCell cell = row.createCell(i);
    cs.setBorderLeft(BorderStyle.THIN);
    cs.setBorderTop(BorderStyle.THIN);
    cs.setBorderRight(BorderStyle.THIN);
    cs.setBorderBottom(BorderStyle.THIN);
    cell.setCellStyle(cs);
}

一見すると、型以外さっきのソースと全く同じで100番目のカラムまで罫線でかこまれそうですが・・

image.png

おや・・。?

結論と対策

タイトル通り、CreateCellStyleはループ内で使用すべきではない。
apache側も打開作として、CellUtilという便利なものを出してくれていますので、こちらを使うのが良さそうです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1