HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Modularise Project and Deduplicate Code By Loading External Modules On Startup

Submitted by: @import:stackexchange-codereview··
0
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

Solution

I have two tiny things right now. The variable 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) Then


This logic can be simplified by editing the ModuleExists function to return the opposite.

ElseIf NoModuleExists(Module) Then


A 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 Function


That would just increase the intuitive logic. Alternatively you could just use

ElseIf Not ModuleExists(Module) Then


But 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 Function


Oh, 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) Then
ElseIf NoModuleExists(Module) Then
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 Function
ElseIf Not ModuleExists(Module) Then
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 Function

Context

StackExchange Code Review Q#126315, answer score: 7

Revisions (0)

No revisions yet.