PDA

View Full Version : Call vs. Raise Event for Document_New



mansky
02-03-2006, 06:46 PM
Hi all,
I have code in the Document_New event procedure of the ThisDocument class module in a template that I attach to a new blank document. If I understand the help files correctly, the code placed in a Document_New (or _Open or _Close as well) event procedure isn't automatically executed if the template is attached to a document. Otherwise it is.

So my question is: What is the recommended method of executing code in one of the Document event procedures of the ThisDocument class when the code is in an attached template?

I can get the code to execute via a Call statement as in:


Sub LoadXrefTemplate()
Dim TmpPath As String, TmpName As String

TmpPath = "Macintosh HD:Applications:Microsoft Office X:Templates:My Templates:"
TmpName = "Xref.dot"

Documents.Add Template:=TmpPath & TmpName, _
DocumentType:=wdNewBlankDocument, Visible:=True

Call LoadXref.ThisDocument.Document_New

End Sub


where the above code snippet is in Normal.dot and, and when executed, opens a new blank document based on the specified template (which is thereby attached). Note that LoadXref is the unique name for the TemplateProject that defines the template file Xref.dot.

Using the Call statement seems incorrect to me, but I can't find a RaiseEvent command, nor do I see a way of using either OrganizerCopy, or the VBProject object, to copy the Document_New procedure in the attached template to the new document I am creating. If the way to get the code in Document_New of an attached template to execute automatically, upon creating a new document based upon that template, is to have that code in the Document_New of the document I am creating, I'd like to do this copying programmatically from within VBA.


Any ideas on how to accomplish this would be greatly appreciated! http://vbaexpress.com/forum/images/smilies/think.gif


Ed

fumei
02-05-2006, 10:25 AM
Something strange there.Sub AttachTemplate()
Dim sPath As String
Dim sFile As String
sPath = "C:\Documents and Settings\Gerry\Application Data\ _
Microsoft\Templates\MyNew\"
sFile = "makeme.dot"
Documents.Add Template:=sPath & sFile
End Sub
I have a simple message in Document_New of the template. I run this from normal.dot. There is a new document cloned from the template AND Document_New fires displaying the message.

fumei
02-05-2006, 10:27 AM
Are you sure the template is in fact attached?

mansky
02-05-2006, 12:37 PM
Hi Gerry,
Something indeed odd is going on. When I place any statement, like a Debug.Print or MsgBox command that forces a printout, then I see the rest of my code in the attached template's Document_New executed (ie. 3 lines of text appear in the document I am creating from that attached template.) When I have no such Debug.Print or MsgBox printout statements in the Document_New code, none of my 3 lines of text are in the newly created document.
I'm pretty sure the template is attached to the document. I inserted the
following line in a new module of the new document I want to create from the attached template:


Debug.Print ActiveDocument.AttachedTemplate


and in the Immediate Window I see printed "Xref.dot" which is the name of the attached template (ie. the template specified in the Documents.Add statement in Normal.dot). I also see a "Reference" to my attached template in the "Project" window in VBE under my new document.

I should mention that I am using MS Office/Word 10.1.6 on the Mac (OSX 10.2.8). In the MS Office Help file, under the entry "Using Events with the Document Object" it states:

"Unlike auto macros, event procedures in the Normal template don't have a global scope. For example, event procedures in the Normal template only occur if the attached template is the Normal template.
If an auto macro exists in a document and the attached template, only the auto macro stored in the document will execute. If an event procedure for a document event exists in a document and its attached template, both event procedures will run."

I conclude from the last sentence from the help file above that if my document does NOT have the event procedure code in my Document_New, but that my attached template does have that code that the code will not fire.

Is the above quote similar to what you see on Windows machines?

What am I missing here? http://vbaexpress.com/forum/images/smilies/think.gif



Ed

fumei
02-05-2006, 10:54 PM
Hi Ed.
"Unlike auto macros, event procedures in the Normal template don't have a global scope. For example, event procedures in the Normal template only occur if the attached template is the Normal template.
If an auto macro exists in a document and the attached template, only the auto macro stored in the document will execute. If an event procedure for a document event exists in a document and its attached template, both event procedures will run."Auto macros = AutoNew, AutoOpen etc
Event macros = Document_New, Document_Open, Document_Close

