Perlモジュールである Spreadsheet::ParseExcel を使って Excelファイル の中身を表示させた時のメモです。

大項目中項目
利用モジュールSpreadsheet::ParseExcel バージョン:0.59
利用Excelファイル名hoge.xls (Office 2010を利用)
Perlスクリプト名example.pl


■説明
Excelファイルからサーバの設定ファイルを自動で生成するツールがPerlで作れたらなぁと思いモジュールをごそごそと探してみたら「Spreadsheet::ParseExcel」を見つけたのでちょっと使ってみました。
実装まではそこまで難しくなかったのですが、とりあえず色々(日本語の取り扱い)あったのでメモっときます。
 


 

(1)Spreadsheet::ParseExcel のインストール

[root@example ~]# cpan -i Spreadsheet::ParseExcel
[root@example ~]# cpan -i Jcode
[root@example ~]# cpan -i Unicode::Map
[root@example ~]# perl -MSpreadsheet::ParseExcel
^C # Ctl+Cで抜ける
[root@example ~]# perl -MJcode
^C # Ctl+Cで抜ける
[root@example ~]# perl -MUnicode::Map
^C # Ctl+Cで抜ける

問題無くインストールされたかハイライト部分のコマンドを実行してエラーが発生しないことを確認する。
# Jcode と Unicode::Map は日本語取扱いのためにインストールする。
 

(2)スクリプトを作成

#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel;

my $input_file = $ARGV[0];
my $parser   = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse($input_file);

for my $worksheet ( $workbook->worksheets() ) {

        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();

        for my $row ( $row_min .. $row_max ) {
                for my $col ( $col_min .. $col_max ) {

                        my $cell = $worksheet->get_cell( $row, $col );
                        next unless $cell;
                        my $cell_in = $cell->value();

                        print "[$row][$col] : $cell_in", "\n";
                }
        }
}

 

(3)Excel でファイルを作成

作成したファイルは以下のようなものです。

・作成したExcel(hoge.xls)の中身
Excelの中身

作成したExcelファイルをアップロードします。
 

(4)実行してみる

[root@example ~]# ./example.pl hoge.xls
[0][0] : a
[0][1] : b
[0][2] : c
[1][0] : d
[1][1] : e
[1][2] : f
[2][0] : g
[2][1] : h
[2][2] : i

結果を見る限り表の扱いはこんな感じ。
col[umn](列)、row(行)
Excelの中身2
 

(5)Excelファイルに日本語を入れてみる

Excelの中身3
 

(6)実行してみる2

[root@example ~]# ./example.pl hoge.xls
[0][0] : a
[0][1] : b
[0][2] : c
[1][0] : d
[1][1] : e
[1][2] : f
[2][0] : g
[2][1] : h
[2][2] : i
Wide character in print at ./example.pl line 22.
[3][0] : テスト

ハイライト部分のようなエラーが出たのでスクリプトを改修する。
 

(7)スクリプトの改修

#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtJapan2;

my $input_file = $ARGV[0];
my $format = Spreadsheet::ParseExcel::FmtJapan2->new(Code => 'utf8');
my $parser   = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse($input_file, $format);

for my $worksheet ( $workbook->worksheets() ) {

        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();

        for my $row ( $row_min .. $row_max ) {
                for my $col ( $col_min .. $col_max ) {

                        my $cell = $worksheet->get_cell( $row, $col );
                        next unless $cell;
                        my $cell_in = $cell->value();

                        print "[$row][$col] : $cell_in", "\n";
                }
        }
}

ハイライト部分を追加しました。
 

(8)実行してみる3

[root@example ~]# ./example.pl hoge.xls
Use of uninitialized value in -r at /usr/local/share/perl5/Spreadsheet/ParseExcel/FmtJapan2.pm line 32.
NO MAP FILE CP932Excel!! at /usr/local/share/perl5/Spreadsheet/ParseExcel/FmtJapan2.pm line 32.

ううむ、エラーが発生。
どうも、「CP932Excel」が無いと言っているようで調べてみると、Unicode::Map にはデフォルトで付属しなくなったようです。(CP932に置き換わったみたい)
解決方法は無いものかと思っていたら Speadsheet::ParseExcel の README_Japan.htm に解決方法がありました。(参考文献2参照)
と、言う事で早速解決方法を試してみます。
 

(9)解決方法の実行

README_Japan.htm によれば Speadsheet::ParseExcel の Ver:0.09 から CP932Excel は同梱されているようなのでそれをコピーします。

[root@example ~]# cp .cpan/build/Spreadsheet-ParseExcel-0.59-uP1f3J/CP932Excel.map /usr/local/lib64/perl5/Unicode/Map/MS/WIN/
[root@example ~]# chmod 444 /usr/local/lib64/perl5/Unicode/Map/MS/WIN/CP932Excel.map

そして、Unicode::Map の REGISTRY に以下を追加します。

[root@example ~]# vi /usr/local/lib64/perl5/Unicode/Map/REGISTRY
(snip)
name:    CP932
srcURL:  $SrcUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT
src:     $DestUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT
map:     $DestMap/MS/WIN/CP932.map

name:    CP932Excel
srcURL:  $SrcUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT
src:     $DestUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT
map:     $DestMap/MS/WIN/CP932Excel.map
:wq! <- 強制書き込み保存

ここでは、CP932 の下あたりに追加しました。
 

(10)実行してみる4

[root@example ~]# ./example.pl hoge.xls
Attempt to bless into a reference at /usr/local/share/perl5/Spreadsheet/ParseExcel/FmtJapan.pm line 96.

まだ、エラーが出るんかい!
調べてみると、文字列化されたものにblessをしようとすると上記のようなエラーになるので以下のように96行目を修正

・修正

[root@example ~]# vi /usr/local/share/perl5/Spreadsheet/ParseExcel/FmtJapan.pm
    return bless $self, $class;
↓ # 修正
    return bless $self, "$class";
:wq! <- 強制書き込み保存

 

(11)実行してみる5

[root@example ~]# ./example.pl hoge.xls
[0][0] : a
[0][1] : b
[0][2] : c
[1][0] : d
[1][1] : e
[1][2] : f
[2][0] : g
[2][1] : h
[2][2] : i
[3][0] : テスト

はい、出来ました:)
ちなみに、ここでは xls(Excel 97-2003)しかサポートされないやり方でやっています。
xlsx を使う場合は Spreadsheet::XLSX が必要です。
 

参考文献

1. http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel-0.59/lib/Spreadshee
t/ParseExcel.pm

2. http://cpansearch.perl.org/src/KWITKNR/Spreadsheet-ParseExcel-0.2603/README
_Japan.htm

3. http://perldoc.jp/docs/perl/5.8.8/perldiag.pod


2月 11, 2013 at 12:24 am by 黒ぶちメガネ
Category: Linux, Perlスクリプト