简体   繁体   中英

Opening/Activating Word Documents in a VBA macro

I'm hoping a VB/VBA expert can help me out. Consider the following: The user opens a document in Word 2003, and within the Normal.dot AutoOpen macro, we look at current document, and if it has been opened by clicking on a link on a webpage, and meets certain other application specific criteria, close the streamed 'copy' and open the source document (found on a shared drive we can assume the user has access to):

Documents.Open origDoc
Documents(ActiveDocument.FullName).Close SaveChanges:=wdDoNotSaveChanges
Documents(origDoc).Activate

With ActiveDocument
    ''# Do work
End With

My thought was that I needed to call Activate to ensure that the original document was the ActiveDocument , but I'm getting a 4160 'Bad file name' error on the .Activate call. If I comment out the call to .Activate , it appears that ActiveDocument is set to the origDoc document, even if there were other documents already opened (I'm not really sure how the Documents Collection is managed, and how Word determines what next ActiveDocument would be if you programatically close the current ActiveDocument)

So, does calling .Open on a document explicitly set the Document to be the ActiveDocument ? Also, does calling .Activate on the already active document cause an error?

I haven't really been able to find much documentation about this, so thanks in advance for any suggestions and insight!

The simple answer is yes. By opening the document with your code you make it the active document, which you then close in the next line and try to activate in the next, and this fails because the document is no longer open. VBA in general seems to work this way.

It is important to be careful with ActiveDocument, because it's not always self-evident what actions, in code or elsewhere, will make a document 'active' (i have no proof but even an autosave might do it). IF there's any doubt you're better off referring to a document through the Documents collection, though this can also cause errors if the document is no longer open, and you might have to resort to iterating through the collection to be sure the document is, in fact, open. I run into this a lot with excel VBA, and Word VBA seems to function identically in that regard.

Also, VBA is flaky about releasing application objects. If you're not careful you'll end up with multiple WINWORD processes,viewable in task manager, regardless of whether you Close or Quit them in your code. The code I've found to work around this amounts to simulating the process of selecting END PROCESS in task manager. It works, but there should be a better solution.

Beware that there are a variety of problems that can be encountered:

  1. if you want to re-open the document after closing it once....Word/Windows DOES NOT 'release' the filename and you get a ' file busy ' message, or message about 'creating a temporary copy '. to deal with this problem, I've had to develop an elaborate system of creating/saving and tidying up multiple versions of any other documents I open/manipulate in my Word applications because of this design flaw in Office Open / Close / Save methods.

  2. Use the ReadOnlyRecommended property set to False with the .Open method

  3. referring to the document object (named doc, above) can cause serious errors if you do not assure that the doc object still exists before you try and manipulate it. Remember always, that Word is an 'open' application platform....and the user can be doing things you didn't count on...in the last millisecond or so. This advice holds for any other object or property you may wish to manipulate in Word.

  4. if you manipulate the Documents collection (or any other) without assuring that the document or other object is still there and valid before deleting or moving it within the collection you may
    get ' stack overflow ' errors. Particularly if you try and close/delete objects in a collection starting at .item(1) . You must delete items in a collection from the last one, and remember that the collection idicies and pointers change whenever you.add/.remove/.close items from them.

You have an error here:

Document(origDoc).Activate

Should be Document s .

Yes, you can activate the active document. Nothing happens then.

Yes, opened document becomes active. If you are not sure, use Documents.Open(origDoc).Activate .

You shouldn't be using the ActiveDocument object in the first place unless absolutely necessary because it's very unreliable. The preferred approach would be this:

Documents(ActiveDocument.FullName).Close SaveChanges:=wdDoNotSaveChanges

Dim doc as Document
Set doc = Documents.Open(origDoc)        
With doc
    'Do work
End With

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM