ActiveState社 ホームページ       Win32 FAQ




文書名

perlwin32faq12 - PerlからのOLE使用法





内容

PerlからのOLEオートメーションの使用方法 - Win32::OLEモジュールの利用


PerlからOLEを利用することはできるのでしょうか?

できます。そうでなければ、このFAQをperlwin32faq4からわざわざ分離するような真似はしませんでした;-)

PerlからOLEを使用する場合、Win32::OLEモジュールが必要となります。 まずは、同モジュールの添付文書を読んでみてください。

use Win32::OLE では、変数や関数は自動的には名前空間mainにエキスポートされません。in関数や with関数を利用したい場合は、以下のようにしてモジュールをロードする必要があります。

use Win32::OLE qw(in with);


OLEに関して、ビルド3xxと変ったところはどこでしょうか?

たくさんあります。Gurusamy Sarathy、後にJan Duboisがコードを再設計し、多くの拡張を行いました。 古いスクリプトも、まったくの修正なしで、あるいは若干の修正で動くはずです。 新しくスクリプトを書く際は、新Win32::OLEモジュールのオプションをガンガン使いましょう。

詳しくは、Win::OLE モジュールのドキュメント(非互換性の下)と、特に リリースノートの 'What's changed from 300 series builds' を参考にしてください。


Microsoft Wordの文書を印刷するにはどうすればよいのでしょうか?

Documentオブジェクトの PrintOutメソッドを使用します。例えば:

use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Word';

my $Word = Win32::OLE->new('Word.Application', 'Quit');
# $Word->{'Visible'} = 1;         # if you want to see what's going on
$Word->Documents->Open("C:\\DOCUMENTS\\test.doc")
    || die("Unable to open document ", Win32::OLE->LastError());
$Word->ActiveDocument->PrintOut({
    Background => 0,
    Append     => 0,
    Range      => wdPrintAllDocument,
    Item       => wdPrintDocumentContent,
    Copies     => 1,
    PageType   => wdPrintAllPages,
});

または、簡単に

$Word->ActiveDocument->PrintOut;


Microsoft Excelから一連のセルの内容を取り出すにはどうすればよいのでしょうか?

シートオブジェクトを使って、$Sheet->Range->{'Value'}のようにすれば、一連のセルの値を取り出すことができます。
例:

my $array = $Sheet->Range("A8:B9")->{'Value'};

これで、$array[0][0]にはセルA8、$array[0][1]にはセルB8、$array[1][0]にはセルA9、$array[1][1]にはセルB9の値が格納されました。

戻り値は、指定したセルの値が格納された二次元配列(正確には配列へのリファレンス)となっています。

完全なサンプルを以下に示します。:


use strict;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Excel';
$Win32::OLE::Warn = 3;                                # die on errors...
my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
    || Win32::OLE->new('Excel.Application', 'Quit');  # get already active Excel
                                                      # application or open new
my $Book = $Excel->Workbooks->Open("C:\\DOCUMENTS\\test.xls"); # Excelのファイルをオープン
my $Sheet = $Book->Worksheets(1);                     # ワークシート1を選択
my $array = $Sheet->Range("A8:B9")->{'Value'};        # 中身を取り出す
$Book->Close;
foreach my $ref_array (@$array) {                     # $arrayが参照している
                                                      # 配列の全要素を取り出す
    foreach my $scalar (@$ref_array) {
        print "$scalar\t";
    }
    print "\n";
}


セルの表示形式のままの値を取り出したい場合は、 {'Value'}プロパティではなく{'Text'} プロパティを使うとよいでしょう。 このプロパティでは、画面に表示されている値がそのまま戻り値となります。つまり、列幅が十分に広く取られていない場合には、'######'という値が返ってくるわけです。 :

my $array = $Sheet->Range("A8:B9")->{'Text'};


Microsoft Excelで図を描くにはどうすればよいのでしょうか?

Microsoft Excelのマクロを記録しておき、そのマクロをPerlに変換するという手がよいのではないかと思います。 以下に完全な例を示します。:

use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';

my $Excel = Win32::OLE->new("Excel.Application");
$Excel->{Visible} = 1;

my $Book = $Excel->Workbooks->Add;
my $Sheet = $Book->Worksheets(1);
my $Range = $Sheet->Range("A2:C7");
$Range->{Value} =
    [['Delivered', 'En route', 'To be shipped'],
     [504, 102, 86],
     [670, 150, 174],
     [891, 261, 201],
     [1274, 471, 321],
     [1563, 536, 241]];

my $Chart = $Excel->Charts->Add;
$Chart->{ChartType} = xlAreaStacked;
$Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
$Chart->{HasTitle} = 1;
$Chart->ChartTitle->{Text} = "Items delivered, en route and to be shipped";


Microsoft Excelで描いた図をGIF/JPEG/PNG形式で保存するにはどうすればよいのでしょうか?

