PDA

View Full Version : Solved: How to execute AutoExec macro in Addin



mansky
01-05-2006, 10:25 AM
Hi All,
I am trying to get executed an AutoExec macro in an Addin that is loaded upon a User pressing the shortcut key associated with the Addin template.
Upon pressing the shortcut key, I see the Addin template checkbox checked in the Tools/Templates & Addins window. But no new document, based on the template, is created. I'm using the Documents.Add method w/the addin template specified.

Here's the AutoExec in Normal.dot:


Sub AutoExec()

'Define the shortcut keys used to load special templates

CustomizationContext = NormalTemplate

KeyBindings.Add wdKeyCategoryMacro, "LoadCjourTemplate", _
BuildKeyCode(wdKeyControl, wdKeyN)
KeyBindings.Add wdKeyCategoryMacro, "LoadVMTemplate", _
BuildKeyCode(wdKeyControl, wdKeyV)
KeyBindings.Add wdKeyCategoryMacro, "LoadWebCopyTemplate", _
BuildKeyCode(wdKeyControl, wdKeyW)
KeyBindings.Add wdKeyCategoryMacro, "LoadXrefTemplate", _
BuildKeyCode(wdKeyShift, wdKeyControl, wdKeyN)

End Sub


and one of the modules called via pressing a shortcut key:


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

'Macro loads addin/User template

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

AddIns(TmpPath & TmpName).Installed = True

End Sub


The snippet of code from the AutoExec module of CSH_Notes.dot that I want executed is:


Sub AutoExec()
Dim F1 As Range, F2 As Range, F3 As Range
' ... other String and Integer variables omitted for clarity
Dim TmpPath As String, TmpName As String

' ... initialization code skipped

'Add 2 Paragraphs to Active Document
TmpPath = "Macintosh HD:Applications:Microsoft Office X: _
Templates:My Templates:"
TmpName = "CSH_Notes.dot"

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

' ... more code skipped

End Sub


I've got two other global templates in the Word Startup folder, each w/an AutoExec, that run fine upon starting Word (they add other shortcut keys useful to Users).

I'm running on Mac OSX 10.2.8 w/Office X 10.1.6 and Word 10.1.6 and VBA 6.0 ( I think).

The AutoExec macro in CSH_Notes.dot worked fined as a macro in Normal.dot. I've learned from the Word MVP website that I should move the macros in Normal.dot to other templates and reduce the size of Normal.dot. I've done that by creating 6 other templates (2 global in startup and 4 loaded upon demand).

How to get the AutoExec code in the loaded-upon-demand templates has got me stumped.

Any ideas on how to proceed would be greatly appreciated!


Ed

fumei
01-05-2006, 07:33 PM
Sorry. I am having a hard time looking at the code. Could you use the underscore character to make it easier for those of us who do not have big monitors and high-rez?

Like this:
KeyBindings.Add wdKeyCategoryMacro, _
"LoadXrefTemplate", BuildKeyCode(wdKeyShift, wdKeyControl, wdKeyN)

Even making more Dim lines (less on one line) would help.

Thanks.

fumei
01-06-2006, 01:08 AM
Thanks! A bunch!

AutoExec is associated with the loading of Word itself. Which is why it is normally only in normal.dot. If you want an automatic firing of a procedure from a global use a Document_New procedure (in the ThisDocument module) in the template.

Note however, that even then it will NOT fire when you load the global. It will only fire when a new document is created.

Loading a global does NOT load the template. Loading a global causes Word to parse through the code and store pointers to the procedures. This is why it is possible to load a template (as global) then afterwards OPEN the template and change procedures. Saving the procedures automatically causes Word to parse the global and update the pointers.

So, simply move what you want executed into an Document_New in your templates.

mansky
01-06-2006, 10:58 AM
Hi,
Thanks for the info on Document_New(), I wondered what the relationship was between the "This Document" object in the template and the Auto macros.

