EDIT: If you have an example in VBA, I'll take it. I'm just trying to understand how to use the Range object with the Tables collection to copy and paste multiple tables without looping. Put another way, how can I specify a range of 1..lastTable using the Tables collection? If I can see a working VBA example of this, I'll work on the VBA --> Perl conversion.
I'm trying to use Perl's Win32::OLE module (via Dave Roth's excellent book) to automate a couple tasks I need to repeatedly perform on some Word documents. However, the book (and most web examples) tends to use Excel for examples, so I am not sure how to copy and paste effectively with the Tables collection object.
Here is a snippet of my code:
my $originalDoc = $MSWord->Documents->Open('C:\Perl\testDocument.doc');
my $newDoc = $MSWord->Documents->Add;
my $selection = $MSWord->Selection(); # this may be spurious
my $Count = int( $originalDoc->Tables()->{Count} );
my $range = $originalDoc->Tables()->Range( { Start => $originalDoc->Tables(1)->{Range}->{Start},
End => $originalDoc->Tables($Count)->{Range}->{End}
} );
$range->Copy();
$newDoc->Range()->Paste();
The original code used Paragraphs, not Tables, so I assume some of the bugs are artifacts from that code (or more likely my non-understanding of that code).
Copying and pasting tables one at a time might be preferable:
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions qw( catfile );
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Word';
$Win32::OLE::Warn = 3;
my $word = get_word();
$word->{Visible} = 1;
my $doc = $word->{Documents}->Open(catfile $ENV{TEMP}, 'test.doc');
my $newdoc = $word->Documents->Add;
my $n_tables = $doc->Tables->Count;
for my $table_i ( 1 .. $n_tables ) {
my $table = $doc->Tables->Item($table_i);
$table->Select;
$word->Selection->Copy;
my $end = $newdoc->GoTo(wdGoToLine, wdGoToLast);
$end->InsertBefore("\n");
$end = $newdoc->GoTo(wdGoToLine, wdGoToLast);
$end->Select;
$word->Selection->Paste;
}
$doc->Close(0);
$newdoc->SaveAs('test-output.doc');
sub get_word {
my $word;
eval {
$word = Win32::OLE->GetActiveObject('Word.Application');
};
die "$@\n" if $@;
unless(defined $word) {
$word = Win32::OLE->new('Word.Application', sub { $_[0]->Quit })
or die "Oops, cannot start Word: ",
Win32::OLE->LastError, "\n";
}
return $word;
}