ChartのExportメソッドを利用するとよいでしょう。 Chartオブジェクト生成後のコードは次のようになります。

$ChartObj->Chart->Export({
    FileName    => "$graphics_filename",
    FilterName  => 'GIF',
    Interactive => 0});

以下は、Excelのワークブックを開き、すべての図をGIFファイルとして保存し、Excelのワークブックを閉じるまでの全体サンプルです。:

use strict;
use Win32::OLE qw(in with);
use Win32::OLE::Const;
use Win32::OLE::Const 'Microsoft Excel';
$Win32::OLE::Warn = 3;        # エラー時はdie...

my $filename = 'c:\\documents\\test.xls';
my $filter = 'GIF';           # GIF, JPG, JPEG , PNGのいずれでも可
my $count = 0;

my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
    || Win32::OLE->new('Excel.Application', 'Quit');  # Excelが既に起動されていればそれを利用。そうでなければ新たに起動
my $Book = $Excel->Workbooks->Open( $filename );      # ファイルを開く
foreach my $Sheet (in $Book->Sheets) {                # 全シートを対象
    foreach my $ChartObj (in $Sheet->ChartObjects) {  # 各シートの全図オブジェクトを対象
        my $savename = "$filename." . $count++ . ".$filter";
        $ChartObj->Chart->Export({
            FileName    => $savename,
            FilterName  => $filter,
            Interactive => 0});
    }
}
$Book->Close;


Microsoft Excelでマクロを実行するにはどうすればよいのでしょうか?

Microsoft Excelのマクロを実行するには、$Excel->Runメソッドを使います。

$Excel->Run("PrintPDFFile");

いうまでもなく、このサンプルを実行するには、'PrintPDFFile'というExcelマクロを用意しておく必要があります。


Microsoft Excelでセル名をセットするにはどうすればよいのでしょうか?

そのシートのNames->Addメソッドを使うとよいでしょう。セル名と対象とする範囲を指定します。
例:

$Sheet->Names->Add({Name => 'NetCost', RefersTo => $Sheet->Range('$B$10')});


Outlookでフォルダを新規作成するにはどうすればよいのでしょうか?

サンプルを再掲:-)

use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Outlook';

my $Outlook = Win32::OLE->new('Outlook.Application', 'Quit');
my $ol = Win32::OLE::Const->Load($Outlook);

my $namespace = $Outlook->GetNamespace("MAPI");
my $Folder = $namespace->GetDefaultFolder(olFolderInbox);
my $NewFolder = $Folder->Folders->Add("Test1");


ADOを使うにはどうすればよいのでしょうか?

ActiveX Data Objects (ADO)を使用するには、以下のようにします。

use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft ActiveX Data Objects';
my $Conn = Win32::OLE->new('ADODB.Connection'); # creates a connection object
my $RS = Win32::OLE->new('ADODB.Recordset');    # レコードセット・オブジェクトを作成ct
$Conn->Open('DBname');                          # opens the database connection

my $Fields = ['Id', 'Name', 'Phone'];
my $Values = [1, 'Joe Doe', '555-1234'];
$RS->AddNew($Fields, $Values);                  # レコードを追加

print "This didn't go well: ", Win32::OLE->LastError(), "\n";
    if (Win32::OLE->LastError());

$RS->Close;
$Conn->Close;

詳しくは、 http://www.fastnetltd.ndirect.co.uk/Perl/perl-win32-database.htmlのADO FAQやThe Perl Journal(http://tpj.com/)のTPJ#10、Jan Duboisの記事を参考するとよいでしょう。


Lotus Notesを使うにはどうすればよいのでしょうか??

OLE経由でLotus Notesにアクセスできます。例えば、以下のようにします。

use strict;
use Win32::OLE;
my $Notes = Win32::OLE->new('Notes.NotesSession')
    or die "Cannot start Lotus Notes Session object.\n";
my ($Version) = ($Notes->{NotesVersion} =~ /\s*(.*\S)\s*$/);
print "The current user is $Notes->{UserName}.\n";
print "Running Notes \"$Version\" on \"$Notes->{Platform}\".\n";
my $Database = $Notes->GetDatabase('', 'help4.nsf');
my $AllDocuments = $Database->AllDocuments;
my $Count = $AllDocuments->Count;
print "There are $Count documents in the database.\n";
for (my $Index = 1 ; $Index <= $Count ; ++$Index) {
    my $Document = $AllDocuments->GetNthDocument($Index);
    printf "$Index. %s\n", $Document->GetFirstItem('Subject')->{Text};
    my $Values = $Document->GetItemValue('Index_Entries');
    foreach my $Value (@$Values) {
        print "Index: $Value\n";
    }
    last unless $Index < 5;
}

