Perl から Win32 を使う
書誌
| tag | Perl |
| text | 唯野 |
| author | tatsuya |
| publisher | ソフトバンク |
| year | 『C Magazine 2004.8』p.59-64 |
履歴
| 2004.11.7 | 読了 |
| 2004.11.11 | 公開 |
| 2005.1.4 | 修正 |
| 2012.1.17 | タグ追加 |
感想
ActivePerl が 5.6 でサポートした Win32 系モジュールを用いた Perl スクリプトにおける Win32 API の使用、OLE 経由による Word/Excel へのアクセスについてを扱った記事。個人的に Excel ファイルへの Perl からのアクセスについては、以前 Spreadsheet::WriteExcel、Spreadsheet::ParseExcel を試みて失敗した経験があったため(参考文献にある IBM のドキュメントによると、これは IO::Scalar の利用できないのが原因とある)、それきりとなってしまっていたが、今回、Win32::OLE を利用することによりこれができたので取り上げる。
但し、私が Win32::OLE から Excel へアクセスするプログラムを書いてみたところ、Perl スクリプトからだと問題ないのに CGI からこれを呼び出すと失敗するケースがあった。きちんとした原因まで把握できていないのだが、少なくともオープンする Excel ファイルのパスは / ではなく \ で区切らないとアプリケーション・オブジェクトの取得に失敗するようである。(環境は Windows2000 SP4、Apache for Win32 2.0.52、ActivePerl 5.8.4 build 810。)
抄録
60-61
Perl から Win32 API を利用するためには PPM で以下のように追加モジュールのインストールが必要。これらは ActiveState にドキュメントがある。
> ppm ・・・ PPM> install Win32-API ・・・ PPM> exit
61
Win32 でシステム情報を取得するプログラムのサンプル。コードを見ると分かるように手順は、必要なモジュールのインポート -> 必要とする API の取得 -> 受取値の器の定義 -> API の呼び出しと結果の器への代入――となる。
# メモリ情報の取得
use strict;
use Win32::API;
my $GlobalMemoryStatus =
new Win32::API(
"Kernel32", "GlobalMemoryStatus", ["P"], "V") || die;
my $mem_sts = pack "L8", (0, 0, 0, 0, 0, 0, 0, 0);
my %mem;
my @mem_param = qw(
Length, MemoryLoad, TotalPhys AvailPhys TotalPageFile
AvailPageFile TotalVirtual AvailVirtual);
$GlobalMemoryStatus->Call($mem_sts);
@mem{@mem_param} = unpack "L8", $mem_sts;
print "全物理メモリ : $mem{'TotalPhys'} Bytes\n";
print "空物理メモリ : $mem{'AvailPhys'} Bytes\n";
print "全ページファイル : $mem{'TotalPageFile'} Bytes\n";
print "空ページファイル : $mem{'AvailPageFile'} Bytes\n";
print "全仮想メモリ : $mem{'TotalVirtual'} Bytes\n";
print "空仮想メモリ : $mem{'AvailVirtual'} Bytes\n";
# OS バージョンの取得
use strict;
use Win32::API;
my $GetVersionEx =
new Win32::API(
"Kernel32", "GetVersionEx", ["P"], "N") || die;
my $os_ver = pack "LLLLLa128", (148, 0, 0, 0, 0, "\0"x128);
my %ver;
my @ver_param = qw(
OSVersionInfoSize MajorVersion MinorVersion
BuildNumber PlatformId);
die if(! $GetVersionEx->Call($os_ver));
@ver{@ver_param} = unpack "LLLLLa128", $os_ver;
print "メジャーバージョン : $ver{'MajorVersion'}\n";
print "マイナーバージョン : $ver{'MinorVersion'}\n";
print "ビルド番号 : $ver{'BuildNumber'}\n";
print "プラットフォームID : $ver{'PlatformId'}\n";
62-64
次いで Excel データ読み書きの例。手順は必要なモジュールのインポート -> 指定された OLE インスタンスに対するリファレンスの取得(このとき Excel が起動していなければ新規にインスタンスを生成する) -> アクセスするブックとシートとセルの指定――となる。Word でも基本的な流れは同じ。これらは Office 関連 VBA メソッドのラッパになっているので MSDN から情報を得ることができる。
# Excel の読み書き
use strict;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Excel';
my $excel = Win32::OLE->GetActiveObject('Excel.Application') ||
Win32::OLE->new('Excel.Application', 'Quit') || die;
# 新規ブックなら $excel->Workbooks->Add() でよい
my $book = $excel->Workbooks->Open('c:\home\src.xls') || die;
my $sheet = $book->Worksheets('Sheet1') || die;
# 単一のセル
$sheet->Cells('5', 'D')->{'Value'} = 1;
my $val = $sheet->Cells('5', 'D')->{'Value'};
# 範囲指定されたセル
$sheet->Range('A1:C4')->{Value} = [
['a', 'b', 'c'],
[1, undef, 3],
["あ", "い", "う"]];
# 配列リファレンスとして取得
my $array = $sheet->Range('A1:C4')->{Value};
# 保存とブックのクローズ
$Excel->{DisplayAlerts} = 'False'; # 警告非表示
$book->SaveAs('c:\home\dest.xls');
$book->Close();
# Word の読み書き
use strict;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Word';
my $word = Win32::OLE->GetActiveObject('Word.Application') ||
Win32::OLE->new('Word.Application', 'Quit') || die;
# 読み込み
my $doc = $word->Documents->Open('c:\home\read.doc') || die;
my $paras = $doc->Paragraphs;
foreach (in $paras)
{
print $_->Range->{'Text'} . "\n";
}
$doc->Close();
# 書き込み
$doc = $word->Documents->Add() || die;
my $range = $doc->{'Content'};
$range->{'Text'} = 'ABC';
$range->InsertParagraphAfter();
$range->InsertAfter('123');
$range->InsertParagraphAfter();
$range->InsertAfter("あいう");
$range->InsertParagraphAfter();
$doc->SaveAs('c:\home\write.doc');
$doc->Close();
64
最後は Wave ファイル再生の例。
# Wave 再生
use strict;
use Win32::Sound;
my ($hz, $bit, $ch) = Win32::Sound::Format(
'c:\home\sample.wav') || die;
print "sample.wav : $hz Hz, $bit bits, $ch Channels\n";
# 再生
Win32::Sound::Play('c:\home\sample.wav');
# ボリューム
Win32::Sound::Volume('50%');
# 停止
Win32::Sound::Stop();
