使ったバージョンは当時最新だった3.0系でした。
このPOIではまったので書いておきます。
#POIにはRuby版もありますが、開発当時はまだ安定していないとのことで、RJB経由でJava版のPOIを使うことにしました。
***********************
【現象】
該当Excelに複雑な画像や大量の画像、リンク貼付をされている画像があるファイルを処理すると出力後のExcelファイルが壊れてしまう。
[1]JavaPOIを通じてExcelファイルを処理したら例外が発生する。※1
→1.7Mバイト(画像やらオートシェイプやらが貼り付けられている)ファイルで発生します。
例外は「Unable to construct record instance」というものです。
[2]ファイルが壊れて表示される。
→上記ファイルからいくつかの画像を削除したファイルで発生します。
この場合、罫線やセル結合、画像がなくなっています。
入力された文字情報は表示されています。
[3]正しく処理されるファイルもある。
→上記ファイルから全ての画像を削除するとうまく行きます。
【処理内容概略】
サーバ上のfolder1にあるExcelファイル(このファイルにリンク貼り付けの画像等がある)をrjb経由でJavaPOIで以下の処理をします。
1:inputStreamで開く。
2:データをセットして、サーバ上のOUTPUT_folderにoutputstreamでExcelとして出力する。
【ソース】
require 'rjb'
Rjb::load("#{RAILS_ROOT}/lib/poi-3.1-beta1-20080428.jar")
jPOIFSFileSystem = Rjb::import("org.apache.poi.poifs.filesystem.POIFSFileSystem")
jFileInputStream = Rjb::import("java.io.FileInputStream")
jHSSFWorkBook = Rjb::import("org.apache.poi.hssf.usermodel.HSSFWorkbook")
jFileOutputStream = Rjb::import("java.io.FileOutputStream")
begin
# 入力ファイルの設定
fi = jFileInputStream.new(filename)
# POIファイルシステムの設定
fs = jPOIFSFileSystem.new(fi)
# Excelワークブックの取得
wb = jHSSFWorkBook.new(fs,true) #<= ※1例外が発生(132行目)
# 出力ファイルの設定
fo = jFileOutputStream.new("#{RAILS_ROOT}/tmp/#{output_file}")
# シートを取得
sheet = wb.getSheetAt(sheet_num)
wb.setBackupFlag(true)
return false unless sheet
# テンプレートファイルの文字列を置換する
replace_cell_data(sheet, max_row, max_col, map, lang)
wb.setSelectedTab(sheet_num)
# 出力ファイルへデータを書き出す
wb.write(fo)
ensure
# 入力、出力それぞれのファイルをクローズする
fo.close if fo
fi.close if fi
【バージョン】
ruby:1.8.6
Rails:1.2.3
JavaPOI:poi-3.0.2-FINAL/poi-3.1-beta1-20080428 ※同じ現象
Office:Office2003 SP3
【解決案】
根本的な解決ではないが、POIのバージョンを3.0.1から2.0に変更する。
【根拠】
poi3.0系では画像、複雑なオブジェクト等があると修復できないエラーが発生する場合があるようです。
【参考情報】
[1]「Apache POI で式などを含む Excel を保存すると修復できないエラーが発生する」
[2]補足情報
URL:http://www.javaroad.jp/bbs/answer.jsp?q_id=20080331092827399
URL:http://d.hatena.ne.jp/S_a_k_U/searchdiary?word=*%5BPOI%5D
***********************
今回は解決できましたが、外部ライブラリを使う際には「そもそも、使う必要があるのか?」という点からちゃんと検討して、その特性を理解しないとあかんなぁと再認識しました。