LotusScriptでアクセス可能なオブジェクトすべてにアクセスすることができます。 LotusScriptクラスについては、 http://www.lotus.com/products/lotusscript.nsfで調べることができます。 また、TPJ#10 (http://tpj.com/のThe Perl Journal)のJan Duboisの記事に目を通すのもよいでしょう。


Wordでプリンタをセットするにはどうすればよいのでしょうか?

$Word->{ActivePrinter} = $printernameで、Word.Applicationオブジェクトを通じてアクティブ状態のプリンタの設定をしたり、設定を取り出すことができます。


VBAマクロをPerlに変換するにはどうすればよいのでしょうか?

Microsoft Officeでマクロを記録している場合、しばしばPerlに直接変換されているようです。 VBA(Visual Basic for Applications)では、文法は以下のようになっています。:

object.method(argument).property = value

Perlでは、以下のようになります。

object->method(argument)->{property} = value;

つまり、次のVBAのサンプルコードは:

ActiveChart.Axes(xlCategory, xlPrimary).CategoryType = xlCategoryScale

Perlでは以下のようになります。:

$Chart->Axes(xlCategory, xlPrimary)->{CategoryType} = xlCategoryScale;


オブジェクトモデルの資料はどこにあるのでしょうか?

ドキュメントが利用できない場合は、OLEタイプブラウザを通じてメソッドやプロパティを勉強するのが一番でしょう。

Microsoft Excel や Microsoft Word が利用可能であれば、Alt+F11 でVisual Basic Editor を呼び出します。 ここでF2でオブジェクトブラウザ画面を開くと、お目当てのものが出てきます。

MS-Officeを持っていない場合には、Microsoft Visual C++ / Microsoft Visual StudioにOleViewプログラム(名前やバージョンはいろいろ)が入っています。また、これはMicrosoft COM Webサイト( http://www.microsoft.com/com/)からダウンロードすることもできます。

しかし、Notesに関しては、まだ全情報をrevealしていない可能性があります。;タイプ情報のサポートを提供するのにオブジェクトは必要とされていません。 たとえば、Lotus Notesは内部の定数、メソッド、プロパティについて何もrevealしていせん。;それらはドキュメントを調べなければなりません。 But it is still possible that Notes doesn't reveal anything; objects are not required to provide type info support. For example Lotus Notes doesn't reveal nothing about it's internal constants, methods and properties; you have to look them up in the documentation.

Lotus Notesについては、 http://www.lotus.com/products/lotusscript.nsfを参照してください。


わかりました。しかし、Win32::OLE::Constからエキスポートされた定数を調べるにはどうすればよいのでしょうか?

次のコードサンプルを使うと全定数を見ることができます。 実際にはこのようなものは必要ありませんが、仕掛けを理解する手助けになるでしょう。

use strict;
use Win32::OLE;
use Win32::OLE::Const;

my $xl = Win32::OLE::Const->Load("Microsoft Excel");
printf "Excel type library contains %d constants:\n", scalar keys %$xl;
foreach my $Key (sort keys %$xl) {
    print "$Key = $xl->{$Key}\n";
}

Win32::OLE::Const自体については、ドキュメントを読んでください。


生成されたエラーメッセージが$!で捕捉できないのはどうしてですか?

Win32::OLEからのエラーメッセージは$!変数にはセットされませんが、Win32::OLE->LastError()でアクセス可能です。


ODBCやOLEを使うとエラーが生じるのはどうしてですか?

ある理由で、 最初にOLEアプリケーションをオープンし、その後で Access ODBC ドライバに対してODBC接続をオープンした場合、'OleInitialize' エラーが発生します。 他の方法を取った場合は、この問題は生じません。

一見Access ODBCドライバがOleInitialize()をコールしているようにみえます。 これは、Win32::OLEがその前にCOMサブシステムを"apartment threaded"として初期化した時にその障害が起きているのです。

このエラーを回避するためには、OLEアプリケーションの前にODBCドライバを開始するようにします。また、さらによい方法として、Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE); でOLEシステムを初期化する方法があります。


上記を全部試したのですが、うまく動きません。どうしてでしょうか。

perl -wuse strictを使ってスクリプトを実行してみることです。これでエラーの大半が捕捉されます。また、Win32::OLEや使用しているオブジェクト のドキュメントに目を通すとよいでしょう。

Microsoft Office 97の場合、最低でもサービスパック1にアップデート していることを確認してください。このアップデートを行っていないと、Microsoft Office 97では大半のOLEが破壊されます。


著者および著作権について

この FAQ は、多くの方々、特にJan Duboisによるサンプルを基に、RTOのHenning Michael Møller-Nielsenが編集しました。 この文書は、perlwin32faq@rto.dkのHenning Michael Møller-Nielsen、Philip Martin、Kevin Meltzer、およびEric Smithが保守しています。

このFAQはパブリックドメインですが、使用する場合、オリジナルの作者について明示してください。

ActiveState Home Page       Win32 FAQ