Word VBA 事件仅针对基于模板的文档触发一次

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5268676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 12:49:09  来源:igfitidea点击:

Word VBA events only fire once for documents based on a template

vbams-wordword-vba

提问by George

I have a macro enabled template with an event listener that listens for content control exit events. The idea is that when the "title" or "date" content controls on the title page of the document are edited, we automatically update the "title" and "date" content controls in the header so that the author doesn't have to enter the same content twice.

我有一个启用宏的模板,带有一个事件侦听器,用于侦听内容控件退出事件。这个想法是,当编辑文档标题页上的“标题”或“日期”内容控件时,我们会自动更新标题中的“标题”和“日期”内容控件,这样作者就不必两次输入相同的内容。

My problem is that, when I open a new document based on my template (right click template => new, or just double click it), these events only fire for the very first instance of a content control being exited. I click inside the CC, click outside the CC, get a MsgBox indicating that my event has fired. I then try that a second time: click inside the CC, click outside the CC and do notget a MsgBox.

我的问题是,当我基于我的模板打开一个新文档时(右键单击模板 => 新建,或者只是双击它),这些事件只会在退出内容控件的第一个实例时触发。我在 CC 内部单击,在 CC 外部单击,得到一个 MsgBox,指示我的事件已触发。然后我再次尝试:在 CC 内部单击,在 CC 外部单击并且没有得到 MsgBox。

Code from my event handler class:

来自我的事件处理程序类的代码:

Public WithEvents doc As Word.Document

Private Sub doc_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
    MsgBox ContentControl.Range.Text    
End Sub

I've checked and found that my event handler object is still defined (not "Nothing") in my NewMacros, it's just that it isn't getting ContentControlOnExitevents, or is ignoring them.

我检查并发现我的 NewMacros 中仍然定义了我的事件处理程序对象(不是“Nothing”),只是它没有获取ContentControlOnExit事件,或者忽略了它们。

If I change the above code such that I'm not actually doing anything with the content control inside the event body, the problem is fixed - my theory is that touching any sort of content control while inside the ContentControlOnExitevent is triggering recursive ContentControlOnExitevents and somehow causing a problem. Obviously a ContentControlOnExitevent is pretty useless if I'm not allowed to do anything with content controls while inside it.

如果我更改了上面的代码,这样我实际上并没有对事件主体内的内容控件做任何事情,那么问题就解决了 - 我的理论是,在ContentControlOnExit事件内部触摸任何类型的内容控件都会触发递归ContentControlOnExit事件并以某种方式导致一个问题。显然,ContentControlOnExit如果不允许我在其中对内容控件进行任何操作,则事件将毫无用处。

i.e. receiving a ContentControlOnExitevent doesn't "break" future ContentControlOnExitevents if I change my code to:

即接收ContentControlOnExit事件不会“破”将来ContentControlOnExit如果我改变我的代码事件:

Public WithEvents doc As Word.Document

Private Sub doc_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
    MsgBox "Content Control exit event"
End Sub

I've tried using an eventsEnabledboolean to try and guard against doc_ContentControlOnExitbeing called recursively in case that's the problem, but it didn't help. The code I used for that was like:

我试过使用eventsEnabled布尔值来尝试防止doc_ContentControlOnExit被递归调用,以防出现问题,但它没有帮助。我使用的代码是这样的:

Sub Class_Initialize()
    pEventsEnabled = True
End Sub

...

' in the doc_ContentControlOnExit sub:
If pEventsEnabled Then
    ' obvious race condition...
    pEventsEnabled = False
    ' Fiddle around with some content controls
    pEventsEnabled = True
End If

Excel has an Application.EnableEventsproperty, but this doesn't seem to be present in Word.

Excel 有一个Application.EnableEvents属性,但 Word 中似乎没有这个属性。

The interesting thing is that this all works fine when editing the template itself, just not for documents based on that template. When editing the template, I get a ContentControlOnExitevent every time I exit a content control, and all of my code works fine.

有趣的是,这在编辑模板本身时一切正常,只是不适用于基于该模板的文档。编辑模板时,ContentControlOnExit每次退出内容控件时都会收到一个事件,并且我的所有代码都可以正常工作。

If it helps, I'm using Word 2010 (Office Professional Plus) on Windows 7 Professional 64 bit. I've also confirmed that the same problem occurs under Word 2007.

如果有帮助,我将在 Windows 7 Professional 64 位上使用 Word 2010 (Office Professional Plus)。我还确认在 Word 2007 下也会出现同样的问题。

edit:

编辑

I just tried setting the event handler object to call "ReincarnateEventHandler" in NewMacros, which in turn set the original event handler object to Nothing and then instantiated a new event handler. This resulted in an infinite loop of event handlers handling the first event and then setting up a new event handler which then handled the same (original) event. Using Application.OnTime to delay the reincarnation by 1 sec fixed the infinite loop, but didn't fix the original problem — i.e. dropping my first event handler and then instantiating a new event handler doesn't let me catch subsequent events after the first event.

我只是尝试将事件处理程序对象设置为在 NewMacros 中调用“ReincarnateEventHandler”,然后将原始事件处理程序对象设置为 Nothing,然后实例化一个新的事件处理程序。这导致处理第一个事件的事件处理程序的无限循环,然后设置一个新的事件处理程序,然后处理相同的(原始)事件。使用 Application.OnTime 将轮回延迟 1 秒修复了无限循环,但没有解决原始问题 - 即删除我的第一个事件处理程序然后实例化一个新的事件处理程序不会让我在第一个事件之后捕获后续事件.

回答by Todd Main

It's a quick fix. Change ThisDocumentto ActiveDocumentin your SetUproutine. As it is, ThisDocumentrefers to the template itself. ActiveDocumentis for the one created from AutoNew. So it should read Set eventHandler.doc = ActiveDocument.

这是一个快速修复。更改ThisDocumentActiveDocument您的SetUp日常工作。照原样,ThisDocument指的是模板本身。ActiveDocument用于从AutoNew. 所以应该读Set eventHandler.doc = ActiveDocument

It won't interfere with other documents not created with "so_template.dotm" as the ones created from that template will have an .AttachedTemplateof "so_template.dotm" and the AutoNew, if present, will control them.

它不会干扰不是使用“so_template.dotm”创建的其他文档,因为从该模板创建的文档将具有.AttachedTemplate“so_template.dotm”,并且AutoNew,如果存在,将控制它们。