Excel 2007形式(XLSX)のファイルをPerlで扱う必要があったので調べてみると、「Spreadsheet::XLSX」というモジュールを見付けた。
Spreadsheet::XLSX – search.cpan.org
http://search.cpan.org/~dmow/Spreadsheet-XLSX-0.12/lib/Spreadsheet/XLSX.pm
そして次のようにXLSX形式のファイルを用意してスクリプトを実行してみたのだが、セルの値にフリガナがくっついて表示されてしまう1。

#!/usr/bin/perl -l
use Spreadsheet::XLSX;
my $excel = Spreadsheet::XLSX->new( "Book1.xlsx" );
my $sheet = $excel->{Worksheet}[0];
print $sheet->{Cells}[0][0]{Val};
実行結果
$ perl readexcel.pl 文字列モジレツ
XLSX形式についてよく知らなかったのでまずはそこから調べてみた。
【OpenXML】Excel 2007では文字列はプールされブック全体で共有される
http://blogs.wankuma.com/nagise/archive/2008/01/25/119214.aspx
XLSX形式のファイルは複数のXMLファイルをZIPで固めたものとなっている。そのうち、「sheetXXX.xml」がシートの本体で、そこに含まれる文字列は「sharedStrings.xml」という別ファイルにある。上記ファイルの「sharedStrings.xml」を整形して書き出してみると次のようになる。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1">
<si>
<t>文字列</t>
<rPh sb="0" eb="3">
<t>モジレツ</t>
</rPh>
<phoneticPr fontId="1"/>
</si>
</sst>
実際の文字列とは別に、<rPh>タグを使ってフリガナが納められているようだ。件のモジュール「Spreadsheet::XLSX」にフリガナを扱う機能はないのだから、これを無視するように変更するしかない。
Spreadsheet::XLSX
foreach my $si ($mstr =~ /<si.*?>(.*?)<\/si/gsm) {
+ $si =~ s!<rPh[^>]*>.*?</rPh>!!gsm;
my $str;
foreach my $t ($si =~ /<t.*?>(.*?)<\/t/gsm) {
$t = $converter -> convert ($t) if $converter;
*** XLSX.pm.orig 2010-03-29 13:26:54.000000000 +0900
--- XLSX.pm 2010-03-29 13:28:49.000000000 +0900
***************
*** 32,37 ****
--- 32,38 ----
my $mstr = $member_shared_strings->contents;
$mstr =~ s/<t\/>/<t><\/t>/gsm; # this handles an empty t tag in the xml <t/>
foreach my $si ($mstr =~ /<si.*?>(.*?)<\/si/gsm) {
+ $si =~ s!<rPh[^>]*>.*?</rPh>!!gsm;
my $str;
foreach my $t ($si =~ /<t.*?>(.*?)<\/t/gsm) {
$t = $converter -> convert ($t) if $converter;
これで正常にファイルが読めるようになった。
$ perl readexcel.pl 文字列
- 下記スクリプトはUTF-8環境じゃないと文字化けします。 ↩

Pingback: Spreadsheet::XLSXでValの値についてしまうフリガナを除去 | PSLブログ(仮)