I moved my macro to Document_New in "This Document" and deleted the AutoNew macro in Modules. When I press the shortcut key to load my template, I still get no new document opened at all. I have the Documents.Add method in the Document_New macro:

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

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


Do I also need the Documents.Open method as well ? The above worked fine before when it was a standalone macro in Normal.dot. A new blank document named "DocumentN" (where N=integer) was created.

On a side note, in the Word MVP website, they mention that one should NOT base a document on an addin. I think the type of problem I'm working on (opening a document based upon a a load-on-demand template) isn't that unusual.

Should I be doing something different ? Is AddIns("X").Installed = True, followed by Documents.Add NOT the way to go?



Ed

fumei
01-06-2006, 12:04 PM
1. Addin.Installed = True has no relation to Documents.Add.

2. Documents.Add does NOT load from the Addins.

3. Addins are NOT loaded as templates.

4. A template loaded as an Addin does NOT fire any events - including Document_New...as you have found.

Addins load any contained code, but NOT the file. So you could fire a macro from the addin, once it is loaded, but you have to do it explicitly.

When I press the shortcut key to load my template, I still get no new document opened at all.
See #4.

Could you run it by again exactly what you are trying to do?

mansky
01-06-2006, 04:03 PM
Sure. Sorry if I wasn't clear in my earlier posts. Obviously I'm still a newbie to VBA programming. I really appreciate the help. Clearly the Word Object Model requires as much study and work in learning as C or Perl does, for example.

What I want to do is have 2 templates always load when Word is opened, and 4 other templates be loaded when the User presses their shortcut key. All 6 templates contain just macros, nothing else.

The first 2 templates I placed in Word's startup folder since I want their macros, each with a shortcut key defined via a KeyBindings.Add statement, to be available to all Users. On my Mac the Word startup folder is located in: Macintosh HD:Applications:Microsoft Office X:Office:Startup:Word

The other 4 templates are in Word' s "My Templates" folder. Once they are tested and ready for production, I'll move them to the Users "My Templates" folder. In AutoExec of Normal.dot I have 4 KeyBindings.Add statements to define each shortcut key. I then have 4 other macros in Normal.dot that just contain an AddIns("X").Installed = True statement, where X is the full path and name of the template in "My Templates" that I want loaded.

Each of the 4 templates in the "My Templates" folder has a macro that should be executed once for each new document of that type requested. The new blank document created from each template has unique text already filled in on the first page of the document.

The reason for the 6 templates is that at first I had all the macros in Normal.dot. The Users began having more and more problems with their documents (characters took a long long time to appear on the screen after they were typed). These problems occurred even on single User machines where nothing else but typing in Word was being done by the User. After finding the Word MVP website, it seemed like a good idea to split the code I had up into different templates and load them according to their function. Hence the 6 templates I have now.

Clearly, I'm not getting the difference between the AddIns and Templates collection classes in Word yet.

Am I trying to do something Word can't do? Or, is it that I'm using the wrong objects to do it with?

Is this clearer now ? http://vbaexpress.com/forum/images/smilies/think.gif

Thanks!


Ed

mansky
01-06-2006, 05:29 PM
Hi Fumei,
I think I've made some progress. After reading your post carefully, and going back to re-read the MS VB Help on AddIns and Documents classes, I switched the AddIns("X").Installed statements to Documents.Add statements and specified the Template I wanted to base the new document upon, and voila! a new document did indeed open with my old code being executed (this time in a Document_New macro in "This Document".)

Interestingly enough, the template that the new document that just opened up does not have it's check box checked in the "Tools/Templates & AddIns" window as I expected. However, going into the VBA Editor does reveal that the template is indeed loaded. Is "loaded" the correct term here?


Thanks for your tips, they did indeed get me thinking. Now on to AutoText entries.

Great website BTW http://vbaexpress.com/forum/images/smilies/023.gif

Ed

fumei
01-08-2006, 07:17 AM
Documents.Add statements and specified the Template I wanted to base the new document upon, and voila! a new document did indeed open with my old code being executed (this time in a Document_New macro in "This Document".)
You are attaching the template to a new document, therefore the template Document_New fires.

