problems loading template and refering to subs or functions

Hello and thanks for your attention,

I am dealing with a collection of templates that I want to all refer to a common template to get code. All templates are located on the network along side the common template.

I was hoping to put some simple code in an autonew module or Document.New in the individual templates that would automatically load the common template, make sure it is global and then allow further code to call subs and functions that are located in the common template code.

The problem I am having (and it seems rather obvious now that I am testing) is that until the code runs that loads the common template (with the functions and subs) Word will have trouble compiling the code in the individual template because it will determine the functions and subs are not yet defined. (Word hasn't had an opportunity to load the source of the functions and subs yet before it starts checking that all called subs and functions are valid. Get it?)

Any ideas? I understand VBA code fairly well but this is my first crack at doing anything like this in Word. I was thinking that this seems fairly straight forward and an issue probably encountered by many so there is probably a best practice I should follow.

I offer up 125 points because I believe it to be fairly straight forward but if it proves more difficult that I believe I will bump it up. (If I can. this is also my first question on this service so feel free to let me know what's goin' on or if you need more details.)

Who is Participating?
Joanne M. OrzechManager, Document Services CenterCommented:
Maybe you could just attach the template on open:

Sub AutoNew() ' or AutoOpen
    With ActiveDocument
        .UpdateStylesOnOpen = False
        .AttachedTemplate = _
            "C:\Program Files\Microsoft Office\Templates\"
    End With
End Sub
aaronrelyeaAuthor Commented:
Here is a bit more information.

Lets say I have code located in the AutoNew module that looks something like this:

1. Code to load the common template (that contain subs and functions that will be used by step 2)
2. Code that calls a sub and/or function that is located in the common template (loaded in step 1) like MyStringParser or something.

The issue as I see it is that when Word goes to run through the code and compile it, before it actually runs it, it checks and sees that step 2 is calling procedures that are not yet in scope because step 1 hasn't actully run yet. I get the error message 'Compile Error: Sub or Function not defined." refering to one of the calls being made in step two.

If the process was able to simply go through the steps without having to do this first check it would run step 1 first, loading the code to be used in step 2, and then run step 2. All fine. But it doen't do this and so I am stuck. Make sense?

Thanks again
Joanne M. OrzechManager, Document Services CenterCommented:
Honestly no... it doesn't make sense.  But that's probably not your fault.  It's probably my thick head :)

Did you try what I suggested?
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Joanne M. OrzechManager, Document Services CenterCommented:
If all your code is in your common template  - then why do you have to run it on an autonew?  Just attach the template and run the macro.??? Maybe I'm not understanding.  Sorry...

I would go with Jo's advice.

I don't think that you call call the code that is in one Template from another, so the code is never in scope.

If you feel that you must, then you can copy the code from the donor template into your (say) Normal Template. You cannot call the imported code directly from the importing procedure. You will get the error that you report. However you can call a sub which itself calls the newly imported procedure.

You need to set a reference to Microsoft Visual Basic for Applications Extensibility
This code in the Normal Template

Sub TestCodeImport()
Dim uf As UserForm
Dim pjTempl As VBProject
Dim pjTempl1 As VBProject
Dim vbCompsTempl1 As VBComponents
Dim vbCompTempl1 As VBComponent
Dim vbCompsTempl As VBComponents
Dim vbCompTempl As VBComponent
Dim strCode As String
Dim Doc As Document
Dim i As Integer
'Open the template as a document so that you can access the code"
Set Doc = Documents.Open("C:\MyTemplates\")
Set pjTempl1 = VBE.VBProjects.Item("Normal")
Set pjTempl = VBE.VBProjects.Item("TestProject")
Set vbCompsTempl1 = pjTempl1.VBComponents
Set vbCompsTempl = pjTempl.VBComponents

Set vbCompTempl1 = vbCompsTempl1.Add(vbext_ct_StdModule)
Set vbCompTempl = vbCompsTempl.Item("Module1")
i = vbCompTempl.CodeModule.CountOfLines
strCode = vbCompTempl.CodeModule.Lines(1, i)
vbCompTempl1.CodeModule.AddFromString strCode
Call CallTest
End Sub

Sub CallTest()
Call Reporter
End Sub

In your donor template, simply:

Public Sub Reporter()
MsgBox "This code has just been imported"
End Sub

Joanne M. OrzechManager, Document Services CenterCommented:
Anne TroyEast Coast ManagerCommented:
If you place code in a template the user's Startup folder, you should be able to call that code from anywhere, no?
Jo, thanks for the correction. Application.Run is a lot less messy than my get-round.
Joanne M. OrzechManager, Document Services CenterCommented:
No problem Graham.... actually, I was a bit hesitant to post it because you're so dang good and I didn't believe you could be wrong!  But we are here to learn and I use this line of code a lot to run a third-party access database to merge with VBA automated Word forms.  I intercept the third-party macro and run my macro first, then the third party macro runs.  It's actually pretty cool.  It's a database called Pattsy - for Patents and Trademarks.

You are so gracious :)

aaronrelyeaAuthor Commented:
Sorry for the delay in getting back to you all. This project is at my work and I am currently at home for the weekend so I will give you suggestions a try on monday and respond then. However, here is a little more information if you are interested.

I inherited this project recently from someone who has long since left the company. I was asked to clean up and standardize roughly 300 templates that use various procedures that were developed over the last 9 years. Many of them were done in WordBasic or use methods that mimic WordBasic like:

WordBasic.Call "MyStringTrim"

Where 'MyStringTrim' is a custom function that is stored in another 'common' template. This was done so that many templates used by many different users could all access the same functions stored in this 'common' template and if those functions needed to be modified they would only need to be modified in one location, the 'common' template.

Because these templates have been worked on since 1995 they have brought with them some bad practices such as the one listed above. Curently  all of the templates that need to use functions or proceduers that are stored in this 'common' template go through the following procedure from an AutoNew module:

A)load the 'common' template
B)make sure this 'common' template has loaded globally
C)proceede to make any calls to functions or subs that are located in the NOW LOADED 'common' template by using the 'WordBasic.Call' property.

