by Hippo2000(2001/2/20)
PerlからExcelだろうがWordだろうが自由に扱えるというWin32::OLEモジュールです。
Copyrightの先頭にあるMicrosoftの文字が光りますね。Jan Duboisさんにはメールで了解をいただきました。
内容等が間違っていたら修正します。ご連絡ください。
Win32::OLE - OLEオートメーション拡張
$ex = Win32::OLE->new('Excel.Application') or die "oops\n";
$ex->Amethod("arg")->Bmethod->{'Property'} = "foo";
$ex->Cmethod(undef,undef,$Arg3);
$ex->Dmethod($RequiredArg1, {NamedArg1 => $Value1, NamedArg2 => $Value2});
$wd = Win32::OLE->GetObject("D:\\Data\\Message.doc");
$xl = Win32::OLE->GetActiveObject("Excel.Application");
このモジュールはPerlからのOLEオートメーションへのインターフェースを提供します。OLEオートメーションはVisualBasicのようなスクリプトの能力を提供し、強力な拡張性とPerlスクリプトから数多くのWin32アプリケーションを制御する能力を提供します。
Win32::OLEモジュールはIDispatchインターフェースを独占的に使用します。カスタムOLEインターフェースにアクセスすることはできません。OLEインベントとOCXは現在のところサポートされていません。
実際には、これは厳密には正しくありません。このモジュールはOLEイベントをアルファレベルでサポートをしています。これはあまりテストされていませんし、インタフェース仕様は将来変更される可能性があります。
new()
クラス・メソッドはOLEオートメーション・オブジェクトの新しいインスタンスを開始します。このオブジェクトのリファレンスか、もし作成が失敗すればundefを返します。PROGID 引数は必要なアプリケーションのOLEプログラムIDまたはクラスIDでなければなりません。オプションのDESTRUCTORにはDESTROYのようなメソッドを指定します。これはCODEリファレンスまたはOLEメソッド名の入った文字列のどちらかにすることができます。これはPerlプログラムが死ぬ(die)するときに、OLEアプリケーションをきれいに終らせるために使われます。
DCOMを通じてリモート・サーバーにオブジェクトを作成するためには、PROGIDのところに配列リファレンスを使うことができます。参照される配列にはマシン名とログラムIDまたはクラスIDが入らなければなりません。例えば:
my $obj = Win32::OLE->new(['my.machine.com', 'Program.Id']);
PROGIDがプログラムであれば、Win32::OLEはローカルに対応するクラスIDを解決しようとします。もしローカルにプログラムIDが登録されていなければ、リモート・レジストリが問い合わせられます。これはローカルなプロセスがリモート・レジストリに読み込みアクセスをもっているときにのみ成功します。もっとも安全な(そしても最も速い)方法は、クラスIDを直接指定することです。
EnumAllObjects([CALLBACK])
$Count = Win32::OLE->EnumAllObjects(sub {
my $Object = shift;
my $Class = Win32::OLE->QueryObjectType($Object);
printf "# Object=%s Class=%s\n", $Object, $Class;
});
EnumAllObjects()
メソッドは主にデバッグのためのツールです。これは例えば、すべての外部コメンクションが適切に破壊されているかをチェックするためにENDブロックに入れて使うことができます。
FreeUnusedLibraries()FreeUnusedLibraries()
クラス・メソッドは使われていないOLEリソースのすべてをアンロードします。これらは破壊されたすべての存在しているオブジェクトのクラスのライブラリです。オブジェクト・ライブラリのアンロードは、長時間とても多くの異なるオブジェクトを繰り返し、インスタンス生成するプロセスを実行したときにだけ本当に重要です。Visual
Baiscで実装されたオブジェクトはこの機能についてバグを持っているかもしれないことに注意してください。実際に彼らのクリーンアップ・コードを実行するまではアンロード可能にすることを拒みます。その時点でDLLをアンロードすることは典型的には、アクセス・バイオレーションを発生させます。この問題の可能性はSpinMessageLoop()
メソッドを呼び出し、2、3秒sleep()することにより減らすことができます。
GetActiveObject()
クラスメソッドは指定されたOLEオートメーション・サーバーの動いているインスタンスへのOLEリファレンスを返します。もしサーバーが現在アクティブでなければ、undefを返します。そのクラス登録さえもしていなければ、croakします。オプションのDESTRUCTORメソッドはメソッド名、あるいはコード・リファレンスをとります。このオブジェクトへの最後のリファレンスが失われるときに実行されます。一般的にあなたが起動したのではないアプリケーションを止めることは一般的には無作法だと考えられます。GetObject()
クラスメソッドは指定されたオブジェクトへのOLEリファレンスを返します。そのオブジェクトはパス名で指定され、オプションで後ろにエクスクラメーション・マーク
'!'によって区切られた追加の要素サブコンポーネントがつきます。オプションのDESTRUCTOR引数はnew() やGetActiveObject()と同じ意味を持ちます。Initialize([COINIT])Initialize()
クラス・メソッドはPerlスレッドのための代わりのアパートメント・モデルを指定するために使うことができます。これは最初のOLEオブジェクトが作成される前に呼ばれなければなりません。もしWin32::OLE::Constモジュールが使われていれば、Initialize()
メソッドの呼出しは最初のWin32::OLE::Constモジュールのためのuseステートメントの前のBEGINブロックでされなければなりません。COINTへの正しい値は以下の通りです:
Win32::OLE::COINIT_APARTMENTTHREADED - スングル・スレッディド Win32::OLE::COINIT_MULTITHREADED - デフォルト Win32::OLE::COINIT_OLEINITIALIZE - スングル・スレッディド、追加のOLEスタッフ
COINIT_OLEINITIALIZEはOLEオブジェクトが、通常のCOMサブシステムでは利用できない、追加のOLEコンパウンド・ドキュメント技術を使っているさいに、ときおり必要になります(例えばMAPIセッションはこれが必要なようです)。COINIT_OLEINITIALIZE
と COINIT_APARTMENTTHREADED
は隠れたトップ・レベル・ウィンドウとPerlプロセスのためのメッセージ・キューを作成します。これは他のアプリケーションとの問題を発生させるかもしれません。というのもPerlは通常そのメッセージ・キューを処理しないからです。つまりアプリケーション間で同期型通信(DDEイニシエーションのような)を使っているプログラムはPerlが他のOLEメソッド呼出し/プロパティ・アクセスをおこすか、終了するまで止まってしまうかもしれません。これはInstallShieldセットアップやシェル関連から発生する多くの事柄にあてはまります。デフォルトのCOINIT_MULTITHREADEDモデルを使うことができないのであれば、Win32::OLE->SpinMessageLoop
と Win32::OLE->Uninitialize
メソッドをを使ってみてください。
Invoke()
オブジェクト・メソッドはOLEメソッドを呼び出す代替方法です。これは通常$OBJECT->METHOD(@ARGS)を同じです。この関数はMETHOD名にPerl変数名として正しくない文字(例えば外国の文字)が入っているときに使わなければなりません。もしデフォルトのメソッドがライブラリで名前を与えられていなくても、そのオブジェクトのデフォルトのメソッドを呼び出すために使うことができます。この場合にはundefまたは''をメソッド名として使います。OLEオブジェクト・ネイティブのInvoke()メソッドを(もしそのようなものがあったとして)呼び出すためには、以下のようにします:
$Object->Invoke('Invoke', @Args);
LastError()LastError()
クラス・メソッドは最後に記録されたOLEエラーを返します。これは$!変数のように2つの値を持ちます:数値コンテキストではそれはエラー番号を返します、そして文字列コンテキストではそれはエラーメッセージを返します。エラー番号は符号付きのHRESULTの値です。符号なしの16進定数を符号付きのHRESULTに変換するためには
HRESULT(ERROR)関数を使ってください。最後のOLEエラーは、後の正常なOLE呼出しによって自動的にリセットされます。数値は明示的に呼び出すことによって設定することができます(それは文字列の値を捨てます)
Win32::OLE->LastError(0);
LetProperty(NAME,ARGS,VALUE)
$Object->{Property} = $OtherObject;
はこのVisual Basic ステートメントに対応します:
Set Object.Property = OtherObject
以下のようなVisual Basic Let
ステートメントの値による扱いを得るには:
Object.Property = OtherObject
PerlではLetProperty()
オブジェクト・メソッドを使わなければなりません:
$Object->LetProperty($Property, $OtherObject);
LetProperty()
はプロパティ設定のためのオプションの引数もサポートしています。詳しくはOBJECT->SetProperty(NAME,ARGS,VALUE)をご覧ください。
MessageLoop()MessageLoop()
クラス・メソッドは標準のWindowsメッセージループを実行します。QuitMessageLoop(),クラス・メソッドが呼ばれるまで、メッセージを処理します。これはOLEイベントを待つために使われます。Option(OPTION)Option()
クラス・メソッドはモジュール・オプションを検査し、変更するために使うことができます。1つだけ引数を指定すると、そのオプションの値を取り出します:
my $CP = Win32::OLE->Option('CP');
一回の呼出しで複数のオプションを同時に設定することもできます。
Win32::OLE->Option(CP => CP_ACP, Warn => 3);
QueryObjectType(OBJECT)QueryObjectType()
クラス・メソッドはタイプ・ライブラリ名とオブジェクト・クラス名のリストを返します。スカラ・コンテキストではそれはクラス名だけを返します。タイプ情報が使えなければ、undefを返します。QuitMessageLoop()QuitMessageLoop()
クラス・メソッドは(ユーザー・レベルで)"Quit"メッセージを現在のスレッド・メッセージ・ループにポストします。QuitMessageLoop()
は典型的にはイベント・ハンドラから呼ばれます。MessageLoop()
クラス・メソッドは、この"Quit"メソッドを受け取ると、戻ります。SetProperty(NAME,ARGS,VALUE)SetProperty()
メソッドはハッシュの書き方をサポートしていないプロパティを引数の値に変更することができます。ハッシュ形式は以下の通りです
$Object->{Property} = $Value;
これは以下のものと同じです
$Object->SetProperty('Property', $Value);
引数はプロパティ名と新しい値の間に指定されなければなりません:
$Object->SetProperty('Property', @Args, $Value);
新しい値はSetProperty()への最後の引数でなければならないので、この関数で"名前付き引数"の書き方を使うことはできません。
このメソッドはSetProperty()と呼ばれるネイティブなOLEオブジェクト・メソッドを隠してしまいます。そのネイティブなメソッドはInvoke()
メソッドを使って呼び出すことができます:
$Object->Invoke('SetProperty', @Args);
Uninitialize()
クラス・メソッドはOLEサブシステムの反初期化をします。これはシングル・スレッディド分離のためのOLEによって作られた隠れたトップ・レベル・ウィンドウを破壊もします。これを呼び出した後には、すべてのOLEオブジェクトが不適切になります!Uninitialize().でOLEを終了させた後、再びInitialize()
クラス・メソッドを異なる分離モデルで呼び出すことは可能です。PerlがWin32::OLEパッケージでメソッド名を見つけられなかった場合、それは自動的にOLEメソッドの名前として使われます。そしてこのメソッド呼出しはOLEサーバーによって処理されます。
このモジュールには1つの特別な方法が組み込まれています。もしメソッドまたはプロパティ名がOLEオブジェクトによって解決されなければ、オブジェクトのデフォルト・メソッドがそのメソッド名を第1引数として呼ばれます。そこで
my $Sheet = $Worksheets->Table1;
または
my $Sheet = $Worksheets->{Table1};
は以下のように解決されます
my $Sheet = $Worksheet->Item('Table1');
$WorksheeetsオブジェクトがTableメソッドまたはプロパティを持っていない場合です。この方法はタイプ・ライブラリではメソッドに名前をつけないコレクションのデフォルト・メソッドを呼び出すために導入されています。"名無しの"デフォルト・メソッドを呼び出す推奨される方法は以下の通りです:
my $Sheet = $Worksheets->Invoke('', 'Table1');
この特殊な方法はuse strict 'subs'の元では使えません。
new() メソッドによって返されるオブジェクトは、特定のOLEクラスのためのドキュメントで説明されているのと同じ形式で、メソッドを呼び出したり、プロパティを取り出したりするのに使うことができます。(例えばMicrosoft
ExcelドキュメントはOLEアクセスのために公開されているプロパティやメソッドを持ったオブジェクト階層について説明しています。)
メソッド呼出しでのオプションのパラメータはundefをプレースホルダとして使うことによって省略することができます。オプションのパラメータの順序はOLEサーバー・アプリケーションの後のバージョンでは変更されてしまうかもしれないので、よりよい方法は名前付き引数を使うことです。名前付きパラメータはハッシュへのリファレンスをメソッド呼出しのへの最後のパラメータとして指定することでできます。
プロパティはハッシュの書き方を使って取得、設定するすることができます。メソッドは通常のperlメソッド呼出しの書き方で呼び出すことができます。keys
と each
関数はオブジェクトのプロパティを列挙するために使うことができます。プロパティは常に書込可能そして、読込可能でさえあるわけではないことに注意してください。(時には未定義である間は読み込んだときに例外を起こすこともあります)
もしメソッドやプロパティが埋め込まれたOLEオブジェクトを返すのであれば、メソッドとプロパティ・アクセスは以下の例にあるようにチェーンされます。
以下の関数はデフォルトではエクスポートされません。
HRESULT(ERROR)HRESULT()
関数は符号なしの数値を符号付きのOLEによって内部的に使われるようなHRESULTエラー値に変換します。これはPerlが全ての16進数定数を符号なしとして扱うために必要です。最後のOLE関数が"Member
not found'' (0x80020003)"を返したかどうかをチェックしたければ、以下のようにすることができます:
if (Win32::OLE->LastError == HRESULT(0x80020003)) {
# your error recovery here
}
in(COLLECTION)in $COLLECTION は、そのコレクションのすべての要素のリストを返します。これはWin32::OLE::Enum->All($COLLECTION)のショートカットです。これは一般的にforeachループで使われます:
foreach my $value (in $collection) {
# do something with $value here
}
valof(OBJECT)valof()
関数は明示的にオブジェクト(デフォルト・メッソドを通じた)とオブジェトの値を区別します。
my $RefOf = $Object;
my $ValOf = valof $Object;
$Object->{Value} = $NewValue;
いまや$ValOfはまだ古い値を持っているのに、$RefOf はまだ$Objectへのリファレンスなので、$NewValue を解決します。
valof()
関数はWin32::OLE::VariantオブジェクトをPerl変数に変換するためにも使うことができます。
$OBJECT->{PROPERTYNAME}
= $VALUE を繰り返しおこないます。Win32::OLEオブジェクトはブール値、数値、文字列コンテキストで使われたときにはいつでも、自動的にそれらの値に変換するためにオーバーロードすることができます。これはデフォルトでは可能ではありません。OVERLOAD疑似エクスポートを通して要求する必要があります:
use Win32::OLE qw(in valof with OVERLOAD);
例えばデバッグのためにoverload::StrVal()メソッドを使って、元のオブジェクトの文字列表現(Win32::OLE=0xDEADBEEF)
を取得することもできます:
print overload::StrVal($object), "\n";
OVERLOADはグローバルな設定であることに注意してください。もしなんらかのモジュールがWin32::OLEオーバーロードを可能にすると、それはいつでも有効です。
Win32::OLEモジュールは今はアルファレベルのイベント・サポートを持っています。このサポートはPerlがシングル・スレッディド分離レベルで実行しているときにだけ利用できます。これはとても簡単にEVENTS疑似インポートを使うことによって、保証することができます:
use Win32::OLE qw(EVENTS);
これは暗黙のうちに以下のようなことをしています:
use Win32::OLE;
Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
現在のOLEイベントへのインターフェースは実験的なものであると考えられ、変更されやすいものです。通常のOLEアプリケーションでは予定通りに機能しますが、OLE制御イベントはまだうまく機能していないようです。
イベントはWin32::OLE->WithEvents()
クラス・メソッドを通して、OLEオブジェクトのために明示的に可能にされなければなりません。Win32::OLEモジュールはオブジェクトのデフォルト・イベント・ソースを判定するために
IProvideClassInfo2 インターフェースを利用しています。このインターフェースがサポートされていなければ、ユーザは
WithEvents()メソッドで明示的にイベント・ソースの名前を指定しなければなりません。オブジェクトのクラス名を3番目のパラメータとして指定することも可能です。この場合、Win32::OLEは、このCOCLASSのためのデフォルト・ソース・インターフェースを見つけようとします。
Win32::OLE->WithEvents()
へのHANDLER引数はCODEリファレンスまたはパッケージ名のどちらかにすることができます。前者の場合、すべてのイベントはこの特定の関数を呼び出します。この関数への最初の2つの引数はOBJECTそのものとイベントの名前になります。残りの引数はイベントによります:
sub Event {
my ($Obj,$Event,@Args) = @_;
print "Event triggered: '$Event'\n";
}
Win32::OLE->WithEvents($Obj, \&Event);
代わりにHANDLER引数がパッケージ名を指定することができます。OBJECTがイベントを発火したとき、Win32::OLEは、このパッケージでイベントと同じ名前の関数を見つけようとします。この関数はOBJECTを最初の引数とし、イベント特有のパラメータが後ろについて呼び出されます:
package MyEvents;
sub EventName1 {
my ($Obj,@Args) = @_;
print "EventName1 event triggered\n";
}
package main;
Win32::OLE->WithEvents($Obj, 'MyEvents', 'IEventInterface');
Win32::OLEがイベント名の関数を見つけなければ、何も起こりません。
リファレンスによって渡されたイベント・パラメータは特別に扱われます。これらは対応するPerlデータ型に変換されず、Win32::OLE::Variantオブジェクトとして渡されます。これらのオブジェクトにPut()メソッドの助けを借りて新しい値を代入することができます。この値はイベント関数が戻るとき、オブジェクトに戻されます:
package MyEvents;
sub BeforeClose {
my ($self,$Cancel) = @_;
$Cancel->Put(1) unless $MayClose;
}
$Cancelへの直接の代入は元の値に何も影響を与えません。そしてこのためオブジェクトにアクションを閉じるのを中止させるように命令しません。
以下のモジュール・オプションはWin32::OLE->Optionクラスメソッドでアクセス、変更することができます。Win32::OLEモジュールの始めのころのバージョンでは、これらのオプションはクラス変数として直接操作されました。この実装はいまや非難されます:
0 エラーを無視。undefを返す
1 $^Wが設定されていれば(-w オプション)Carp::carp
2 常にCarp::carp
3 Carp::croak
エラー番号とメッセージ(Carp行/モジュール情報は無し)はWin32::OLE->LastError クラス・メソッドを通して利用することができます。
代わりにCODEリファレンスにWarnオプションを設定することができます。例えば
Win32::OLE->Option(Warn => 3);
これは以下のものと同じです。
Win32::OLE->Option(Warn => \&Carp::croak);
これはVisualBasicのOn Error Goto Label構造をエミュレートするために使うことさえもできます:
Win32::OLE->Option(Warn => sub {goto CheckError});
# ... 通常のOLEコードをここに ...
CheckError:
# ... エラーを扱うコードをここに ...
_NewEnumオプションが設定されたとき、すべてのコレクションは1つの追加のプロパティ:
_NewEnumを受け取ります。kのプロパティの値はコレクションのすべての要素が入った配列へのリファレンスになります。このオプションはData::Dumperやオブジェクト・ツリー・ブラウザのような自動的なツリー構造横断プログラムと一緒に使うときに便利でしょう。このオプションの値は1(有効)または0(無効、デフォルト)でなければなりません。
Win32::OLE->Option(_NewEnum => 1);
# ...
my @sheets = @{$Excel->Worksheets->{_NewEnum}};
通常のアプリケーション・コードでは、これは以下のように書いた方がよいでしょう:
use Win32::OLE qw(in);
# ...
my @sheets = in $Excel->Worksheets;
_Unique
オプションはWin32::OLEがネイティブのCOM/OLEオブジェクトと1対1のマッピングを維持することを保証します。このオプションがないと、元になっている同じCOMオブジェクトのために異なるWin32::OLEオブジェクトを取得し、同じプロパティを重複して問い合わせることになりかねません。ユニーク・プロキシーを使うと、特定のノードを既に訪れたことを理解するためのツリー構造横断アルゴリズムは簡単になります。このオプションは大きな犠牲を払います:Win32::OLEがすべての存在するオブジェクトと対応するプロキシーのグローバルなハッシュと維持しなければならなりません。オブジェクトがプロセスの外側に、あるいは異なるコンピュータにあったりしたら、COMオブジェクトの識別子チェックも同様に高価になりかねません。このためこのオプションはプログラムがデバッガで実行されるのでなければ、デフォルトではオフです。
残念ながら、このオプションは常に助けにはなりません。いくつかのプログラムは同じプロパティであってさえも、何度も聞くと新しいCOMオブジェクトを返すことがあります(特にコレクションについては)。この場合、これらのオブジェクトが事実上同じであると見分けるためにWin32::OLEができることは何もありません(というのもそれはCOMレベルではないからです)
_Unique
オプションは1(有効)または0(無効、デフォルト)のどちらかに設定することができます。
これは簡単なMicrosoft Excelアプリケーションです。
use Win32::OLE;
# もしExcelが既に実行中であれば、既存のインスタンスを利用する
eval {$ex = Win32::OLE->GetActiveObject('Excel.Application')};
die "Excel not installed" if $@;
unless (defined $ex) {
$ex = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;})
or die "Oops, cannot start Excel";
}
# 新しいワークブックを取得
$book = $ex->Workbooks->Add;
# あるセルに出力
$sheet = $book->Worksheets(1);
$sheet->Cells(1,1)->{Value} = "foo";
# 2行、3列の範囲に出力
$sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ],
[ 42, 'Perl', 3.1415 ]];
# "XyzzyPerl"と出力
$array = $sheet->Range("A8:C9")->{Value};
for (@$array) {
for (@$_) {
print defined($_) ? "$_|" : "<undef>|";
}
print "\n";
}
# 保存して終了
$book->SaveAs( 'test.xls' );
undef $book;
undef $ex;
Win32::OLE->newメソッドでデストラクタが指定されていることに注意してください。これはPerlプログラムが死んだときでさえも、Excelが適切に終了されることを保証します。そうでなければExcelのOLEインスタンスが開いたあとで、アプリケーションが死ぬとプロセス・リークになりかねません。OLEオブジェクトが確実に適切に片づけられるようにするのはモジュール利用者の責任です!
以下はVariantデータ型を使った例です。
use Win32::OLE;
use Win32::OLE::Variant;
$ex = Win32::OLE->new('Excel.Application', \&OleQuit) or die "oops\n";
$ex->{Visible} = 1;
$ex->Workbooks->Add;
# should generate a warning under -w
$ovR8 = Variant(VT_R8, "3 is a good number");
$ex->Range("A1")->{Value} = $ovR8;
$ex->Range("A2")->{Value} = Variant(VT_DATE, 'Jan 1,1970');
sub OleQuit {
my $self = shift;
$self->Quit;
}
上記では文字列は"3 is a good number"ではなく、"3"をセルA1に入れます。セルA2は日付を持ちます:
同様に、バイナリ・データでメソッドを呼び出すためには、以下のようにできます:
$obj->Method( Variant(VT_UI1, "foo\000b\001a\002r") );
以下のものは基本的にnew()とDESTROY()を除いたすべてを委任するラッパー・クラスです。下記のラッパー・クラスは、アプリケーションが適切なクリーンアップなしに死ぬことが免れないときに、接続を適切に終らせるもう1つの方法です。あなた自身のラッパーは、独自に確証したいメソッドをオーバーライドするといったように、おそらくあなたの扱いたい特定のOLEオブジェクトにより特化したようなことをするでしょう。
package Excel;
use Win32::OLE;
sub new {
my $s = {};
if ($s->{Ex} = Win32::OLE->new('Excel.Application')) {
return bless $s, shift;
}
return undef;
}
sub DESTROY {
my $s = shift;
if (exists $s->{Ex}) {
print "# closing connection\n";
$s->{Ex}->Quit;
return undef;
}
}
sub AUTOLOAD {
my $s = shift;
$AUTOLOAD =~ s/^.*:://;
$s->{Ex}->$AUTOLOAD(@_);
}
1;
上記のモジュールは、異常終了のさいに接続を閉じるように気をつけてくれる点を除いて、Win32::OLEとまったく同じように使うことができます。この特定の例の効果はWin32::OLE::newのデストラクタ引数を使うことによって、より簡単に実現できるということに注意してください:
my $Excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;});
上記の例での委任は特化されたオブジェクトでのメソッド呼出しのさらなる継承への見方と同じではないことに注意してください。詳細についてはperlobj, perltoot そして perlbotをご覧ください。本当のサブクラスか(@ISAを設定することによって利用できることになる)も、以下のデモンストレーションのように可能です:
#
# エラー報告をWin32::OLEに追加する
#
package Win32::OLE::Strict;
use Carp;
use Win32::OLE;
use strict qw(vars);
use vars qw($AUTOLOAD @ISA);
@ISA = qw(Win32::OLE);
sub AUTOLOAD {
my $obj = shift;
$AUTOLOAD =~ s/^.*:://;
my $meth = $AUTOLOAD;
$AUTOLOAD = "SUPER::" . $AUTOLOAD;
my $retval = $obj->$AUTOLOAD(@_);
unless (defined($retval) || $AUTOLOAD eq 'DESTROY') {
my $err = Win32::OLE::LastError();
croak(sprintf("$meth returned OLE error 0x%08x",$err))
if $err;
}
return $retval;
}
1;
このパッケージはコンストラクラnew()をWin32::OLEパッケージから継承しています。パッケージについての情報がオブジェクトによってキャッシュされるためにWin32::OLEを再びblessすることはできないことに注意しすることは大切なことです。常に正しいパッケージを通して、new()
コンストラクタを呼び出してください!
以下に上記のクラスがどのように使われるかを示します:
use Win32::OLE::Strict;
my $Excel = Win32::OLE::Strict->new('Excel.Application', 'Quit');
my $Books = $Excel->Workbooks;
$Books->UnknownMethod(42);
上記のサンプルでUnknownMethod()を呼び出すと、それは以下のように捕らえられます:
UnknownMethod returned OLE error 0x80020009 at test.pl line 5
というのもWorkbooksオブジェクトは$ExcelオブジェクトからWin32::OLE::Strictクラスを継承しているからです。
クラス名はそのオブジェクトを作るメソッド/プロパティ名と常に同じではありません。例えばWorkbookメソッドはOffice95ではWorkbookオブジェクトを返しますが、Office97では_Workbookを返します。
GetObject("File.XLS!Sheet")
を通してあるワークシート・オブジェクトを取り出すことはできないようです。さらにExcel95ではモニカはWorkseetオブジェクトを開始し、Excel97ではWorkbookオブジェクトを返します。移植性のあるコードを書くためには、Win32::OLE::QueryObjectType
クラス・メソッドまたは$object->{Version}
のどちらかかを使うことができます。
$Word->WordBasic->FileSaveAs($file);
この問題はOffice97サービス・リリース1を提供することにより修正されるようです。
Activewareによって(build306として)配布されたバージョンとはいくつかの点で互換性がありません。
Invokeを使う必要があります:
$Object->Invoke('Dispatch', @AdditionalArgs);
同じことがExporterまたあhDynaloaderモジュールによってエクスポートされる名前についてもあてはまります。例えば:
export, export_to_level, import,
_push_tags, export_tags, export_ok_tags,
export_fail, require_version, dl_load_flags,
croak, bootstrap, dl_findfile,
dl_expandspec, dl_find_symbol_anywhere,
dl_load_file, dl_find_symbol, dl_undef_symbols,
dl_install_xsub そして dl_error。
Win32::OLE::Const, Win32::OLE::Enum, Win32::OLE::NLS そして Win32::OLE::Variant のドキュメントにはWin32上のPerlのための追加のOLEサポートについての情報が入っています。
Originally put together by the kind people at Hip and Activeware.
Gurusamy Sarathy <gsar@activestate.com> subsequently fixed several major bugs, memory leaks, and reliability problems, along with some redesign of the code.
Jan Dubois <jand@activestate.com> pitched in with yet more massive redesign, added support for named parameters, and other significant enhancements. He's been hacking on it ever since.
Please send questions about problems with this module to the Perl-Win32-Users mailinglist at ActiveState.com. The mailinglist charter requests that you put an [OLE] tag somewhere on the subject line (for OLE related questions only, of course).
(c) 1995 Microsoft Corporation. All rights reserved.
Developed by ActiveWare Internet Corp., now known as
ActiveState Tool Corp., http://www.ActiveState.com
Other modifications Copyright (c) 1997-2000 by Gurusamy Sarathy
<gsar@activestate.com> and Jan Dubois <jand@activestate.com>
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the README file.
Version 0.14 22 August 2000
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。