简体   繁体   English

在 VBA 宏中打开/激活 Word 文档

[英]Opening/Activating Word Documents in a VBA macro

I'm hoping a VB/VBA expert can help me out.我希望 VB/VBA 专家可以帮助我。 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):考虑以下情况:用户在 Word 2003 中打开一个文档,在 Normal.dot AutoOpen宏中,我们查看当前文档,如果它是通过单击网页上的链接打开的,并且满足某些其他特定于应用程序的条件,关闭流式传输的“副本”并打开源文档(在我们可以假设用户有权访问的共享驱动器上找到):

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.我的想法是我需要调用Activate以确保原始文档是ActiveDocument ,但我在.Activate调用中收到 4160 'Bad file name' 错误。 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)如果我注释掉对.Activate的调用,似乎ActiveDocument设置为 origDoc 文档,即使已经打开了其他文档(我不太确定如何管理 Documents Collection,以及 Word 如何确定下一个ActiveDocument如果您以编程方式关闭当前的 ActiveDocument)

So, does calling .Open on a document explicitly set the Document to be the ActiveDocument ?那么,在文档上调用.Open是否明确地将 Document 设置为ActiveDocument Also, does calling .Activate on the already active document cause an error?另外,在已经激活的文档上调用.Activate会导致错误吗?

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. VBA 通常似乎以这种方式工作。

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).小心使用 ActiveDocument 很重要,因为代码或其他地方的哪些操作会使文档“激活”并不总是不言而喻的(我没有证据,但即使是自动保存也可能会这样做)。 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.如果有任何疑问,您最好通过 Documents 集合引用文档,尽管如果文档不再打开,这也会导致错误,并且您可能不得不求助于遍历集合以确保文档是,其实开。 I run into this a lot with excel VBA, and Word VBA seems to function identically in that regard.我在 excel VBA 遇到了很多这样的问题,而 VBA 在这方面似乎与 ZC1C425268E68385D14ZA97 相同。

Also, VBA is flaky about releasing application objects.此外,VBA 在释放应用程序对象方面存在问题。 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.如果你不小心,你最终会得到多个 WINWORD 进程,可以在任务管理器中查看,无论你是在代码中关闭还是退出它们。 The code I've found to work around this amounts to simulating the process of selecting END PROCESS in task manager.我发现解决此问题的代码相当于模拟在任务管理器中选择 END PROCESS 的过程。 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 '.如果您想在关闭文档后重新打开它......Word/Windows 不会“释放”文件名,您会收到“文件忙”消息或有关“创建临时副本”的消息。 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.为了解决这个问题,我不得不开发一个精心设计的系统来创建/保存和整理我在 Word 应用程序中打开/操作的任何其他文档的多个版本,因为 Office Open / Close / Save方法中的这个设计缺陷。

  2. Use the ReadOnlyRecommended property set to False with the .Open method使用.Open方法将ReadOnlyRecommended属性设置为False

  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.如果您在尝试操作之前不能确保doc object 仍然存在,则参考文档 object(上面命名为文档)可能会导致严重错误。 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.永远记住,Word 是一个“开放”的应用程序平台......用户可能会在最后几毫秒左右做一些你没想到的事情。 This advice holds for any other object or property you may wish to manipulate in Word.此建议适用于您可能希望在 Word 中操作的任何其他 object 或属性。

  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如果您操作 Documents 集合(或任何其他集合)而不确保文档或其他 object 在集合中删除或移动之前仍然存在且有效,您可以
    get ' stack overflow ' errors.得到“堆栈溢出”错误。 Particularly if you try and close/delete objects in a collection starting at .item(1) .特别是如果您尝试关闭/删除从.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.您必须从最后一个集合中删除项目,并记住,每当您.add/.remove/.close 项目时,集合 idicies 和指针都会更改。

You have an error here:你在这里有一个错误:

Document(origDoc).Activate

Should be Document s .应该是 Document

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 .如果您不确定,请使用Documents.Open(origDoc).Activate

You shouldn't be using the ActiveDocument object in the first place unless absolutely necessary because it's very unreliable.除非绝对必要,否则您不应该首先使用ActiveDocument object,因为它非常不可靠。 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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