Perl で Excel を Parse する
Perl で Excel を Parse するときのお約束といえば
- Spreadsheet-ParseExcel
- http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel-0.54/lib/Spreadsheet/ParseExcel.pm
ですよね!
というわけで、今回の話題は Perl で Excel を Parse する方法について。
ただし、Excel にはイタリア語とか、フランス語とか、日本語とか。。。
とにかくイロイロな国の文字が入力されているという、稀によくある状況を想定しています。
が、ハングル文字とかキリル文字とか、アジア圏の文字全部に対応できているかは謎です。
アジアってすごいよね。。。言語的意味で。
ちなみに日本語のみの Excel では、以下のモジュールを使うと便利だそうです。
- Spreadsheet-ParseExcel-FmtJapan
- http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel-0.54/lib/Spreadsheet/ParseExcel/FmtJapan.pm
あんまり利用したことないけれど、きっとこんな感じ。
use Spreadsheet::ParseExcel; use Spreadsheet::ParseExcel::FmtJapan; our $PARSE_FILE = 'hogehoge.xls'; my $excel = Spreadsheet::ParseExcel->new; # Excel を Parse my $book = $excel->Parse($PARSE_FILE, SpreadSheet::ParseExcel::FmtJapan->new); # 1番目のシートを取得 my $sheet = $book->worksheet(0); # Cell の値取得 my $cell = $sheet->get_cell(0, 1); print $cell->value, "\n";
Parse の第2引数として Formatter*1 を指定すれば日本独自の年号とか、(株) とかが入っていても、特に何も考えずに Parse することができるみたいですね。
そのあたりは以下のサイトなどが役に立ちそうです。
- Excelファイル読み込めるSpreadsheet-ParseExcel(Perl)
- http://blog.setunai.net/20080511/excel%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%81%E3%82%8Bspreadsheetparseexcelperl/
でも、こんな文字 → è のように、イタリア語やフランス語、ドイツ語だとうまく Parse できないみたいで *2 文字化け?*3 してしまいました。
というわけで文字化けに対処すべく、以下のモジュールを Formatter として利用しました。
- Spreadsheet-ParseExcel-FmtUnicode
- http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel-0.54/lib/Spreadsheet/ParseExcel/FmtUnicode.pm
が、FmtJapan と違い、ただ Formatter として指定するだけではどうやらダメなようで。。。
しっかり読み込んだ Cell の値を Encode してあげる必要がありました。
また、XML にするので正しい文字参照に変換する必要もあります。
Encode といえば、当然 Encode.pm なんですが。。。
なんかすごいジャストな記事っぽい!
というわけで、
my $result = defined $cell->{Code} ? decode($cell->{Code}, $cell->value, sub{ sprintf "&#%d;", shift }) : decode('ascii', $cell->value, sub{ sprintf "&#%d;", shift });
こんな風にすると、うまく Parse することができました!
$cell->{Code} に Encode 名が入っているんだけれど、define されていない場合は、ASCII として単に処理してあげればいいみたいですね。
わーい。
あ、ただ1つ残ってしまった疑問は、decode を OO で呼び出した場合、つまり
my $enc = find_encoding('ascii'); $enc->encode($strings);
の場合、第3引数?第2引数?が利用することができませんでした。
OO で呼び出した方がコスト的にはメリットがあるそうですが。。。
うーん。この辺はもうすこし調べてみよう。。。