PDA

View Full Version : Solved: Globally-Loaded Templates



geekgirlau
02-05-2008, 12:33 AM
Hi guys,

I'd like to clarify that I understand correctly how Word works with globally-loaded code templates. Forgive me if there's a little too much detail here, but I want to make sure I'm not barking up the wrong tree!

Background:
I've inherited an application written in Word VBA that consists of 5 globally-loaded code templates. Attempting to sort out the spaghetti in the back end and create processes for testing, installation, upgrades etc.

Code Templates:
1 of these templates is a repository of functions and procedures that are called by each of the other 4 templates.

Questions:

Is it necessary to each of the other 4 templates to have a hard-coded reference to this "library" template?
Is there another way to do this?
Is it possible to call functions and procedures from the library template without having the reference?This situation causes me issues due to the hard-coded reference. For example, a site may have X:\MyApp\System and X:\MyApp TEST\System. On completing a test process, it is not possible to just copy the code templates to the production folder, as the references have to be updated first to point to the new file location.

I have attempted an "update references" procedure, but it's a little hit and miss to say the least. The issue appears to be due to the fact that the code templates have already been globally loaded. It is also unsuccessful if I have users on Word 2002.

Future Direction:
This application is going to be completely redeveloped on a non-VBA platform in future, but given that this may still be some time away, I want to make sure that the current product is made as stable, secure and reliable as I can in its current format.

My understanding is that to redevelop this as a COM addin is a fair amount of work (still lots of code here even after slashing through the spaghetti with a chainsaw :devil2: ). This would certainly resolve the security issue, but is it worth the effort given the future redevelopment plans?

Fix Reference code:

Private Sub FixReferences()
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~
' Purpose: The system templates contain a reference to the Library
' template. Unfortunately this means that it often
' hangs onto the wrong reference. This procedure:
'
' * Prompts for the location of the current system files
' * Opens all system templates
' * Removes all existing references to the Library template
' * Adds a reference to the current version of the Library
' template
'
' Restrictions: * Requires a reference to Microsoft Visual Basic for
' Application Extensibility
' * Must have "Trust access to Visual Basic project" selected in
' Macro Security
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~

Dim dlgOpen As Object
Dim ref As Reference
Dim strTemplate(0 To 3) As String
Dim strFolder As String
Dim i As Integer


strTemplate(0) = "Code1"
strTemplate(1) = "Code2"
strTemplate(2) = "Code3"
strTemplate(3) = "Code4"

If vbNo = MsgBox("Have you ticked" & vbCrLf & vbCrLf & _
" 'Trust access to Visual Basic project'" & vbCrLf & _
" (Tools | Macro | Security | Trusted Publishers)", _
vbQuestion + vbYesNo + vbDefaultButton2, "Trusted access") Then

MsgBox "You MUST tick this option before you can continue:" & vbCrLf & vbCrLf & _
vbTab & "Tools" & vbCrLf & _
vbTab & "Macro" & vbCrLf & _
vbTab & "Security" & vbCrLf & _
vbTab & "Trusted Publishers" & vbCrLf & _
vbTab & "Trust access to Visual Basic project", vbCritical, _
"Update Cancelled"

Else
FindLibrary:
MsgBox "Please navigate to the current LIBRARY system template," & vbCrLf & _
"and double-click on the file", vbInformation, "Find Library Template"

Set dlgOpen = Dialogs(wdDialogFileOpen)

With dlgOpen
If .Display = -1 Then
If LCase(.Name) <> "library.dot" Then
GoTo FindLibrary
End If

strFolder = Options.DefaultFilePath(wdCurrentFolderPath)

For i = 0 To UBound(strTemplate)
Documents.Open strFolder & "\" & strTemplate(i) & ".dot", , , False

For Each ref In ActiveDocument.VBProject.References
If LCase(ref.Name) = "library" Then
ActiveDocument.VBProject.References.Remove ref
End If

If InStr(1, ref.Name, "~") > 0 Then
ActiveDocument.VBProject.References.Remove ref
End If
Next ref

