Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have the following code, which WORKS for a word file, but crashes for a similar word file (both docx)
use strict; use Excel::Writer::XLSX; use Spreadsheet::ParseXLSX; use Carp qw( croak ); use Cwd qw( abs_path ); use Path::Class; use Win32::OLE qw(in); use Win32::OLE::Const 'Microsoft Word'; ... my $path=....; my $word =Win32::OLE->new('Word.Application','Quit'); my $word_file = file(abs_path($path)); my $doc = $word->{Documents}->Open("$word_file"); print "after doc\n"; my $tables = $word->ActiveDocument->{Tables}; for my $table (in $tables) { my $numrows=$table->Rows->Count; $main::numcols=$table->Columns->Count; # Iterate through rows and count columns foreach my $rownum (1 .. $table->Rows->Count) { my $row = $table->Rows->Item($rownum);# code crashes here ... } }
The code crashes as indicated with the message

Win32::OLE(0.1712) error 0x8002000e: "Invalid number of parameters" in METHOD/PROPERTYGET "Item" at C:/Strawberry/perl/lib/Devel/ptkdb.pm line 2658.

When I try to debug with ptkdb it crashes as soon as I ask for a listing of $doc or $table How do I go about debugging this??

Replies are listed 'Best First'.
Re: WIn32::OLE debug
by Corion (Patriarch) on Oct 12, 2025 at 08:03 UTC

    It helps a bit to know about VBA / OLE. The ->Item method is what is used to enumerate arrays. The in function is what maps that to Perl.

    In your code, you have:

    my $tables = $word->ActiveDocument->{Tables}; for my $table (in $tables) {

    If the document has no tables, maybe $tables is undef. Check for that.

    If your debugger crashes, do print debugging:

    my $tables = $word->ActiveDocument->{Tables}; print "Tables is <$tables>"; print sprintf "Tables has %d items", $tables->Count; for my $table (in $tables) {
Re: WIn32::OLE debug
by Marshall (Canon) on Oct 12, 2025 at 04:43 UTC
    1. First step turn STDOUT buffering off
    $|=1; #put at top of code
    This allows error messages and normal prints to appear in the order of execution.

    2. You have one doc that works and one that doesn't.
    Add error checking on the opens and new operations.
    my $word =Win32::OLE->new('Word.Application','Quit') or die "blah$!";
    my $doc = $word->{Documents}->Open("$word_file") or die "bla2$!";

    3. Add some prints for each variable - look for something weird like undef value

    Update:
    From your description, it looks like tabler 1 in the failing doc is what is failing.
    Try cut and paste the table that works from doc 1 to doc 2.
    Again make sure the open worked. you could conceiveably get your error if the Word doc didn't open.

    Do both docs render ok on the screen? Can you print them without problems?

    It is possible with the drawing tools to make something that looks like a table, but is not a table in the Word sense.

      Thanks, I did try your advice. The result:

      Tables is <Win32::OLE=HASH(0x57d0ab0)>Tables has 70 itemsbefore table loop

      table=Win32::OLE=HASH(0x57d0c60) file=C:\Users\...\mydoc.docx

      numrows=23

      table rows count= Win32::OLE=HASH(0x5606e48)->Rows->Count

      OLE exception from "Microsoft Word":

      ?e? e??a? d??at? ? p??s▀as? ╡e╡???╡???? ??a╡╡?? se a?t?? t? s??????, epe?d? ? p??a?a? ??e? s?????e?╡??a ?e??? ?ata????fa.

      Win32::OLE(0.1712) error 0x800a1767 in METHOD/PROPERTYGET "Item" at parserworks16.pl line 188.

      The failing line is the last line shown
      print "table rows count= $table->Rows->Count \n"; # this print seems t +o indicate the problem foreach my $rownum (1 .. $table->Rows->Count) { my $row = $table->Rows->Item($rownum);
      So it looks like $table->Rows->Count is an object instead of a number! Why is that ?
        Method calls are not interpolated in double quoted strings. Therefore,
        print "table rows count= $table->Rows->Count \n";

        only interpolates $table. Instead, try

        print 'table rows count = ', $table->Rows->Count, ".\n";

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]