16bit!

エンジニアじゃなくなっちゃった人が何かを書くブログ

【Java】poiのバージョンが古くて数式が設定されているセルを読み込めない

お仕事にて、Excelファイルの取込処理でエラーが起きたり起きなかったりする事象が発生しました。
調べてみたところ、どうやらExcelを扱うために使っているライブラリであるpoiがバグっていて、数式を含むセルを読み込もうとした際に、エラーが発生することがあるとのこと。

51273 – ArrayIndexOutOfBoundsException in FormulaCellCacheEntrySet

hashCodeがマイナスになるとエラーが発生するようです。
自分で試した時も2回に1回くらい起きてたから、たぶんあってる。

なお、もともとのソースは、

CreationHelper crateHelper = cell.getSheet().getWorkbook().getCreationHelper();
FormulaEvaluator evaluator = crateHelper.createFormulaEvaluator();
colVal = getCellVal(evaluator.evaluateInCell(cell));

こんな感じでした。
EvaluatorのevaluateやevaluateInCellで数式を解析しようとすると駄目っぽい。
また、上記リンク先では「clearAllCachedResultValues()を呼んでね」と書いてありますが、呼んでも駄目でした。

ちなみに、最新のpoiではちゃんと直ってます。

[Apache-SVN] Revision 1128268

よって、poiを新しいのに置き換えれば直るはずなんですが、そこはお仕事プログラミングなので、「poiを置き換えたらpoiを使ってExcel扱ってる機能を全部検証しなおさなきゃいけないじゃないか!」となります。
もちろん置き換えるのが正だと思いますが、そうは言ってもそんな時間はないという場合に、ひとまずFormulaEvaluatorのevaluateやevaluateInCellを使わずに無理矢理取る方法はないものかと考え、書いたのが以下のコード。

try {
  //文字列として取得
  colVal = cell.getStringCellValue();
  break;
} catch (IllegalStateException ignore) {
}
try {
  //数値として取得
  colVal = cell.getNumericCellValue();
  break;
} catch (IllegalStateException ignore) {
}
…

恐ろしい・・・!

あらゆるIllegalStateExceptionを無視しますが、ひとまず目的は達成。
なんか絶対もっといい方法あると思うんですが、オモイツカナカッタデス。


終わり。