They were able to get away with this because, I believe, when Word first tries to compile the code before running it, it only sees the WordBasic.Call. It understands that WordBasic.Call is valid (in scope so to speak) but never attempts to deterimine what is being passed to it, such as in this case, the string "MyStringTrim". It simply doesn't care as it only sees it as a string being passed to the WordBasic property and not as a function that the WordBasic property will call.

Now, however, I want to eliminate the Wordbasic references and simply call the functions and subs using VBA, wherein, I run into the problem I am describing. I was hoping to go about this in much the same way as has already been done the steps A),B), and C) above so that others in the office that are familiar with how things had been done in the past would not be too confused. I will be leaving the company in a few months and don't want them to be confused over what I have done after I am gone.

The IS dept does not want to modify on all the worstations so I was hoping to simply have the AutoNew module in any current or newly created template that needs to use functions or subs that are in the 'common' template simply load the common template and proceede to use the 'common' code. This way after I am gone if someone with a limited amount of experience that needs to make a new template could easilly copy the code (that I will have created to load the 'common' template) into an AutoNew module in the template they are developing and simpy make calls or use functions stored in the 'common' template.

I am sorry if this post is overly long but I just wanted to give as much informatios as I could because I fear I am not describing the issue well. My guess is that either I am missing something very easy, I am going about his in entirely the wrong way or I am asking the impossible. Regardless, thank you all for your advice and I will dig into your suggestions on Monday.

Thank you,
aaronrelyeaAuthor Commented:
I have awarded the points above. My situation was never directly addressed but I have decided to go about the problem in an entirely different way. It is most likely I was attempting to do something not allowed. If either of the other posters would like some points please let me know how to do so an I will be happy to do so.

Thanks fo your suggestions,
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.