patternMinor
Modularise Project and Deduplicate Code By Loading External Modules On Startup
Viewed 0 times
modulesdeduplicatecodemodulariseprojectloadingandexternalstartup
Problem
Starting point
I kind-of inherited a VBA project at work that consists of a bunch of Word document templates that provide users with the tools they need to create documents according to company guidelines and to help them give all documents the same appearance. We use different templates for the documents that we create, and each of these uses a different subset of tools from the collection. I was faced with the problem of having to maintain multiple copies of the same code in as many different templates.
Current Solution
The solution I came up with was to group associated code fragments into separate modules where each serves a well-defined purpose, to export these modules to external files and to build a preloading process that is triggered from AutoNew() and AutoOpen(). One advantage of this is that I can change the code in these modules without having to wait for write access to the templates that need them.
Failed Ideas
What I tried but failed at is to move the code to another template and to link that to the document template via the VBE in an attempt at faking some kind of inheritance. This approach consistently led to crashes of the macro system as well as (occasionally) Word itself. What's more, the error codes that Word decided to spew at me were entirely unhelpful, which is the main reason why I threw all of this in the bin - I didn't feel equipped to even start debugging it.
What's probably not going to work
What I would like to avoid, though, is to write a Word AddIn or using VSTO because we do not have any meaningful way of deploying new versions of the code to the users' workstations, and I'd hate the prospect of having to tamper with their machines every time I fix something. For my personal convenience, I'd pretty much prefer if everything could just sit in our group's template directory on our central network share.
Well, here's the monstrosity I created and that I'd like your opinion on:
```
' Constants are public because they are defined in
I kind-of inherited a VBA project at work that consists of a bunch of Word document templates that provide users with the tools they need to create documents according to company guidelines and to help them give all documents the same appearance. We use different templates for the documents that we create, and each of these uses a different subset of tools from the collection. I was faced with the problem of having to maintain multiple copies of the same code in as many different templates.
Current Solution
The solution I came up with was to group associated code fragments into separate modules where each serves a well-defined purpose, to export these modules to external files and to build a preloading process that is triggered from AutoNew() and AutoOpen(). One advantage of this is that I can change the code in these modules without having to wait for write access to the templates that need them.
Failed Ideas
What I tried but failed at is to move the code to another template and to link that to the document template via the VBE in an attempt at faking some kind of inheritance. This approach consistently led to crashes of the macro system as well as (occasionally) Word itself. What's more, the error codes that Word decided to spew at me were entirely unhelpful, which is the main reason why I threw all of this in the bin - I didn't feel equipped to even start debugging it.
What's probably not going to work
What I would like to avoid, though, is to write a Word AddIn or using VSTO because we do not have any meaningful way of deploying new versions of the code to the users' workstations, and I'd hate the prospect of having to tamper with their machines every time I fix something. For my personal convenience, I'd pretty much prefer if everything could just sit in our group's template directory on our central network share.
Well, here's the monstrosity I created and that I'd like your opinion on:
```
' Constants are public because they are defined in
Solution
I have two tiny things right now. The variable
This logic can be simplified by editing the
A simple adjustment here
That would just increase the intuitive logic. Alternatively you could just use
But that is also using a
Speaking of checking for the module, you could simplify all that nesting by using the module objects as the loop.
Oh, one more thing on that integer - integers are obsolete. According to msdn VBA silently converts all integers to
count is a system reserved name for something else, so I would avoid naming the variable that way. countComponents might be good.ElseIf (ModuleExists(Module) = False) ThenThis logic can be simplified by editing the
ModuleExists function to return the opposite.ElseIf NoModuleExists(Module) ThenA simple adjustment here
Private Function NoModuleExists(ByVal WantedModule As String) As Boolean
Dim countModules As Integer
NoModuleExists = True
WantedModule = Split(WantedModule, ".")(0)
With ThisDocument.VBProject.VBComponents
For countModules = 1 To .count
If (.Item(count).Name = WantedModule) Then
ModuleExists = False
Exit For
End If
Next countModules
End With
End FunctionThat would just increase the intuitive logic. Alternatively you could just use
ElseIf Not ModuleExists(Module) ThenBut that is also using a
False basis when a True is always more intuitive with if.Speaking of checking for the module, you could simplify all that nesting by using the module objects as the loop.
Private Function NoModuleExists(ByVal WantedModule As String) As Boolean
Dim targetModule As Object
NoModuleExists = True
For Each targetModule In Application.VBE.ActiveVBProject.VBComponents
If targetModule.Name = WantedModule Then
NoModuleExists = False
Exit Function
End If
Next
End FunctionOh, one more thing on that integer - integers are obsolete. According to msdn VBA silently converts all integers to
long.Code Snippets
ElseIf (ModuleExists(Module) = False) ThenElseIf NoModuleExists(Module) ThenPrivate Function NoModuleExists(ByVal WantedModule As String) As Boolean
Dim countModules As Integer
NoModuleExists = True
WantedModule = Split(WantedModule, ".")(0)
With ThisDocument.VBProject.VBComponents
For countModules = 1 To .count
If (.Item(count).Name = WantedModule) Then
ModuleExists = False
Exit For
End If
Next countModules
End With
End FunctionElseIf Not ModuleExists(Module) ThenPrivate Function NoModuleExists(ByVal WantedModule As String) As Boolean
Dim targetModule As Object
NoModuleExists = True
For Each targetModule In Application.VBE.ActiveVBProject.VBComponents
If targetModule.Name = WantedModule Then
NoModuleExists = False
Exit Function
End If
Next
End FunctionContext
StackExchange Code Review Q#126315, answer score: 7
Revisions (0)
No revisions yet.