ActiveDocument.VBProject.References.AddFromFile _
strFolder & "\Library.dot"

ActiveDocument.Close True
Next i

MsgBox "Make sure you remove the " & vbCrLf & vbCrLf & _
" 'Trust access to Visual Basic project'" & vbCrLf & _
" (Tools | Macro | Security | Trusted Publishers)" & _
vbCrLf & vbCrLf & "now that the references are done.", _
vbInformation, "Trusted access"

End If
End With
End If
On Error Resume Next
ActiveDocument.Close False
End Sub

fumei
02-06-2008, 10:03 AM
Hi. I am not quite following this. You have code that is dealing with VBProject.References, but global templates are NOT VBProject References. If you have a global template loaded, it does not show as a Reference.

References are for .DLL libraries. Global templates are not DLL libraries.

Is it necessary to each of the other 4 templates to have a hard-coded reference to this "library" template?

No. IF, and only IF, the "main" template is loaded as an Addin, then procedures can call to anything in it.

Say I have the global template VBA XTools.Dot loaded. It shows as checked in Templates and Add-ins. Note that it is not open, just loaded.

It has a procedure:Sub CalledFromGlobal()
Msgbox "A message from my global."
End Sub

Then a simple: Application.Run "CalledFromGlobal"

will execute that procedure. This can be executed from any code module.

Is there another way to do this?

Not sure, as you mention References in the same breath as global templates.

Is it possible to call functions and procedures from the library template without having the reference?

Yes, as mentioned above.

You certainly know what you are doing, so I am assuming that I am not quite getting the situation.

geekgirlau
02-06-2008, 05:56 PM
You've hit the nail right on the head Gerry (although I don't know that your statement "You certainly know what you are doing" is all that accurate :tongue2: ).

Much of the code uses "Call" when attempting to call procedures and functions from the Library, which doesn't work if the reference is not there - it didn't even occur to me to try Application.Run, so thinking about it now you definitely need to take back your earlier statement regarding my ability!

I'm excited already - I knew I could count on you to come up with the answer on this one!

geekgirlau
02-07-2008, 05:12 PM
Just to report back:

There are some limitations in what Word seems to accept in terms of nested calls to another project (in this case the "library"). However it is possible to work around this. The application I have inherited also used many global variables that were declared in the library; I have issues generally with unnecessarily declaring variables as global anyway, and of course none of these now work as they reside in a different project.

So the short answer: Gerry is absolutely correct, but it is not quite as straightforward as calling a procedure in the same project, and you will need to be careful about how you nest calls to different functions from another project within a single procedure.

:whyme: I miss Excel ...

fumei
02-11-2008, 12:07 PM
I miss Excel ...

Yes....well...as Steve says.....

geekgirlau
02-21-2008, 08:48 PM
Just another heads-up for anyone else attempting something similar. If you are calling a procedure from another project using Application.Run, be careful with optional parameters. If you leave any blank in the middle, any subsequent parameters don't work correctly.

For example,

Application.Run "MyProcedure", "Text", , False

...

Public Sub MyProcedure(strTitle As String, Optional strStyle As String = "Normal", _
Optional blnContinue As Boolean = True)

will actually interpret the last parameter as the default value of True. The short answer - explicitly set all parameters even when using the default value.

Application.Run "MyProcedure", "Text", "Normal", False

lucas
02-21-2008, 09:51 PM
Did I hear my name? Oh Boy Global templates....This turned out to be one of my favorite features once I got used to it....especially after my normal.dot got corrupted once....

Word is different.

Hi Gerry and Anne.

fumei
02-22-2008, 11:11 AM
"The short answer - explicitly set all parameters even when using the default value."

Not all that bad as a general rule anyways, but thanks for pointing that out. Good one.

Hi Steve.

fumei
02-22-2008, 11:13 AM
PS....will people PLEASE think about using the underscore character as a general rule? I know I am a complainer on this, but what can I say?