4

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).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
romandas
  • 4,086
  • 7
  • 29
  • 33
  • My suggestion is to try performing the task manually while recording a macro, then look at the VBA subroutine produced. You should be able to generalise that and transpose it into Perlish without much trouble. – j_random_hacker Sep 16 '09 at 15:51
  • Using this method just shows me how to use Selection to obtain one table, whereas if I try to select multiple tables, the macro is written to grab the text between them as well, which is not what I'm after. – romandas Sep 17 '09 at 12:48

1 Answers1

6

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;
}
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • Great! One question though.. is there no way to select a range of objects from a collection object? Say, all the table objects, without any other text in one operation? I'm just asking about whether this is possible -- I'm getting the impression it isn't, or at least it doesn't work the way I think it could. – romandas Sep 20 '09 at 18:42
  • @romandas I do not think so. The `Tables` collection does not have a `Range` method. – Sinan Ünür Sep 20 '09 at 19:17