John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

Consider this code:
my $filename= shift @ARGV; print "processing [$filename]\n"; my $Doc= Win32::OLE->GetObject ($filename, sub {$_[0]->Close()} ); print "** $Doc $Doc->{FullName}\n"; $Doc->SaveAs ('F:\\dev\\experiment\\ScanWord\\foobar.doc');
I've got several problems here, which I think are all related. When I run this, giving it a fully-qualified file name of a Word document, it apparently does load the object and hooks it up to the proper COM server, because the FullName property works and SaveAs works.

But then when it quits, it can't Close the document (error says "This method or property is not available because a document window is not active". Close method is documented as taking either a Window or a Document or Pane, so why doens't it close this document?).

Meanwhile, after Perl terminates, WINWORD.EXE is still running, and still has the file foobar.doc open. That problem (I would have thought that this whole reference counting thing would have taken care of it!) is why I put the Close in the destructor-spec in the first place.

Any clues, please? Pointers to better Win32::OLE information than came with the .pm?

—John

Replies are listed 'Best First'.
Re: Win32::OLE problem with Destructing
by cacharbe (Curate) on Jul 21, 2001 at 00:41 UTC
    I'm in a bit of a hurry, but I'll UPDATE this when I get home. Until then, here's some food for thought:

    $Doc->Activate(); $Doc->SaveAs ('F:\\dev\\experiment\\ScanWord\\foobar.doc');

    You need to have an "Active Document" for it to work. You might also have to instantiate an object pointing at word specifically to use
    $Word->ActiveDocument->SaveAs()

    use Win32::OLE qw(in with); use Win32::OLE::Const 'Microsoft Word'; $Win32::OLE::Warn = 2; # Throw Errors, I'll catch them my $Word = Win32::OLE->GetActiveObject('Word.Application') || Win32::OLE->new('Word.Application', 'Quit'); my $Doc = Win32::OLE->GetObject($wrdfile) || die &CheckError(); #### or #### my $Doc = $Word->Documents->Open($wrdfile) || die &CheckError();
    C-.
      Why should it have to be active before it can be saved, if I'm telling it which object to use?

      I think it's a bug, because if I have Word open it doesn't object to that! Even though this document never shows up in the Word interactive application. So perhaps Word is getting an internal error because at some point it assumes that there is some Active document and dereferencing it or something?

      —John

        Was that the solution, then?

        A document doesn't close itself, the application does it.

        You are telling the word application implicitly that you want the object that it is working on to be the 'Active' document. It doesn't have to be active for many (most) functions/methods/objects to be referenced, but Close is an exception. It's true with all of the office applications. The Application Engine needs to activate implicitly the open object that needs to be acted on, etc.

        You can also name the document specifically through the application object:

        $Word->$Documents($Docname)->SaveAs($filename); $Word->$Documents($Docname)->Close; undef $Doc;

        if the document already has a name.

        C-.

Re: Win32::OLE problem with Destructing
by rchiav (Deacon) on Jul 21, 2001 at 00:30 UTC
    Rewriting due to connectivity problems

    There are two things you might want to try..

    1) Close the doc first.. $Doc->Close(); 2)Use the quit method when trying to close Word. $_[0]->Quit();

    And as far as the Win32::OLE docs, they are pretty good. What you're probably after is more information on the Word Object Model.

    Hope this helps
    Rich

      why would calling $Doc->Close() "first" (first compared to what?) work better than letting the "destruct" do that?

      I'm not explicitly creating a Word application. I would have supposed that if it was created, it will be destroyed when the last ref goes out of scope; if it found an existing one, it shares counts with that. I don't want to just call Quit blindly!

      —John