Word 2007 VBA - Load macro on Document New via Addin - vba

Good morning good folks! :) So here's what I'm trying to do. I've got this design template that I want to add to all new documents that are being created in Word 2007. In additon, I've got an addin in the form of a dotm file that's loaded everytime Word starts. This addin is located in the Startup folder on each computer. This is not a COM addin btw.
Now, I've tried a few things out. First of all, I've tried the Document_New and Document_Open handlers, as well as the AutoExec and AutoOpen handlers in the addin dotm-file. Document_New did not trigger anything when I start a new document. Document_Open didn't either. But AutoExec did trigger, but I can't apply the design profile in that trigger because there is no document open at that point.
So, how do I do this? I do not want to mess with the normal.dot at all, so I'm trying to avoid that and keep all code in the addin and perhaps a few macros in each template. But that's it. I want to keep it clean. Any ideas?

Are you hooking in to events at the Application level? or just at the document level? You need a "with events" reference to the Word application in order to trap the events you're interested in.
See here: http://word.mvps.org/FAQs/MacrosVBA/AppClassEvents.htm

Related

Word VBA AutoNew macro not firing when opening Word

Using Word 2013.
I found this previous question that is similar, but there was no accepted answer, and I'm not trying to build an add-in, so I hope I don't need something complex.
I have AutoNew and AutoOpen macros in my Normal.dotm. They are working great except that neither one of them fires when I open Word from the taskbar or other icon. In that situation, Word opens with the blank "Document1," but without the initialization I want.
Suppose my macros display a message with the document's name when a document opens or is created. I know this is silly, but it seems like a workable example.
If I open a document by clicking on it in File Explorer or by using File | Open or File | New, then the appropriate macro will fire and the message will pop up.
But if I just open Word from scratch, then no macro fires, and there is no message displaying "Document1."
I tried AutoExec to cover this situation, but when AutoExec fires, there is no active window and no document loaded yet.
Ideas?
The example cited in the question not "workable" because it makes no sense to want to show the name of an automatically generated document.
In any case, only AutoExec will fire when the Word application is started - this is by design. AutoNew does not fire when Word creates a new, default document when the application starts. (You'll also notice if you immediately open another document, without doing anything to the default document, that document is closed automatically. In a manner of speaking, this default document doesn't exist until the user takes action on it.)
What can work is to explicitly create a new document during AutoExec. This will have the effect of generating a document in place of the default document. The document will have the same name as that default document. The only different would be that this document will not close automatically when another document is opened.
When the document is created then AutoNew (and Document_New) will be triggered.
Sub AutoExec()
Documents.Add
End Sub
In Word 2016 64bits AutoOpen is triggered before AutoExec.
So if you Open a file, when AutoExec runs you can open a new file only if there is no file already opened.
As a result when you open a file you don't have another blank document opened as well.
In Word 2010 and 2013 AutoExec is triggered before AutoOpen.
So the solution cannot be applied.
But you can ask Word to close the blank file in the AutoOpen macro.
Have you tried just adding code for the Document_New() and Document_Open() events in your Normal.dot file? I just tried it with mine and however I opened the test document I got the Document_Open() to fire. The Document_New() worked as well.
Screen shot of my setup for testing. The relevant msgbox includes the name of the document.

How to call a VBA-macro in another MS Word document?

in MS Excel I have been distributing a xls-file that contains a macro. From the users "random" current open workbook I have successfully been calling this macro by telling Word in which file to look for it. Like this, when the user clicks a button on the ribbon:
C:\\"'MyExcelFileWithTheMacro.xls'!MyMacroName"
Can I do the same in MS Word?
That is, to call a macro in a Word-file located in any given folder from an instance of Word that has not opened that file?
I have tried, of course, but Word keeps saying it can't find the macro.
The reason I want to do it this way is that it is makes for easy distribution and updating of the macro. Next up is signing the macro. I hope it can be done when doing things this way, but not sure.
No, it's not possible to call and run a macro in any Office application if the file that contains the macro is not loaded in the application interface.
That being said, if you place the macro in a *.dotm template and have the user put the template in the STARTUP folder used by the Word application, then Word will load the template as an "Add-in". And in that case you should be able to access the macro.
Or, if you don't want it in the Startup folder and you have code that automates the Word.Application, anyway, then that code can load the *.dotm as an "Addin", which should make the macro available (and remove it when you're done with it). Research Application.Addins.Load and Addin.Installed in the Word language reference as well as on-line for examples.

