How to control macros

K

Keith

Hi,
I have a Word 2007 template with macros (dotm) that gathers information to
format and populate a standardized title page. The macro works fine in the
template but once the template is used, it creates document1 which is saved
as a Word 97-2003 document. Once the new (doc) file is opened, the macros
will not execute. I need them in the child documents to adjust the data.

What am I doing wrong?
Thanks
Keith
 
D

Doug Robbins - Word MVP

I am not sure why you would want the macro to run again when a document
created from the template is opened.

But, I assume that the name of your macro is AutoNew(). You would need
another macro named AutoOpen() if you want it to run when a document created
from the template is opened. The template however that contains that macro
will need to be available on the machine on which the document is being
opened.

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
P

Pesach Shelnitz

Hi Keith,

As it seems to me you know, you need to attach the template containing your
macros to the new document that your document-creating macro creates in order
for your other macros to work in the new document. If the name of your
template is MyTemplate.dotm and if this template is stored in the same folder
as Normal.dotm, the code for creating the new document should be as follows.

Dim doc As Document
Set doc = Documents.Add(Template:=Environ$("AppData") _
& "\Microsoft\Templates\MyTemplate.dotm")

To save the new document as a Word 2007, use the following line of code, in
which the variable name must be set to the name of the new file, including
its path and the extension .docx.

doc.SaveAs FileName:=name, FileFormat:=wdFormatDocumentDefault

Note that the enum value wdFormatDocumentDefault was added in Word 2007.

I want to take this opportunity to thank Jay Freedman and Tony Jollans for
teaching me the best ways to specify a template in calls to the Documents.Add
method. We're all learning new things every day.
 
G

Gordon Bentley-Mix

Keith,

