diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Win32/OLE.pm')
-rw-r--r-- | Master/tlpkg/tlperl/lib/Win32/OLE.pm | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE.pm b/Master/tlpkg/tlperl/lib/Win32/OLE.pm new file mode 100644 index 00000000000..a447f1aaa18 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE.pm @@ -0,0 +1,968 @@ +# The documentation is at the __END__ + +package Win32::OLE; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK @EXPORT_FAIL $AUTOLOAD + $CP $LCID $Warn $LastError $_NewEnum $_Unique); + +$VERSION = '0.1709'; + +use Carp; +use Exporter; +use DynaLoader; +@ISA = qw(Exporter DynaLoader); + +@EXPORT = qw(); +@EXPORT_OK = qw(in valof with HRESULT EVENTS OVERLOAD + CP_ACP CP_OEMCP CP_MACCP CP_UTF7 CP_UTF8 + DISPATCH_METHOD DISPATCH_PROPERTYGET + DISPATCH_PROPERTYPUT DISPATCH_PROPERTYPUTREF); +@EXPORT_FAIL = qw(EVENTS OVERLOAD); + +sub export_fail { + shift; + my @unknown; + while (@_) { + my $symbol = shift; + if ($symbol eq 'OVERLOAD') { + eval <<'OVERLOAD'; + use overload '""' => \&valof, + '0+' => \&valof, + fallback => 1; +OVERLOAD + } + elsif ($symbol eq 'EVENTS') { + Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE()); + } + else { + push @unknown, $symbol; + } + } + return @unknown; +} + +unless (defined &Dispatch) { + # Use regular DynaLoader if XS part is not yet initialized + bootstrap Win32::OLE; + require Win32::OLE::Lite; +} + +1; + +######################################################################## + +__END__ + +=head1 NAME + +Win32::OLE - OLE Automation extensions + +=head1 SYNOPSIS + + $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"); + +=head1 DESCRIPTION + +This module provides an interface to OLE Automation from Perl. +OLE Automation brings VisualBasic like scripting capabilities and +offers powerful extensibility and the ability to control many Win32 +applications from Perl scripts. + +The Win32::OLE module uses the IDispatch interface exclusively. It is +not possible to access a custom OLE interface. OLE events and OCX's are +currently not supported. + +Actually, that's no longer strictly true. This module now contains +B<ALPHA> level support for OLE events. This is largely untested and the +specific interface might still change in the future. + +=head2 Methods + +=over 8 + +=item Win32::OLE->new(PROGID[, DESTRUCTOR]) + +The new() class method starts a new instance of an OLE Automation object. +It returns a reference to this object or C<undef> if the creation failed. + +The PROGID argument must be either the OLE I<program id> or the I<class id> +of the required application. The optional DESTRUCTOR specifies a DESTROY-like +method. This can be either a CODE reference or a string containing an OLE +method name. It can be used to cleanly terminate OLE applications in case the +Perl program dies. + +To create an object via DCOM on a remote server you can use an array +reference in place of PROGID. The referenced array must contain the +machine name and the I<program id> or I<class id>. For example: + + my $obj = Win32::OLE->new(['my.machine.com', 'Program.Id']); + +If the PROGID is a I<program id> then Win32::OLE will try to resolve the +corresponding I<class id> locally. If the I<program id> is not registered +locally then the remote registry is queried. This will only succeed if +the local process has read access to the remote registry. The safest +(and fastest) method is to specify the C<class id> directly. + +=item Win32::OLE->EnumAllObjects([CALLBACK]) + +This class method returns the number Win32::OLE objects currently in +existance. It will call the optional CALLBACK function for each of +these objects: + + $Count = Win32::OLE->EnumAllObjects(sub { + my $Object = shift; + my $Class = Win32::OLE->QueryObjectType($Object); + printf "# Object=%s Class=%s\n", $Object, $Class; + }); + +The EnumAllObjects() method is primarily a debugging tool. It can be +used e.g. in an END block to check if all external connections have +been properly destroyed. + +=item Win32::OLE->FreeUnusedLibraries() + +The FreeUnusedLibraries() class method unloads all unused OLE +resources. These are the libraries of those classes of which all +existing objects have been destroyed. The unloading of object +libraries is really only important for long running processes that +might instantiate a huge number of B<different> objects over time. + +Be aware that objects implemented in Visual Basic have a buggy +implementation of this functionality: They pretend to be unloadable +while they are actually still running their cleanup code. Unloading +the DLL at that moment typically produces an access violation. The +probability for this problem can be reduced by calling the +SpinMessageLoop() method and sleep()ing for a few seconds. + +=item Win32::OLE->GetActiveObject(CLASS[, DESTRUCTOR]) + +The GetActiveObject() class method returns an OLE reference to a +running instance of the specified OLE automation server. It returns +C<undef> if the server is not currently active. It will croak if +the class is not even registered. The optional DESTRUCTOR method takes +either a method name or a code reference. It is executed when the last +reference to this object goes away. It is generally considered C<impolite> +to stop applications that you did not start yourself. + +=item Win32::OLE->GetObject(MONIKER[, DESTRUCTOR]) + +The GetObject() class method returns an OLE reference to the specified +object. The object is specified by a pathname optionally followed by +additional item subcomponent separated by exclamation marks '!'. The +optional DESTRUCTOR argument has the same semantics as the DESTRUCTOR in +new() or GetActiveObject(). + +=item Win32::OLE->Initialize([COINIT]) + +The Initialize() class method can be used to specify an alternative +apartment model for the Perl thread. It must be called B<before> the +first OLE object is created. If the C<Win32::OLE::Const> module is +used then the call to the Initialize() method must be made from a BEGIN +block before the first C<use> statement for the C<Win32::OLE::Const> +module. + +Valid values for COINIT are: + + Win32::OLE::COINIT_APARTMENTTHREADED - single threaded + Win32::OLE::COINIT_MULTITHREADED - the default + Win32::OLE::COINIT_OLEINITIALIZE - single threaded, additional OLE stuff + +COINIT_OLEINITIALIZE is sometimes needed when an OLE object uses +additional OLE compound document technologies not available from the +normal COM subsystem (for example MAPI.Session seems to require it). +Both COINIT_OLEINITIALIZE and COINIT_APARTMENTTHREADED create a hidden +top level window and a message queue for the Perl process. This may +create problems with other application, because Perl normally doesn't +process its message queue. This means programs using synchronous +communication between applications (such as DDE initiation), may hang +until Perl makes another OLE method call/property access or terminates. +This applies to InstallShield setups and many things started to shell +associations. Please try to utilize the C<Win32::OLE-E<gt>SpinMessageLoop> +and C<Win32::OLE-E<gt>Uninitialize> methods if you can not use the default +COINIT_MULTITHREADED model. + +=item OBJECT->Invoke(METHOD[, ARGS]) + +The Invoke() object method is an alternate way to invoke OLE +methods. It is normally equivalent to C<$OBJECT->METHOD(@ARGS)>. This +function must be used if the METHOD name contains characters not valid +in a Perl variable name (like foreign language characters). It can +also be used to invoke the default method of an object even if the +default method has not been given a name in the type library. In this +case use <undef> or C<''> as the method name. To invoke an OLE objects +native Invoke() method (if such a thing exists), please use: + + $Object->Invoke('Invoke', @Args); + +=item Win32::OLE->LastError() + +The LastError() class method returns the last recorded OLE +error. This is a dual value like the C<$!> variable: in a numeric +context it returns the error number and in a string context it returns +the error message. The error number is a signed HRESULT value. Please +use the L<HRESULT(ERROR)> function to convert an unsigned hexadecimal +constant to a signed HRESULT. + +The last OLE error is automatically reset by a successful OLE +call. The numeric value can also explicitly be set by a call (which will +discard the string value): + + Win32::OLE->LastError(0); + +=item OBJECT->LetProperty(NAME,ARGS,VALUE) + +In Win32::OLE property assignment using the hash syntax is equivalent +to the Visual Basic C<Set> syntax (I<by reference> assignment): + + $Object->{Property} = $OtherObject; + +corresponds to this Visual Basic statement: + + Set Object.Property = OtherObject + +To get the I<by value> treatment of the Visual Basic C<Let> statement + + Object.Property = OtherObject + +you have to use the LetProperty() object method in Perl: + + $Object->LetProperty($Property, $OtherObject); + +LetProperty() also supports optional arguments for the property assignment. +See L<OBJECT->SetProperty(NAME,ARGS,VALUE)> for details. + +=item Win32::OLE->MessageLoop() + +The MessageLoop() class method will run a standard Windows message +loop, dispatching messages until the QuitMessageLoop() class method is +called. It is used to wait for OLE events. + +=item Win32::OLE->Option(OPTION) + +The Option() class method can be used to inspect and modify +L<Module Options>. The single argument form retrieves the value of +an option: + + my $CP = Win32::OLE->Option('CP'); + +A single call can be used to set multiple options simultaneously: + + Win32::OLE->Option(CP => CP_ACP, Warn => 3); + +=item Win32::OLE->QueryObjectType(OBJECT) + +The QueryObjectType() class method returns a list of the type library +name and the objects class name. In a scalar context it returns the +class name only. It returns C<undef> when the type information is not +available. + +=item Win32::OLE->QuitMessageLoop() + +The QuitMessageLoop() class method posts a (user-level) "Quit" message +to the current threads message loop. QuitMessageLoop() is typically +called from an event handler. The MessageLoop() class method will +return when it receives this "Quit" method. + +=item OBJECT->SetProperty(NAME,ARGS,VALUE) + +The SetProperty() method allows to modify properties with arguments, +which is not supported by the hash syntax. The hash form + + $Object->{Property} = $Value; + +is equivalent to + + $Object->SetProperty('Property', $Value); + +Arguments must be specified between the property name and the new value: + + $Object->SetProperty('Property', @Args, $Value); + +It is not possible to use "named argument" syntax with this function +because the new value must be the last argument to SetProperty(). + +This method hides any native OLE object method called SetProperty(). +The native method will still be available through the Invoke() method: + + $Object->Invoke('SetProperty', @Args); + +=item Win32::OLE->SpinMessageLoop + +This class method retrieves all pending messages from the message queue +and dispatches them to their respective window procedures. Calling this +method is only necessary when not using the COINIT_MULTITHREADED model. +All OLE method calls and property accesses automatically process the +message queue. + +=item Win32::OLE->Uninitialize + +The Uninitialize() class method uninitializes the OLE subsystem. It +also destroys the hidden top level window created by OLE for single +threaded apartments. All OLE objects will become invalid after this call! +It is possible to call the Initialize() class method again with a different +apartment model after shutting down OLE with Uninitialize(). + +=item Win32::OLE->WithEvents(OBJECT[, HANDLER[, INTERFACE]]) + +This class method enables and disables the firing of events by the +specified OBJECT. If no HANDLER is specified, then events are +disconnected. For some objects Win32::OLE is not able to +automatically determine the correct event interface. In this case the +INTERFACE argument must contain either the COCLASS name of the OBJECT +or the name of the event DISPATCH interface. Please read the L<Events> +section below for detailed explanation of the Win32::OLE event +support. + +=back + +Whenever Perl does not find a method name in the Win32::OLE package it +is automatically used as the name of an OLE method and this method call +is dispatched to the OLE server. + +There is one special hack built into the module: If a method or property +name could not be resolved with the OLE object, then the default method +of the object is called with the method name as its first parameter. So + + my $Sheet = $Worksheets->Table1; +or + my $Sheet = $Worksheets->{Table1}; + +is resolved as + + my $Sheet = $Worksheet->Item('Table1'); + +provided that the $Worksheets object doesnot have a C<Table1> method +or property. This hack has been introduced to call the default method +of collections which did not name the method in their type library. The +recommended way to call the "unnamed" default method is: + + my $Sheet = $Worksheets->Invoke('', 'Table1'); + +This special hack is disabled under C<use strict 'subs';>. + +=head2 Object methods and properties + +The object returned by the new() method can be used to invoke +methods or retrieve properties in the same fashion as described +in the documentation for the particular OLE class (eg. Microsoft +Excel documentation describes the object hierarchy along with the +properties and methods exposed for OLE access). + +Optional parameters on method calls can be omitted by using C<undef> +as a placeholder. A better way is to use named arguments, as the +order of optional parameters may change in later versions of the OLE +server application. Named parameters can be specified in a reference +to a hash as the last parameter to a method call. + +Properties can be retrieved or set using hash syntax, while methods +can be invoked with the usual perl method call syntax. The C<keys> +and C<each> functions can be used to enumerate an object's properties. +Beware that a property is not always writable or even readable (sometimes +raising exceptions when read while being undefined). + +If a method or property returns an embedded OLE object, method +and property access can be chained as shown in the examples below. + +=head2 Functions + +The following functions are not exported by default. + +=over 8 + +=item HRESULT(ERROR) + +The HRESULT() function converts an unsigned number into a signed HRESULT +error value as used by OLE internally. This is necessary because Perl +treats all hexadecimal constants as unsigned. To check if the last OLE +function returned "Member not found" (0x80020003) you can write: + + if (Win32::OLE->LastError == HRESULT(0x80020003)) { + # your error recovery here + } + +=item in(COLLECTION) + +If COLLECTION is an OLE collection object then C<in $COLLECTION> +returns a list of all members of the collection. This is a shortcut +for C<Win32::OLE::Enum->All($COLLECTION)>. It is most commonly used in +a C<foreach> loop: + + foreach my $value (in $collection) { + # do something with $value here + } + +=item valof(OBJECT) + +Normal assignment of Perl OLE objects creates just another reference +to the OLE object. The valof() function explictly dereferences the +object (through the default method) and returns the value of the object. + + my $RefOf = $Object; + my $ValOf = valof $Object; + $Object->{Value} = $NewValue; + +Now $ValOf still contains the old value wheras $RefOf would +resolve to the $NewValue because it is still a reference to +$Object. + +The valof() function can also be used to convert Win32::OLE::Variant +objects to Perl values. + +=item with(OBJECT, PROPERTYNAME => VALUE, ...) + +This function provides a concise way to set the values of multiple +properties of an object. It iterates over its arguments doing +C<$OBJECT->{PROPERTYNAME} = $VALUE> on each trailing pair. + +=back + +=head2 Overloading + +The Win32::OLE objects can be overloaded to automatically convert to +their values whenever they are used in a bool, numeric or string +context. This is not enabled by default. You have to request it +through the OVERLOAD pseudoexport: + + use Win32::OLE qw(in valof with OVERLOAD); + +You can still get the original string representation of an object +(C<Win32::OLE=0xDEADBEEF>), e.g. for debugging, by using the +C<overload::StrVal()> method: + + print overload::StrVal($object), "\n"; + +Please note that C<OVERLOAD> is a global setting. If any module enables +Win32::OLE overloading then it's active everywhere. + +=head2 Events + +The Win32::OLE module now contains B<ALPHA> level event support. This +support is only available when Perl is running in a single threaded +apartment. This can most easily be assured by using the C<EVENTS> +pseudo-import: + + use Win32::OLE qw(EVENTS); + +which implicitly does something like: + + use Win32::OLE; + Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE); + +The current interface to OLE events should be considered experimental +and is subject to change. It works as expected for normal OLE +applications, but OLE control events often don't seem to work yet. + +Events must be enabled explicitly for an OLE object through the +Win32::OLE->WithEvents() class method. The Win32::OLE module uses the +IProvideClassInfo2 interface to determine the default event source of +the object. If this interface is not supported, then the user must +specify the name of the event source explicitly in the WithEvents() +method call. It is also possible to specify the class name of the +object as the third parameter. In this case Win32::OLE will try to +look up the default source interface for this COCLASS. + +The HANDLER argument to Win32::OLE->WithEvents() can either be a CODE +reference or a package name. In the first case, all events will invoke +this particular function. The first two arguments to this function will +be the OBJECT itself and the name of the event. The remaining arguments +will be event specific. + + sub Event { + my ($Obj,$Event,@Args) = @_; + print "Event triggered: '$Event'\n"; + } + Win32::OLE->WithEvents($Obj, \&Event); + +Alternatively the HANDLER argument can specify a package name. When the +OBJECT fires an event, Win32::OLE will try to find a function of the same +name as the event in this package. This function will be called with the +OBJECT as the first argument followed again by the event specific parameters: + + package MyEvents; + sub EventName1 { + my ($Obj,@Args) = @_; + print "EventName1 event triggered\n"; + } + + package main; + Win32::OLE->WithEvents($Obj, 'MyEvents', 'IEventInterface'); + +If Win32::OLE doesn't find a function with the name of the event then nothing +happens. + +Event parameters passed I<by reference> are handled specially. They are not +converted to the corresponding Perl datatype but passed as Win32::OLE::Variant +objects. You can assign a new value to these objects with the help of the +Put() method. This value will be passed back to the object when the event +function returns: + + package MyEvents; + sub BeforeClose { + my ($self,$Cancel) = @_; + $Cancel->Put(1) unless $MayClose; + } + +Direct assignment to $Cancel would have no effect on the original value and +would therefore not command the object to abort the closing action. + +=head2 Module Options + +The following module options can be accessed and modified with the +C<Win32::OLE->Option> class method. In earlier versions of the Win32::OLE +module these options were manipulated directly as class variables. This +practice is now deprecated. + +=over 8 + +=item CP + +This variable is used to determine the codepage used by all +translations between Perl strings and Unicode strings used by the OLE +interface. The default value is CP_ACP, which is the default ANSI +codepage. Other possible values are CP_OEMCP, CP_MACCP, CP_UTF7 and +CP_UTF8. These constants are not exported by default. + +=item LCID + +This variable controls the locale idnetifier used for all OLE calls. +It is set to LOCALE_NEUTRAL by default. Please check the +L<Win32::OLE::NLS> module for other locale related information. + +=item Variant + +This options controls how method calls and property accessors return +values of type VT_CY and VT_DECIMAL are being returned. By default +VT_CY values are turned into strings and VT_DECIMAL values into +floating point numbers. If the C<Variant> option is enabled, these +values are returned as Win32::OLE::Variant objects, just like VT_DATE +and VT_ERROR values. If the Win32::OLE::Variant module is also +loaded, then all values should still behave as before in string and in +numeric context. + +The only reason that the C<Variant> behavior is not the default is that +this is an incompatible change that might break existing programs. + +=item Warn + +This variable determines the behavior of the Win32::OLE module when +an error happens. Valid values are: + + 0 Ignore error, return undef + 1 Carp::carp if $^W is set (-w option) + 2 always Carp::carp + 3 Carp::croak + +The error number and message (without Carp line/module info) are +available through the C<Win32::OLE->LastError> class method. + +Alternatively the Warn option can be set to a CODE reference. E.g. + + Win32::OLE->Option(Warn => 3); + +is equivalent to + + Win32::OLE->Option(Warn => \&Carp::croak); + +This can even be used to emulate the VisualBasic C<On Error Goto +Label> construct: + + Win32::OLE->Option(Warn => sub {goto CheckError}); + # ... your normal OLE code here ... + + CheckError: + # ... your error handling code here ... + +=item _NewEnum + +This option enables additional enumeration support for collection +objects. When the C<_NewEnum> option is set, all collections will +receive one additional property: C<_NewEnum>. The value of this +property will be a reference to an array containing all the elements +of the collection. This option can be useful when used in conjunction +with an automatic tree traversal program, like C<Data::Dumper> or an +object tree browser. The value of this option should be either 1 +(enabled) or 0 (disabled, default). + + Win32::OLE->Option(_NewEnum => 1); + # ... + my @sheets = @{$Excel->Worksheets->{_NewEnum}}; + +In normal application code, this would be better written as: + + use Win32::OLE qw(in); + # ... + my @sheets = in $Excel->Worksheets; + +=item _Unique + +The C<_Unique> options guarantees that Win32::OLE will maintain a +one-to-one mapping between Win32::OLE objects and the native COM/OLE +objects. Without this option, you can query the same property twice +and get two different Win32::OLE objects for the same underlying COM +object. + +Using a unique proxy makes life easier for tree traversal algorithms +to recognize they already visited a particular node. This option +comes at a price: Win32::OLE has to maintain a global hash of all +outstanding objects and their corresponding proxies. Identity checks +on COM objects can also be expensive if the objects reside +out-of-process or even on a different computer. Therefore this option +is off by default unless the program is being run in the debugger. + +Unfortunately, this option doesn't always help. Some programs will +return new COM objects for even the same property when asked for it +multiple times (especially for collections). In this case, there is +nothing Win32::OLE can do to detect that these objects are in fact +identical (because they aren't at the COM level). + +The C<_Unique> option can be set to either 1 (enabled) or 0 (disabled, +default). + +=back + +=head1 EXAMPLES + +Here is a simple Microsoft Excel application. + + use Win32::OLE; + + # use existing instance if Excel is already running + 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"; + } + + # get a new workbook + $book = $ex->Workbooks->Add; + + # write to a particular cell + $sheet = $book->Worksheets(1); + $sheet->Cells(1,1)->{Value} = "foo"; + + # write a 2 rows by 3 columns range + $sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ], + [ 42, 'Perl', 3.1415 ]]; + + # print "XyzzyPerl" + $array = $sheet->Range("A8:C9")->{Value}; + for (@$array) { + for (@$_) { + print defined($_) ? "$_|" : "<undef>|"; + } + print "\n"; + } + + # save and exit + $book->SaveAs( 'test.xls' ); + undef $book; + undef $ex; + +Please note the destructor specified on the Win32::OLE->new method. It ensures +that Excel will shutdown properly even if the Perl program dies. Otherwise +there could be a process leak if your application dies after having opened +an OLE instance of Excel. It is the responsibility of the module user to +make sure that all OLE objects are cleaned up properly! + +Here is an example of using Variant data types. + + 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; + } + +The above will put value "3" in cell A1 rather than the string +"3 is a good number". Cell A2 will contain the date. + +Similarly, to invoke a method with some binary data, you can +do the following: + + $obj->Method( Variant(VT_UI1, "foo\000b\001a\002r") ); + +Here is a wrapper class that basically delegates everything but +new() and DESTROY(). The wrapper class shown here is another way to +properly shut down connections if your application is liable to die +without proper cleanup. Your own wrappers will probably do something +more specific to the particular OLE object you may be dealing with, +like overriding the methods that you may wish to enhance with your +own. + + 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; + +The above module can be used just like Win32::OLE, except that +it takes care of closing connections in case of abnormal exits. +Note that the effect of this specific example can be easier accomplished +using the optional destructor argument of Win32::OLE::new: + + my $Excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;}); + +Note that the delegation shown in the earlier example is not the same as +true subclassing with respect to further inheritance of method calls in your +specialized object. See L<perlobj>, L<perltoot> and L<perlbot> for details. +True subclassing (available by setting C<@ISA>) is also feasible, +as the following example demonstrates: + + # + # Add error reporting to 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; + +This package inherits the constructor new() from the Win32::OLE +package. It is important to note that you cannot later rebless a +Win32::OLE object as some information about the package is cached by +the object. Always invoke the new() constructor through the right +package! + +Here's how the above class will be used: + + use Win32::OLE::Strict; + my $Excel = Win32::OLE::Strict->new('Excel.Application', 'Quit'); + my $Books = $Excel->Workbooks; + $Books->UnknownMethod(42); + +In the sample above the call to UnknownMethod() will be caught with + + UnknownMethod returned OLE error 0x80020009 at test.pl line 5 + +because the Workbooks object inherits the class C<Win32::OLE::Strict> from the +C<$Excel> object. + +=head1 NOTES + +=head2 Hints for Microsoft Office automation + +=over 8 + +=item Documentation + +The object model for the Office applications is defined in the Visual Basic +reference guides for the various applications. These are typically not +installed by default during the standard installation. They can be added +later by rerunning the setup program with the custom install option. + +=item Class, Method and Property names + +The names have been changed between different versions of Office. For +example C<Application> was a method in Office 95 and is a property in +Office97. Therefore it will not show up in the list of property names +C<keys %$object> when querying an Office 95 object. + +The class names are not always identical to the method/property names +producing the object. E.g. the C<Workbook> method returns an object of +type C<Workbook> in Office 95 and C<_Workbook> in Office 97. + +=item Moniker (GetObject support) + +Office applications seem to implement file monikers only. For example +it seems to be impossible to retrieve a specific worksheet object through +C<GetObject("File.XLS!Sheet")>. Furthermore, in Excel 95 the moniker starts +a Worksheet object and in Excel 97 it returns a Workbook object. You can use +either the Win32::OLE::QueryObjectType class method or the $object->{Version} +property to write portable code. + +=item Enumeration of collection objects + +Enumerations seem to be incompletely implemented. Office 95 application don't +seem to support neither the Reset() nor the Clone() methods. The Clone() +method is still unimplemented in Office 97. A single walk through the +collection similar to Visual Basics C<for each> construct does work however. + +=item Localization + +Starting with Office 97 Microsoft has changed the localized class, method and +property names back into English. Note that string, date and currency +arguments are still subject to locale specific interpretation. Perl uses the +system default locale for all OLE transaction whereas Visual Basic uses a +type library specific locale. A Visual Basic script would use "R1C1" in string +arguments to specify relative references. A Perl script running on a German +language Windows would have to use "Z1S1". Set the LCID module option +to an English locale to write portable scripts. This variable should +not be changed after creating the OLE objects; some methods seem to randomly +fail if the locale is changed on the fly. + +=item SaveAs method in Word 97 doesn't work + +This is an known bug in Word 97. Search the MS knowledge base for Word / +Foxpro incompatibility. That problem applies to the Perl OLE interface as +well. A workaround is to use the WordBasic compatibility object. It doesn't +support all the options of the native method though. + + $Word->WordBasic->FileSaveAs($file); + +The problem seems to be fixed by applying the Office 97 Service Release 1. + +=item Randomly failing method calls + +It seems like modifying objects that are not selected/activated is sometimes +fragile. Most of these problems go away if the chart/sheet/document is +selected or activated before being manipulated (just like an interactive +user would automatically do it). + +=back + +=head2 Incompatibilities + +There are some incompatibilities with the version distributed by Activeware +(as of build 306). + +=over 8 + +=item 1 + +The package name has changed from "OLE" to "Win32::OLE". + +=item 2 + +All functions of the form "Win32::OLEFoo" are now "Win32::OLE::Foo", +though the old names are temporarily accomodated. Win32::OLECreateObject() +was changed to Win32::OLE::CreateObject(), and is now called +Win32::OLE::new() bowing to established convention for naming constructors. +The old names should be considered deprecated, and will be removed in the +next version. + +=item 3 + +Package "OLE::Variant" is now "Win32::OLE::Variant". + +=item 4 + +The Variant function is new, and is exported by default. So are +all the VT_XXX type constants. + +=item 5 + +The support for collection objects has been moved into the package +Win32::OLE::Enum. The C<keys %$object> method is now used to enumerate +the properties of the object. + +=back + +=head2 Bugs and Limitations + +=over 8 + +=item * + +To invoke a native OLE method with the same name as one of the +Win32::OLE methods (C<Dispatch>, C<Invoke>, C<SetProperty>, C<DESTROY>, +etc.), you have to use the C<Invoke> method: + + $Object->Invoke('Dispatch', @AdditionalArgs); + +The same is true for names exported by the Exporter or the Dynaloader +modules, e.g.: C<export>, C<export_to_level>, C<import>, +C<_push_tags>, C<export_tags>, C<export_ok_tags>, C<export_fail>, +C<require_version>, C<dl_load_flags>, +C<croak>, C<bootstrap>, C<dl_findfile>, C<dl_expandspec>, +C<dl_find_symbol_anywhere>, C<dl_load_file>, C<dl_find_symbol>, +C<dl_undef_symbols>, C<dl_install_xsub> and C<dl_error>. + +=back + +=head1 SEE ALSO + +The documentation for L<Win32::OLE::Const>, L<Win32::OLE::Enum>, +L<Win32::OLE::NLS> and L<Win32::OLE::Variant> contains additional +information about OLE support for Perl on Win32. + +=head1 AUTHORS + +Originally put together by the kind people at Hip and Activeware. + +Gurusamy Sarathy <gsar@cpan.org> 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). + +=head1 COPYRIGHT + + (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-2006 by Gurusamy Sarathy + <gsar@cpan.org> 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. + +=head1 VERSION + +Version 0.1709 17 April 2008 + +=cut |