ホーム > 読んだ >

スクリプト言語で手軽にプログラミング
Perl から Win32 を使う

書誌

tagPerl
authortatsuya
publisherソフトバンク
year『C Magazine 2004.8』p.59-64

履歴

editor唯野
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();

参考文献

Up