seeking Win32::OLE example

G

Greg Bacon

I was trying to put together a quick hack to extract review comments
(using the Comments property) from a Word document to jump start
compiling review minutes, but I found the MSDN Word object model
documentation surprisingly opaque. For example, the docs didn't say
which property held the comment tag (e.g., [b1]), and the empirical
measure of iterating over the keys didn't bear fruit.

I played with the code in <[email protected]> and found
that it made a difference whether I called Documents->Open or
GetActiveObject -- although the two seem equivalent in the docs.

Can people recommend a good resource? I read Jan's TPJ article and
the various pods, but I was frustrated with my low progress.

Thanks,
Greg
 
J

Jay Tilton

(e-mail address removed) (Greg Bacon) wrote:

: I was trying to put together a quick hack to extract review comments
: (using the Comments property) from a Word document to jump start
: compiling review minutes, but I found the MSDN Word object model
: documentation surprisingly opaque. For example, the docs didn't say
: which property held the comment tag (e.g., [b1]),

What is your example "[b1]" meant to show? Is that the expected content
of the document's comments property?

: and the empirical
: measure of iterating over the keys didn't bear fruit.

A splash of code will better show what you are talking about, and will
probably show where the difficulty lies.

: I played with the code in <[email protected]> and found
: that it made a difference whether I called Documents->Open or
: GetActiveObject -- although the two seem equivalent in the docs.

Which docs were you reading that suggested that the
Win32::OLE->GetActiveObject method is similar to the Word application's
Documents->Open method?

Are you perhaps thinking of the Win32::OLE->GetObject method when you
say GetActiveObject?

: Can people recommend a good resource?

A resource on using Win32::OLE? The pods that come with ActivePerl are
pretty much it, and pretty much all that is needed. Win32::OLE is not
much more than a way for Perl to poke and prod at OLE libaries.

A resource on how any of those libraries responds to being poked and
prodded? That's a job for the library's author.

The OLE Browser included with ActivePerl is a decent tool for navigating
the various libraries and the classes within those libraries. Be sure
to notice the clickable help icon in the bottom frame.

The object browser in the Visual Basic Editor (included with any Office
installation) does mostly the same job, but also has a very useful
search tool.

As for your original quick hack program, see if this does not fill the
need.

#!perl
use warnings;
use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Word';
print
Win32::OLE
->GetObject('foo.doc')
->BuiltinDocumentProperties(wdPropertyComments)
->Value;
 
G

Greg Bacon

: (e-mail address removed) (Greg Bacon) wrote:
:
: : I was trying to put together a quick hack to extract review comments
: : (using the Comments property) from a Word document to jump start
: : compiling review minutes, but I found the MSDN Word object model
: : documentation surprisingly opaque. For example, the docs didn't say
: : which property held the comment tag (e.g., [b1]),
:
: What is your example "[b1]" meant to show? Is that the expected content
: of the document's comments property?

No, not the comment itself, the comment *tag*. I'm talking about the
tags identify each comment and show up in the document as hidden text.
The leader seems to be the author's initials because in a dummy doc I
just created, Word tagged my comments as [geb1] and so on.

The comment text itself is straightforward:

print "$_->{Range}{Text}\n" for in $Doc->{Comments};

: : and the empirical
: : measure of iterating over the keys didn't bear fruit.
:
: A splash of code will better show what you are talking about, and will
: probably show where the difficulty lies.

Here's the code I've been using to explore:

#! perl

use strict;
use Win32::OLE qw/ in /;

sub usage { "Usage: $0 [--active | --open]\n" }

## main
die usage unless @ARGV;

Win32::OLE->Option(Warn => 2);

my $Word;
my $Doc;

my $arg = shift;
if ($arg eq '--active') {
$Doc = Win32::OLE->GetActiveObject('Word.Application', 'Quit');
}
elsif ($arg eq '--open') {
$Word = Win32::OLE->new('Word.Application', 'Quit');

# requires absolute path?
$Doc = $Word->Documents->Open('c:\temp\foo.doc');
}

#$Doc->{Visible} = 1;

foreach my $Property (in $Doc->BuiltinDocumentProperties) {
my $Name = $Property->Name;
local $Win32::OLE::Warn = 0;
my $Value = $Property->Value;

$Value = '***Error***' if Win32::OLE->LastError;
$Value = '<undef>' unless defined $Value;
printf "%s %s = %s\n", $Name, '.' x (40-length($Name)), $Value;
}

foreach my $c (in $Doc->{Comments}) {
print $c->{Reference}{BookmarkID}, " - ", $c->{Range}{Text}, "\n";
}

#$Doc->{Saved} = 1;

In the loop over BuiltinDocumentProperties, I'd tried iterating
over keys %$Property and printing out the values, but the comment
tag didn't appear.

: : I played with the code in <[email protected]> and found
: : that it made a difference whether I called Documents->Open or
: : GetActiveObject -- although the two seem equivalent in the docs.
:
: Which docs were you reading that suggested that the
: Win32::OLE->GetActiveObject method is similar to the Word application's
: Documents->Open method?
:
: Are you perhaps thinking of the Win32::OLE->GetObject method when you
: say GetActiveObject?

I see that I was unclear. I should have written "equivalent, assuming
the document we want is open". Using the code above with the --active
option, I get the following error:

Win32::OLE(0.1603) error 0x80020011: "Does not support a collection"
in METHOD/PROPERTYGET "" at props line 29
Can't call method "Name" on an undefined value at props line 30.

I obviously read more into the docs than was there, and I'm happy to
take correction. Where can I find a good orientation to thinking OLE?

: : Can people recommend a good resource?
:
: A resource on using Win32::OLE? The pods that come with ActivePerl are
: pretty much it, and pretty much all that is needed. Win32::OLE is not
: much more than a way for Perl to poke and prod at OLE libaries.
:
: A resource on how any of those libraries responds to being poked and
: prodded? That's a job for the library's author.
:
: The OLE Browser included with ActivePerl is a decent tool for navigating
: the various libraries and the classes within those libraries. Be sure
: to notice the clickable help icon in the bottom frame.

Didn't notice the help icon before. Thanks for the pointer. I'm
closer:

foreach my $c (in $Doc->{Comments}) {
my $tag = $c->{Initial} . $c->{Index};
print "$tag - ", $c->{Range}{Text}, "\n";
}

Now I'm trying to get at the highlighted portion of the document
associated with a given comment. Strike that:

foreach my $c (in $Doc->{Comments}) {
my $tag = $c->{Initial} . $c->{Index};
print $tag, " - ", $c->{Range}{Text}, "\n";
print $c->{Scope}{Text}, "\n";
}

: [...]
: As for your original quick hack program, see if this does not fill the
: need.
:
: #!perl
: use warnings;
: use strict;
: use Win32::OLE;
: use Win32::OLE::Const 'Microsoft Word';
: print
: Win32::OLE
: ->GetObject('foo.doc')
: ->BuiltinDocumentProperties(wdPropertyComments)
: ->Value;

That produced no output. (Yes, I used the appropriate path.)

A couple of remaining questions:

Why does iterating over the BuiltinDocumentProperties make the
application think I have changes that need saving? (I see that setting
the Saved property says nothing needs saving.)

What the difference between getting at the document via Documents->Open
versus GetActiveObject? I'd like to avoid typing long paths.

Greg, drifting off-topic :-(
 
J

Jay Tilton

(e-mail address removed) (Greg Bacon) wrote:

: In article <[email protected]>,
:
: : (e-mail address removed) (Greg Bacon) wrote:
: :
: : : I was trying to put together a quick hack to extract review comments
: : : (using the Comments property) from a Word document
:
: No, not the comment itself, the comment *tag*. I'm talking about the
: tags identify each comment and show up in the document as hidden text.
: The leader seems to be the author's initials because in a dummy doc I
: just created, Word tagged my comments as [geb1] and so on.

I'm hip. You want the comments embedded within the document's body, not
the "comment" property of the document object.

: Here's the code I've been using to explore:

[snipped here, but mostly retained in comments below]

: : : I played with the code in <[email protected]> and found
: : : that it made a difference whether I called Documents->Open or
: : : GetActiveObject -- although the two seem equivalent in the docs.
: :
: I see that I was unclear. I should have written "equivalent, assuming
: the document we want is open". Using the code above with the --active
: option, I get the following error:
:
: Win32::OLE(0.1603) error 0x80020011: "Does not support a collection"
: in METHOD/PROPERTYGET "" at props line 29
: Can't call method "Name" on an undefined value at props line 30.

I see now. No, the GetActiveObject method cannot be used to hook into
an already-open document in one step. It can be used to connect with a
running Word application, then that application object can return the
open document.

#! perl
use strict;
use Win32::OLE qw/ in /;
sub usage { "Usage: $0 [--active | --open]\n" }
die usage unless @ARGV;
Win32::OLE->Option(Warn => 2);
my $Word;
my $Doc;
my $arg = shift;
if ($arg eq '--active') {
$Word = Win32::OLE->GetActiveObject('Word.Application');
$Doc = $Word->Documents->Item(1);
}
elsif ($arg eq '--open') {
$Word = Win32::OLE->new('Word.Application', 'Quit');
$Doc = $Word->Documents->Open('c:\temp\foo.doc');
}

: I obviously read more into the docs than was there, and I'm happy to
: take correction. Where can I find a good orientation to thinking OLE?

I don't know. Familiarity with the various forms of Visual Basic is
helpful. Drafting a program in VBScript and running it with the Windows
Script Host (cscript.exe) is often useful since you won't need to
translate sample code into its Perl equivalent.

: Now I'm trying to get at the highlighted portion of the document
: associated with a given comment. Strike that:
:
: foreach my $c (in $Doc->{Comments}) {
: my $tag = $c->{Initial} . $c->{Index};
: print $tag, " - ", $c->{Range}{Text}, "\n";
: print $c->{Scope}{Text}, "\n";
: }

That seems to work well. Does it need more tweaking?

: : As for your original quick hack program, see if this does not fill the
: : need.
:
[code snipped]
:
: That produced no output. (Yes, I used the appropriate path.)

Just as well. You want the inline comments, not the document's Comments
property. These aren't the droids you're looking for.

: A couple of remaining questions:
:
: Why does iterating over the BuiltinDocumentProperties make the
: application think I have changes that need saving? (I see that setting
: the Saved property says nothing needs saving.)

I don't know. Reasonably, a simple peek at an object's properties
should not alter the object. It is quite a nuisance.

: What the difference between getting at the document via Documents->Open
: versus GetActiveObject? I'd like to avoid typing long paths.

See above.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top