Spreadsheet::ParseExcel と UTF-8

hippo2000 さん作成の Spreadsheet::ParseExcel は Excel のワークシートを Perl から直接読むことができるので便利です。Excel ワークシートから DBI 経由で DB にたたき込むスクリプトを書いたりと重宝しています。
でも残念ながらちょっと古いので,内部リテラルは全部 UTF-8 で使ってやろう,といったスクリプトとは少し相性が悪いです。
なので,Encode モジュールを使ったフォーマッタを自作して対処しています。

package Spreadsheet::ParseExcel::FmtEncode;
use strict;
use base qw(Spreadsheet::ParseExcel::FmtDefault);
use Encode;

my %hEncodeMap = (
  ucs2 => 'UCS2-BE',
);

sub new($%) {
  my $sPkg = shift;
  my %hKey = @_;
  my $oThis = $sPkg->SUPER::new;
  $oThis->{NativeCode} = $hKey{NativeCode};
  bless $oThis, $sPkg;
};

sub TextFmt($$;$) {
  my ($oThis, $sTxt, $sCode) =@_;
  return $sTxt unless $sCode;
  if ($sCode eq '_native_') {
    return $sTxt unless $oThis->{NativeCode};
    $sCode = $oThis->{NativeCode};
  }
  $sCode = $hEncodeMap{$sCode} if exists $hEncodeMap{$sCode};
  Encode::decode($sCode, $sTxt);
}

1;

使い方は,

use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtEncode;

my $book = Spreadsheet::ParseExcel::Workbook->Parse(
  'excel_file.xls',
  Spreadsheet::ParseExcel::FmtEncode->new(NativeCode => 'cp932'),
);

my $value = $book->{Worksheet}->[0]->{Cells}[0][0]->Value;

のような感じです。$sCode として _native_ が渡される xls ファイルにお目にかかったことがないので残念ながらその辺はたしかめていません。値のフォーマッタとして S::P::FmtJapan も捨てがたいんで,実際に私が使っているモジュールは FmtJapan を拡張したものになっています。