How to limit scope of functions in a standard module

Viewed 105

I've prepared a standard module, MyPath, which contains a few useful functions. In this case standard module is better for me than a class module.

Much more comfortable to write:

Dim ext As String
ext = MyPath.getFileExtension("test.docx")   ' returns "docx"

Instead of:

Dim Pth As MyPath
Set Pth = New MyPath

Dim ext As String
ext = Pth.getFileExtension("test.docx")

or something like

Dim ext As String
With New MyPath
    ext = .getFileExtension("test.docx")
End With

The only problem with my "pseudo-static-class" module is its scope (and IntelliSense use).

Dim ext As String
ext = getFileExtension("test.docx")   ' This works, but I don't want it to

What I would like to achieve is:

  • If one doesn't specify MyPath when calling a function, IntelliSense does not suggest the methods from the module and they cannot be used.
  • In order to use any methods from the MyPath module, one needs to type in MyPath., and after the dot IntelliSense should suggest methods from the module.

I've tried some combinations with Option Private Module, Private functions, but no one works the way I described.
I am preparing a lot of classes and similar modules and I would keep everything in order.

edit
In short, I would like to force the compiler to throw an error if I don't specify the "parent" module for the function or sub. At the same time, if I type the name of my module I would be able to use IntelliSense (no solutions with run/call, just simply type module name, dot and select the member).

enter image description here

2 Answers

Another solution, inspired by VBA's Err object, is to implement a function that returns a reference to your "static object"

Public Static Function MyPath() As PathObject
    Dim result As PathObject
    If result Is Nothing Then Set result = New PathObject
    Set MyPath = result
End Function

Where PathObject is the class that contains all your pseudo static methods.

This approach has the added bonus that the caller cannot set their MyPath reference to Nothing - in case you decide your Static module should be stateful (perhaps for some costly initialisation routine)

PS I think the Static Function syntax is cute, but you could equally just declare result with the static keyword


In fact you could possibly make it even more concise with

Public Static Function MyPath() As PathObject
    Dim result As New PathObject
    Set MyPath = result
End Function

Not tested, but should have the behaviour that MyPath is instantiated only when used for the first time, but thereafter hangs around indefinitely

The behavior you describe is actually achievable via a Predeclared Class, but will require a little prep work.

To make a predeclared class, you can write up a class with whatever functions you want. Then export it to text (.cls) and edit it, setting the Attribute VB_PredeclaredId to True. Then re-import it. My Class is called PredeclaredClass and looks like this in the .cls file:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "PredeclaredClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "Rubberduck" ,"Predeclared Class Module"

Option Explicit

Public Sub ThisIsVisible()

End Sub

After you import this class, you can now use its methods only by referencing the class module (and no new instance needed).

enter image description here

You will not see it in intellisense nor be able to use its function without the module reference. The compiler will complain, provided you are using Option Explicit

enter image description here

By the way, Rubberduck makes this pretty easy to do this without the need to export/import modules.

Related