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
Word VBA events only fire once for documents based on a template
提问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 ContentControlOnExit
events, 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 ContentControlOnExit
event is triggering recursive ContentControlOnExit
events and somehow causing a problem. Obviously a ContentControlOnExit
event is pretty useless if I'm not allowed to do anything with content controls while inside it.
如果我更改了上面的代码,这样我实际上并没有对事件主体内的内容控件做任何事情,那么问题就解决了 - 我的理论是,在ContentControlOnExit
事件内部触摸任何类型的内容控件都会触发递归ContentControlOnExit
事件并以某种方式导致一个问题。显然,ContentControlOnExit
如果不允许我在其中对内容控件进行任何操作,则事件将毫无用处。
i.e. receiving a ContentControlOnExit
event doesn't "break" future ContentControlOnExit
events 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 eventsEnabled
boolean to try and guard against doc_ContentControlOnExit
being 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.EnableEvents
property, 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 ContentControlOnExit
event 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 ThisDocument
to ActiveDocument
in your SetUp
routine. As it is, ThisDocument
refers to the template itself. ActiveDocument
is for the one created from AutoNew
. So it should read Set eventHandler.doc = ActiveDocument
.
这是一个快速修复。更改ThisDocument
为ActiveDocument
您的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 .AttachedTemplate
of "so_template.dotm" and the AutoNew
, if present, will control them.
它不会干扰不是使用“so_template.dotm”创建的其他文档,因为从该模板创建的文档将具有.AttachedTemplate
“so_template.dotm”,并且AutoNew
,如果存在,将控制它们。