いよいよWindows でPerlを使う真骨頂!! MS-OfficeのOLEを用いて、データを取り出したり、加工したりします。
これも、いきなりサンプルソースを提示します。
「excel2text.pl」 適当なExcelファイルが複数入っているフォルダで実行すると、1シート目をTAB区切りテキストにして出力してくれます。
複数のエクセルファイルを順次処理している所等が、参考になるかもです。ファイル名をcp932からエンコードしたり、デコードしたり。
print OUT %en_sjis(......);としている所等。
なお、改行文字はASCIIと同じコードなので、エンコードに含めなくても大丈夫っぽい。
print OUT "\n";
とか。
OLEをPerlから呼び出している所は、Excel VBA を使い慣れた方なら「こんな風にやるんだ~」と、コツがつかめるのではないでしょうか。
そうなんです。Excel VBA そのまんまなんですよ~。Perlでは正規表現や連想配列も使えるので、VBAなんかより、遥かに便利です!
Wordを操作するサンプルは示しませんが、似たような感じでWord VBA が使えますよ。色々試してみてね~
サンプルソース「excel2text.pl」
#!/usr/bin/perl
# excel2text.pl
#必ずソースをUTF-8で記載すること。
use strict;
use Encode;
#use Encode::JP::H2Z;
use utf8;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Excel';
use Win32::OLE::Enum;
binmode STDIN, ":encoding(cp932)"; # 入力なのに、何故かencoding
binmode STDOUT, ":encoding(cp932)";
binmode STDERR, ":encoding(cp932)";
# ファイルハンドル<IN>等からの入力時はdecodeが必要
# ファイルハンドル<OUT>等への出力時はencodeが必要
our $debug=1;
# Excel オブジェクトはグローバル変数として宣言し取得。(そうしないと何個もExcelが開くので)
our $Excel=Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application','Quit');
#Excel ファイルは絶対pathでないと開かないようです。
our $ExcelDir=$0; #実行中のplスクリプトフルパス
$ExcelDir=&de_sjis($ExcelDir);
$ExcelDir=~s/[^\\]+\.pl$//;
&vv('$ExcelDir',$ExcelDir);
opendir (LS,&en_sjis($ExcelDir));
my @fnames=readdir(LS);
for my $FName(@fnames) {
$FName=&de_sjis($FName);
chomp $FName;
if ($FName =~ /\.(xls|xlsx)$/) {
print '$FName=[',$FName,"]\n";
&excel2text($ExcelDir,$FName);
}
}
$Excel->Quit();
print '[Finish!]',"\n";
<>;
exit;
sub excel2text
{
my ($ExcelDir,$ExFileName)=@_;
print 'ExFileName=[',$ExcelDir.$ExFileName,']',"\n";
my $FNameHead=$ExFileName;
$FNameHead=~s/\.(xls|xlsx)$//;
&vv('$FNameHead',$FNameHead);
my $Book=$Excel->Workbooks->Open(&en_sjis($ExcelDir.$ExFileName));
print 'BookName=[',&de_sjis($Book->Name),']',"\n";
my $SheetCnt=$Book->WorkSheets->Count;
print 'SheetCnt=[',$SheetCnt,']',"\n";
# for (my $i=1;$i<=$SheetCnt;$i++) { # 全シート対象の場合
my $i=1; #シート1のみ対象
my $Sheet=$Book->Worksheets($i);
my $SheetName=$Sheet->{'Name'};
$SheetName=&de_sjis($SheetName);
print 'SheetName=[',$SheetName,']',"\n";
my $MaxRow = $Sheet->Cells->SpecialCells(xlCellTypeLastCell)->{'Row'};
my $MaxCol = $Sheet->Cells->SpecialCells(xlCellTypeLastCell)->{'Column'};
print 'MaxRow=[',$MaxRow,']',"\n";
print 'MaxCol=[',$MaxCol,']',"\n";
open (OUT,'>'.&en_sjis($ExcelDir.$FNameHead.'.txt'));
for (my $row=1; $row<=$MaxRow+1; $row++) {
for (my $col=1; $col<=$MaxCol+1; $col++) {
my $str1=$Sheet->Cells($row,$col)->{'Value'};
$str1=&de_sjis($str1);
$str1=~s/(\t|\r|\n)//g; # Tabや改行文字を削除する
print OUT &en_sjis($str1."\t"); # Tab区切りテキストで、出力
}
print OUT "\n";
}
close(OUT);
# }
$Excel->{DisplayAlerts} = 'False';
$Excel->Workbooks->close();
close(OUT2);
}
print '[Finish!]',"\n";
<>;
exit;
#===============================
sub en_jis
{
my ($buf)=@_;
encode('iso-2022-jp',$buf);
}
sub de_jis
{
my ($buf)=@_;
decode('iso-2022-jp',$buf);
}
sub en_sjis
{
my ($buf)=@_;
encode('cp932',$buf);
}
sub de_sjis
{
my ($buf)=@_;
decode('cp932',$buf);
}
sub en_utf8
{
my ($buf)=@_;
encode('utf-8',$buf);
}
sub de_utf8
{
my ($buf)=@_;
decode('utf-8',$buf);
}
sub en_euc
{
my ($buf)=@_;
encode('euc-jp',$buf);
}
sub de_euc
{
my ($buf)=@_;
decode('euc-jp',$buf);
}
sub vv
{
my($Name,$Value)=@_;
if($debug) {
print $Name.'=['.$Value.']',"\n";
}
}
1;