Prevent Word macro in Normal.dotm for some templates

I have a Normal.dotm file that contains an AutoNew macro.
This macro is automatically executed each time a new document is created using any other template.
Is there any way I can prevent this automatic behavior for a specific template?
I have a Word VSTO add-in running, so I can hook into Word's events, but so far I havn't found a way to prevent this.
I do know that I can prevent macro execution when using templates programmatically, for example like this:
' Disable auto-macros before opening document
wordApplication.WordBasic.DisableAutoMacros(1)
' Open document
newWordDocument = wordApplication.Documents.Open(template.FullName, ConfirmConversions:=False, [ReadOnly]:=True, AddToRecentFiles:=False, Revert:=True)
' Re-enable auto-macros
wordApplication.WordBasic.DisableAutoMacros(0)
But this solution doesn't work when the user uses a Word template from Windows explorer or the Open-dialog in Word, since in those cases I can't execute code before it's too late already.
Or can I?
I hope someone has a trick for me :-)
-
Edit: While trying different solutions, I discovered something that might help others in similar situations, though unfortunately it doesn't help me.
It seems that if a template contains a module containing an AutoNew (or AutoOpen for that matter), that local macro is executed instead of the one in Normal.dotm.
Example:
Normal.dotm contains the following macro:
Sub AutoNew()
MsgBox "Normal.dotm"
End Sub
Test.dotm contains the following macro:
Sub AutoNew()
MsgBox "Test.dotm"
End Sub
When executing Test.dotm the message "Test.dotm" is displayed, while the message "Normal.dotm" is not displayed.
If the AutoNew macro is removed from the Test.dotm template, the message "Normal.dotm" is indeed displayed.
So it is possible to easily override the auto-macros.
The local versions of AutoNew and AutoOpen can even be empty subs that do nothing. It still works.
This is not possible in my case though, since the template I use is generated by code, and cannot contain macros (because adding macros to templates programmatically requires the user to manually activate the option "Trust access to the VBA project object model", and that's something I cannot ask my customers to do for all users. It's also a security risk.)
Based on the workaround described in the "Edit" part of the question - providing a template with "empty" Auto-macros - it's possible to use the Open XML SDK to create a template and add the VBA project to it in order to provide this functionality. This approach avoids the user needing to allow access to the VBA project on his installation. The only "macro security" that could be triggered is that for not allowing macros to run. But since the client uses macros, anyway, this should not be a major obstacle.
The simplest method is to create as much of the basic template as possible in the Word UI and use this as a starting point.
Since you're unfamiliar with the Open XML SDK, the next step would be to create one (or more) templates in the Word UI using the basic template as the starting point, saving under a different file name.
You can then use Open XML SDK Productivity Tool to see the code required to generate any one of these files, as well as, using the Compare tool, the code for converting the basic template to the derived version. This should give you a decent start with the SDK and it's object model. Once you get a feel for how the Open XML SDK works, if you're familiar with Word's object model, using that provided by the SDK is relatively straight-forward as an effort was made to make it correspond as closely as possible to the "COM" object model.
The VBA project can be added later, but you can also include it in the basic template. That would be the simplest approach.
Include this "starting point" basic template as part of your solution, installing it as part of the solution.
Within the AutoNew macro you can check the AttachedTemplate property. Only if it is a template where you want to apply the cleaning you can execute the respective macros.
Sub AutoNew()
If ActiveDocument.AttachedTemplate <> "Normal.dotm" Then
Exit Sub
End If
' rest of the macro
End Sub
If you don't control the Normal.dotm you can put an empty AutoNew macro in your own templates. As Word only executes the auto macro in the closest context, the macro in the Normal.dotm file would not be executed.
If you don't control the other templates either, you can tell your users to hold down the SHIFT key while creating a document. This prevents the execution of the auto macro.
Probably it is best, however, if you ask the owner of the other system to find another solution that does not rely on polluting the Normal.dotm file.