Rather than running the macro again whenever the document is opened, perhaps
what you're looking for is something along the lines of a "Rerun" macro. I
do this all the time with my templates. (Note that all of my templates are
Word 2003, so I use a button on a custom toolbar to call the rerun macro,
but I'm sure you can work out a way to do this in 2007 as well.) Here's how
my macros are configured.

I have an AutoNew macro that calls a routine called "RunTemplate". This
routine basically does what a 'normal' AutoNew macro would do - most notably
loads and shows a UserForm. I also have an AutoOpen macro that only executes
if the file being opened is a document. This macro just creates the custom
"Rerun" toolbar, which has one button on it linked to a routine called
"RerunTemplate". This routine again just calls the "RunTemplate" routine
that's called in the AutoNew macro. (There are good reasons for this
separation, but I won't go into them here.)

I don't know how your current AutoNew macro works, but if you are like most
people, you're probably relying on the "Magic Forms" functionality of Word
VBA in your code. (Google "word vba magic forms" for more info or ask Doug
Robbins if he has a link to Malcolm Smith's rant on the topic.) I also
expect that most of your code is in the UserForm module rather than being
separated into a module for code that does stuff with the document and
*nothing* in the UserForm module that isn't directly related to the UserForm
itself. There's really no problem in doing either of these, but it does mean
that any code I use won't be especially useful to you - so I won't bother
posting any. However, if you want to post your code, I'd be happy to give
some pointers on how to make it work with the above process.

There's one more tip I'd like to share with you. To make my "Rerun" macro
work as easily as possible, I repopulate the UserForm with the values that
were entered previously. I do this by saving the values in document
variables and setting a flag to indicate whether the document is a new
document just created from the template or an existing document that's being
rerun. This flag is evaluated in the Initialize event of the UserForm; if
it's a new document the UserForm is initialised for "fresh" input, and if
it's a rerun, it's initialised using the document variables. That way the
user doesn't have to re-enter all the values if they just want to change
one.

Again, my code probably wouldn't be very useful to you because of the way I
do things, and it's also a bit too complex to post here. However, if you're
interested I can give you a few tips.
--
Cheers!

Gordon Bentley-Mix
Word MVP

Please post all follow-ups to the newsgroup.

Read the original version of this post in the Office Discussion Groups - no
membership required!
 
R

ribbonspace.com

Gordon,

I'm interested and yes I've read Malcolm Smith...

You mean call the specific modules from the global macro template yes?.

Do go on...
 
G

Gordon Bentley-Mix on news.microsoft.com

"You mean call the specific modules from the global macro template yes?"

Umm... no, not exactly.

I really meant that if Keith was interested in how to store and retrieve
values for initalising a UserForm using document variables I'd be willing to
provide a few tips, so I hope that's what you're asking as well. However, as
I said the code is a bit much to post, so I'll just give you an overview of
how it works.

When I initially create a document from a template, I set a flag to indicate
that it's
a new document. I do this by creating a document variable (called,
imaginatively enough, "NewDoc") and setting its value to "true". Then when I
initialise the UserForm, I check the value of this document variable, and if
it's "true", I load any default values that might be required. If "NewDoc"
is "false", then I call code to pull values from document variables and use
those to initialise the UserForm.

The code for doing this looks like:

If fcnIsNewDoc = True Then LoadDefaults Else LoadDocumentVariables

where fcnIsNewDoc is a Boolean function that queries the status of the
"NewDoc" variable. (The reason it's function has to do with something that's
discussed further on.)

The exact structure of the LoadDocumentVariables rountine varies. It can be
quite complex for some templates and extremely simple for others - depends on
the UserForm. However, in all cases the process is basically the same. I have
various functions that simply extract the value from a document variable and
use them to set the appropriate property of a specific control: .Value for
TextBoxes (function returns a String), .ListIndex for ComboBoxes (function
returns a Long), .Value for CheckBoxes and OptionButtons (function returns a
Boolean), etc. The same functions are also used to set the values for things
like counters and arrays.

When I create the document, I use similar processes to write the values into
the document variables as well. The only really tricky bit is that on a
rerun, I delete any existing array-related document variables first - just a
bit of housekeeping really so there aren't a bunch of extra document
variables floating around. I also convert any numbers or Boolean values to
Strings first because document variables only store Strings. And of course
there's error handling throughout for things like making sure a document
variable exists before trying to read the value of it and storing a single
space in the document variable if there's no value entered in the UserForm.
(This is why fcnIsNewDoc is a function - because it relies on another error
handling function to make sure the variable exists before trying to read its
value.)

One knock-on from this process is that I can actually provide functionality
to (optionally) "pause" the creation of a document on cancelling the
UserForm. I do this by building the document with as much information as I
have and the user can just invoke the "rerun" functionality to pick up where
he/she left off. (I also set a status for the document at various times -
"NEW DOCUMENT" initally, "IN PROGRESS" after a pause and "COMPLETE" at the
end - and use this status to inform the user of where they are in the
document creation process by displaying the status in the caption of the
UserForm and by putting "IN PROGRESS" in red in the header of a paused
document.)

There are a couple of keys to making this work efficiently:

First, as I mentioned before, I separate the code into various modules
depending on purpose. Usually I have a "DocumentOps" module that contains all
of the code that's related to manipulating the document, and I also have a
"Tools" module that contains common procedures and functions that are used in
multiple places in the code. And the code in the UserForm is limited to
_only_ operations that are performed when the UserForm is visible; e.g.
validation and formatting of values, reconfiguration of the UserForm in
response to the selection/deselection of option buttons or checkboxes, etc.

Second, as is implied by the use of a "Tools" module, I make extensive use
of common procedures and functions (that usually accept arguments) to make it
easier to perform repetitive operations - like validating and formatting
values, inserting AutoText entries, populating Bookmarks, etc. That way I
don't have to repeat the code everytime I want to do one of those operations.

And finally, because I separate the code this way, I also declare and
instantiate specific instances of various objects like UserForms and
Documents, and then refer to these objects explicitly throughout my code.
This addresses Malcolm Smith's "Magic Forms" concern nicely, and also makes
the code a bit easier to share amongst projects.

As for a "global macro template", I don't have one - at least not for the
majority of the work I do. This is because my templates have to be as
"portable" as possible. (I need to be able to email a template to someone and
have it run without it depending on anything but Word - the client's
requirement, not mine.) I _have_ done global templates in the past, but just
not so much recently.

So does that satisfy your interest? ;-P

BTW, here's an example of one of those "common" functions from the "Tools"
module. This one is for inserting an AutoText entry into the document. I'll
leave it to you to work out how it works.

Public Sub InsertATEntry(BkmkName As String, ATEntryName As String, Optional
bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(BkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(BkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(ATEntryName).Insert myRange,
True
If bRestoreBkmk Then .Bookmarks.Add BkmkName, myRange
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry could not be found." & vbLf &
"Please contact the Service Desk for assistance.", vbCritical, "AutoText
Error"
End Sub
--
Cheers!

Gordon Bentley-Mix
Word MVP

Please post all follow-ups to the newsgroup.

Read the original version of this post in the Office Discussion Groups - no
membership required!
 
R

ribbonspace.com

Gordon thank you for that - yes I'll leave you in peace for now.

My curiosity is constant and I was interested.


"Gordon Bentley-Mix on news.microsoft.com"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top