Please note that this only occurs when you attach a template in the same instruction as a new document. That is:

Documents.Add Template:="whatever..."

What that does is merge the instruction. It makes a new document calling the template.

If you use the AttachTemplate method to an existing document - using the same template file - Document_New does NOT fire.

Interestingly enough, the template that the new document that just opened up does not have it's check box checked in the "Tools/Templates & AddIns" window as I expected.
Read my posts again.

Templates that are called - that is, that are used to create a new document (cloned from the template really) and are NOT loaded as templates (as addin). Therefore making a new document from a template will not have the template show up in the Templates and Addins. They are called, and a new document with the same code as the template is created.

Conversely, a template that IS added as an Addin is loaded for its code, but is NOT loaded as a template.

This is why MS recommends separating document creating templates from (if you can forgive the pun) code bearing templates.

There is an unfortunate sloppiness of terms.

mansky
01-08-2006, 09:50 AM
Hi Gerry,
Thanks for your post. It's helping to clarify the differences between Templates and AddIns collection classes. I can see now where my previous posts were unclear, and getting the two classes and their functions mixed up.

So to see if I understand things, a query:



If you use the AttachTemplate method to an existing document - using the same template file - Document_New does NOT fire.


In this case, code in a Document_Open() macro would be executed automatically. Is this correct ?


To sum up then, is my use of a Documents.Add statement in Normal.dot, together w/code in Document_New() of "This Document", the usual way one creates a new document based upon a template via pressing a shortcut key ? Or is there another way that is recommended?

I want to make sure that the documents I have Users create from these templates don't end up getting corrupted later, so I want to (hopefully) get it right the first time.


Ed

fumei
01-08-2006, 02:31 PM
If you are attaching a template to an existing document (NOT a new one)...no Document_Open does not fire.

Think about it. Is the document being opened? No.

If you create a new document using a template, does Document_Open fire? No. The document is not being opened.

But Document_New does fire.

OK. It appears you are going distribute the same Normal.dot to your users. It appears you want (in Normal.dot) a method for creating documents from templates.

You certainly can use KeyBindings, but it is not needed really. You could simply have a bunch of macros in that distributed Normal.dot that create new documents (from your templates) and have shortcut keystrokes for them.

Sub MakeFinanceDoc()
' using shortcut Ctrl-6
Documents.Add Template:=path & template name
End Sub

Sub MakeReportDoc()
' using shortcut Ctrl-5
Documents.Add Template:=path & template name
End Sub

Sub MakeLetterDoc()
' using shortcut Ctrl-4
Documents.Add Template:=path & template name
End Sub

You could also have (in the distributed Normal.dot) a menu with the documents listed:

Finance Document
Report Document
Letter Document

and when the users selects the menu item...the document is created from the templates.

Again, if you have code you want to fire when the new document is created, put it in the Document_New event for that template.

To sum up then, is my use of a Documents.Add statement in Normal.dot, together w/code in Document_New() of "This Document", the usual way one creates a new document based upon a template via pressing a shortcut key
The code in template Document_New has NOTHING to do with the creation of a document.

The document is created by Documents.Add Template:=blahblah.

Period. Whether there is code in Document_New, or not, is completely irrelevant to the creation of a new document from the template.

I want to make sure that the documents I have Users create from these templates don't end up getting corrupted later, so I want to (hopefully) get it right the first time.
Again, this has no relevance to the creation process.

The document is created by Documents.Add Template:=blahblah.

Period. If the document gets corrupted it would be because there is something wrong with the template, NOT the creation process.

The document is created by Documents.Add Template:=blahblah.

Period.

mansky
01-08-2006, 04:10 PM
OK. Clearly Documents.Add and the code in Document_New() are independent of one another. So it appears that the new document that's created via Documents.Add is completely governed by the code in the Template that's named in the Documents.Add statement.

If any code is in Document_New() in "This Document" is really a secondary, and independent, issue. What sort of code does Microsoft assume, or recommend, go into a Document_New() ? Also, what's considered good programming practice in the VBA community regarding code in Document_New() ?