Outlook 2007 - VBA macro in NormalEmail.dotm

I have a Word 2007 template that I use as Normal.dotm, which has corporate theme, styles, etc., plus a tiny bit of macro code that overrides the default behaviour of the bullet & number buttons on the ribbon.
I'd now like to use this same template when creating emails in Outlook 2007. I've tried just copying my Normal.dotm to NormalEmail.dotm, and to an extent this works, but although my macro is correctly invoked when I press the bullet/number buttons in the email editor, it gives an error:
Run time error 429: ActiveX component can't create object
On further investigation, it seems that anything I do within my macro that references an object in the normal Word object model (Application, Selection, etc.) causes this error. So, even if my macro consists of the following, it still fails:
MsgBox TypeName(Application)
I have an inkling that this is because I'm running in the context of Outlook, not Word, and so perhaps there is no (Word) application, or any of the objects associated with it. I know that the email editor in Outlook is Word-but-not-as-we-know-it-Jim.
Having said that, I did discover that ThisDocument does return a valid Document object; unfortunately, it corresponds to the template itself, not the email being edited.
By trial and error, I've discovered that I can get at the Document corresponding to the email by the following circuitous route (this displays the text in the email):
MsgBox ThisDocument.MailEnvelope.Item.Application.ActiveInspector.WordEditor.Content.Text
However, this code also seems to cause Outlook to crash - not at the time, but later, when you close Outlook.
At this point, I'm just about ready to admit defeat. No doubt the "correct" way to create macros in Outlook is to create them in Outlook itself, but from my limited experience, that's just horrible. (You can create macros in VBA, but you can't deploy them; or, you can create them in VSTO, but then you need an installer rather than simply deploying a template).
So. Any ideas out there that would let me do all that I hoped to do?
Override the behaviour of the bullet/number buttons on the ribbon in the email editor.
Deploy the macros in the NormalEmail.dotm file, rather than having to "install" them.
Not crash Outlook.
Have you tried adding the reference in the VBA editor to the Microsoft Outlook Object Library?
In Outlook 2007 you might also have to add VBA references to "Microsoft Word 12.0 Object Library" and maybe "Microsoft Forms 2.0 Object Library". Different versions may apply for other version years.
In addition, in the macro/code you have to set the objects to get/use the correct methods and properties.
I'm not an OO programmer and usually copy code from elsewhere and modify for my need so I can't help much more than what I said above. (And one of my macros is also giving me the same 429 error you get.)

How come my Macros are triggered by events in other word documents

I am executing code on the WindowSelectionChange event in Microsoft Word. How come when I open another document, that does not have this macro referenced in it, the code is still being called on WindowSelectionChange. I do not have the macro stored in the default template, it is stored in a template not referenced by my other word documents.
Is there a way to limit this event to the document that has the VBA code in it?
The macro events only fire unwantedly if the document that they are supposed to fire in is open at the same time. The project is stored in my own .dot file, not the default template.
Is this just the nature of binding events in word? It effects all open documents. Any ideas?
I believe the WindowSelectionChange event is called at the application level, right? So basically I think the way to fix this is to modify the code in the WindowSelectionChange so that it only executes if ActiveDocument = ThisDocument. ThisDocument is the document where your code is stored, so you can make it so the code executes only when ThisDocument is the active document in Word.
Is it possible that you made the macro in the default template instead of in the specific document?
Yes, in the macro editor, make sure your code is in the project for your document and the the one called "Normal".