Again:
If an event procedure for a document event exists in a document and its attached template, both event procedures will run."This is a bit misleading. A template has a Document_New. It is used to clone a new document...Document_New fires. The new document does NOT have a Document_New.

In fact, Document_New is rarely, if ever, used EXCEPT from a template. Why would you use it from a document???? So let's ignore it for them moment.

If a template has a Document_Open, and a document cloned from that template has a Document_Open written for it (and the file saved), this is what happens.

The TEMPLATE Document_Open fires first.
The DOCUMENT Document_Open fires second.

Now say you have a Document_Open in normal.dot, and you open that file. This is what happens.

The TEMPLATE Document_Open fires first.
The DOCUMENT Document_Open fires second.

The Document_Open in normal.dot does NOT fire. The Document_Open in the attached template takes precedent. HOWEVER, if you open a file that does not have a template attached, then the Document_Open in normal.dot DOES fire.

OK, back to Document_New. I have tested repeatedly and againSub AttachTemplate()
Dim sPath As String
Dim sFile As String
sPath = "C:\Documents and Settings\Gerry\Application Data\" _
Microsoft\Templates\MyNew\"
sFile = "test_events.dot"
Documents.Add _
Template:=sPath & sFile
End SubDOES indeed fire the Document_New procedure in the template.

So it definitely works in a Windows environment. I suppose it would not be past MS weirdness to have it different on a Mac...but sheeesh.

TonyJollans
02-06-2006, 05:10 AM
It is inconceivable (to me) that this can be anything other than user error - even on a Mac :)

What you say about attaching templates is causing confusion. Every document has an attached template. When you base a new document on a template, that template becomes attached to the new document. With one exception (the new blank document based on Normal which you get as a default when starting Word with no other document), any Document_New routine in the template will be run when a new document is created. What I imagine you're reading about in the help files is that the event doesn't fire when you explicitly attach a template to an existing document.

That the code runs when it includes a debug.print proves that the code runs, so the question must be what does the code do when it runs? It would help if you could post the code. It would also be helpful to know whether you have any addins and/or application events running.

I must say, however, that it all sounds a bit strange. One possible implication of the output appearing to force the rest to run is that a delay is somehow all that is needed but I can't think of any circumstances where that would happen.

mansky
02-06-2006, 07:46 AM
Hi
Yes, I also suspect User error http://vbaexpress.com/forum/images/smilies/sad2.gif, just not sure where the offending line is.

Here's the code in my attached template's Document_New event that I want executed automatically,


Sub Document_New()
Dim F1 As Range, F2 As Range, F3 As Range
Dim Subject_label As String, Filename_label As String
Dim UnitsMoved As Integer, UnitsMoved2 As Integer
Dim LD As Integer, LF As Integer, LVMF As Integer
Dim L1 As Integer, L2 As Integer, L3 As Integer, _
L4 As Integer, L5 As Integer
Dim LSum As Integer, LSum2 As Integer, NoHFields As Integer

' Template for Xref Notes Documents

On Error GoTo Error_Handler

' Initialize
NoHFields = LoadHashes.AutoExec.MyConstant.NoHFields(4)
Subject_label = "Subject : "
Filename_label = "Filename : "
L1 = Len(Subject_label)
L2 = Len(Filename_label)
LSum = L1 + L2

'Add 2 Paragraphs to Active Document
pinitial = ActiveDocument.Paragraphs.Count
ActiveDocument.Paragraphs.Add
ActiveDocument.Paragraphs.Add

'Assign styles to the 2 paragraphs
ActiveDocument.Paragraphs(pinitial + 1).Style = wdStyleBodyText
ActiveDocument.Paragraphs(pinitial + 2).Style = "XrefText"

'Insert XrefHash into document
Set F1 = ActiveDocument.Paragraphs(1).Range
For i = 1 To NoHFields
If (i = 1) Then 'first time thru
F1.Text = LoadHashes.AutoExec.MyHashes.XrefHash(i, 1)
Else
UnitsMoved = F1.Move(Unit:=wdSentence, Count:=1)
F1.Expand wdSentence
F1.InsertAfter (LoadHashes.AutoExec.MyHashes.XrefHash(i, 1) & vbCrLf)
End If
Next i

LF = Len(vbTab & ActiveDocument.Name & vbCrLf)

LSum2 = LSum + LF