I use KeyBindings.Add statements to define the shortcut keys since I wanted a method that would be completely self-contained in code to add the shortcut keys. As I study other Objects in Word, it's clear I could define the shortcut keys a number of different ways, as you've pointed out. KeyBindings.Add is just one of many methods I could use.


Thanks for your help!

Ed

fumei
01-08-2006, 05:33 PM
Clearly Documents.Add and the code in Document_New() are independent of one another. So it appears that the new document that's created via Documents.Add is completely governed by the code in the Template that's named in the Documents.Add statement.
Yes, of course. Documents.Add is a totally separate instruction from anything in Document_New. For one thing, Documents.Add is a single instruction, Document_New is a procedure and may contain multiple instructions.

If any code is in Document_New() in "This Document" is really a secondary, and independent, issue. What sort of code does Microsoft assume, or recommend, go into a Document_New() ? Also, what's considered good programming practice in the VBA community regarding code in Document_New() ?
"Secondary"???? I would not consider it secondary. Independent, yes. They are not related. They have nothing to do with each other - unless you make something be that way.

Documents.Add makes a new document. It can be based on an explicit template by using the Template:= parameter.

Document_New is a set of instructions that fire when a document is created. As such, it is very very useful for - well, firing instructions when a document is created. This can range from displaying a UserForm that collects user input, to getting other information from other files, to simply picking up the user login name and putting it into the document. Whatever. It is simply a vehicle for actions that occur when the document is created. Totally up to the programmer.

I would like to add that the document created by Documents.Add is not really "governed" (at least it is not the word I would use). A document created by Documents.Add Template:= is a clone of the template. It is a duplicate.

mansky
01-08-2006, 06:31 PM
I would like to add that the document created by Documents.Add is not really "governed" (at least it is not the word I would use). A document created by Documents.Add Template:= is a clone of the template. It is a duplicate.

This helps clarify the issue for me immensely. I was think more along the lines of copy, but clone is different.

My point in all these questions is to make sure, as I split my macros up into different templates (in order to bring down the size of Normal.dot), that I don't make the performance of Word any worse for my Users! As Normal.dot has gotten larger, Users have had intermittent problems w/certain documents. I suspect I'm going in the right direction now w/multiple templates and Normal.dot down to 64kB --from 600+kB.


Thanks again for the help!

Ed

fumei
01-08-2006, 10:13 PM
600Kb normal.dot! Accck! No! No! No!

You are DEFINITELY doing the right thing. The object is to have as little as possible in normal.dot. Normal.dot get corrupted easily. You want to move as much code, or AutoText out of normal.dot as you can.

And template either for documents, or loaded as globals is the way to go.

Pardon me for asking though....but if you have a 600 Kb normal.dot I suspect that you are possibly dealing with some inefficiencies of coding. Are most of your macros created by using the macro recorder?

mansky
01-09-2006, 05:52 AM
No, only a small number were macros from the recorder. I most certainly have inefficent code as I am learning from this website and Word MVP and other websites. I also had (probably 50-60%) a lot of dead code (ie. testing code that I used for testing and had left in afterwards).

I am defintely keeping Normal.dot as small as possible now. Just code to define the shortcut keys I need. As I learn how to programmatically create menus, I will be able to move the KeyBindings code from Normal.dot into it's own menu.

I'm also working on making more efficient the remaining code I have. Could you recommend any good books or websites on tuning VBA and/or efficient VBA coding practices (similar to tuning books I have on milters in sendmail, or tuning Sun and Linux.) ?


Thanks!


Ed

fumei
01-10-2006, 06:33 PM
Hmmmmm. Yes, you certainly can programatically create menus. But I am wondering why are thinking about that. You can create custom menus in your templates. Just create them. Attach macros to the menu items. Then any documents cloned from the template will have those.

What are you doing - or thinking of doing - that you may need menus to be created programatically?? I am just wondering if you are making more work than needed.