"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!