Set F3 = ActiveDocument.Paragraphs(2).Range
F3.Start = LSum2 + 50
F3.End = LSum2 + 50

' Insert Code name into Manager field in _
BuiltinDocumentProperties collection to allowing tracking
For Each p In ActiveDocument.BuiltInDocumentProperties
On Error Resume Next
If (p.Name = "Manager") Then
p.Value = "OpenXref"
End If
Next p

Error_Handler:
If (Err.Number > 0) Then
MsgBox (Err.Number & " " & Err.Description)
End If

End Sub


Note that the style "XrefText" is a User-defined style loaded from a different template in the Startup folder. The data in the variables NoHFields and XrefHash have been loaded into UDTs that are defined in a second template, again in the Startup folder.

The purpose of this code is to place 3 lines of text into a new document being created from the template this code is a part of. The specific strings to be placed in the new document are stored in the variable "XrefHash" and the number of such hash elements is stored in the integer array NoHFields.

Here are the definitions of the UDTs I use:


Public Type ERI_constants
NoHFields(1 To 4) As Integer
End Type
Public Type ERI_hashes
CjourHash(1 To 5, 1 To 2) As Variant
VMHash(1 To 17, 1 To 2) As Variant
WebCopyHash(1 To 9, 1 To 2) As Variant
XrefHash(1 To 3, 1 To 2) As Variant
End Type
Public MyConstant As ERI_constants, MyHashes As ERI_hashes


I'm probably missing something really straightforward.

This code was all part of Normal.dot at one time. In learning VBA it's clear to me that this code needed to be moved out of Normal.dot and into it's own template, which I have done.

I suspect that the statements with ActiveDocument in them, now that all this code is part of a Document event procedure, may need a slight delay placed in front of them to allow Word time to actually create the document before the subsequent code in Document_New can be fully executed. Just guessing here http://vbaexpress.com/forum/images/smilies/think.gif


Any ideas would be greatly appreciated, I've learned a lot so far from your forums here, excellent website!



Ed

fumei
02-06-2006, 10:27 AM
I must say, this seems overly complex processing. I will look at it in more detail a bit later, but I have two immediate comments.
LF = Len(vbTab & ActiveDocument.Name & vbCrLf)

LSum2 = LSum + LF

Set F3 = ActiveDocument.Paragraphs(2).Range
F3.Start = LSum2 + 50
F3.End = LSum2 + 50
Very nice...but rather useless, don't you think? You make a Range...and never use it! Further, you do not release the Range object with an = Nothing.
Subject_label = "Subject : "
Filename_label = "Filename : "
L1 = Len(Subject_label)
L2 = Len(Filename_label)
LSum = L1 + L2
You have string variables (Subject_label and Filename_label), then set them...but it seems to be only used to get the length of the two of them! You never use the string variables for anything else.

Why not just make LSum = 21? With your code it will never be anything but 21.

Beside, why bother making the other integers L1 and L2 at all? Why not just make:LSum = Len(Subject_label) + Len(Filename_label)It is not like you are using them again, or for anything else.

fumei
02-06-2006, 10:38 AM
Hmmmm, yes, you are making things WAY too complex. here is your code: ' Insert Code name into Manager field in _
BuiltinDocumentProperties collection To allowing tracking
For Each p In ActiveDocument.BuiltInDocumentProperties
On Error Resume Next
If (p.Name = "Manager") Then
p.Value = "OpenXref"
End If
Next p

Here is mine:ActiveDocument.BuiltInDocumentProperties("Manager") = "OpenXRef"

Why are you looping through the entire collection when you can set the value directly?

TonyJollans
02-06-2006, 05:43 PM
I don't think you can reference variables in a global template like this ... NoHFields = LoadHashes.AutoExec.MyConstant.NoHFields(4)Modules in global templates (in a StartUp folder) are hidden from code in other templates.

I think there may be a couple of other errors (even when you reduce the complexity) but the above ought to fail. What I don't understand is why your error trap doesn't catch it.

TonyJollans
02-06-2006, 05:50 PM
Unless, of course, you have a reference to it in your (document) template - in which case I'll have to look again.

mansky
02-06-2006, 06:02 PM
Hi Tony,
I do indeed have a reference to the TemplateProject "LoadHashes" that contains my UDT declarations in the "LoadXref" TemplateProject.

Before I added the reference I did indeed get a compilation error. Now it works just fine.


Ed