One of my biggest issues with coding in VBA is a total lack of namespaces making it difficult to ensure things like scoping and selecting the right function when every function of the same name is in the global namcespace. I know you can prefix your function calls with the module name it is in, but it seems to me that this is also possible by replacing all your modules by predeclared classes. A namespace would look something like this:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "MyNamespace"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'@Folder("Project.Namespace")
Option Explicit
Public Function Foo() As String
Foo = "bar"
End Function
' Opionally make sure users do not use this as a class
Private Sub Class_Initialize()
If Not Me Is MyNamespace Then
Err.Raise 512, _
Source:="MyNamespace.Initialize", _
Description:="Cannot create an instance of a namespace."
End If
End Sub
Thus if you ever want to call Foo
in this namespace you have to write
MyNamespace.Foo()
While simply calling Foo()
will not work.
My question is this:
Is there any reason you wouldn't want to do this? As far as I can see the class' constructor is only called the first time you call any of its functions after you open your project, so I can't see any overhead there, but there could be something sneaky I am not aware of. Of course this is in no way an ideal way of addressing this lack of functionality, but it is not as if VBA programmers aren't already using the language in roundabout ways to provide lacking functionality.
Also, I see that this is basically the same as this question, however I'd further want to know whether there are any specific issues with having a ton of predeclared "empty" classes in your code. Say you replace 100 modules with 100 predeclared classes, will that have any significant impact on e.g. performance/stability/etc...?
It costs you an object pointer, is all. I wouldn't call it a namespace though.
Every single UserForm
module you've ever worked with has a VB_PredeclaredId
attribute set to True
. This instance is automatically created, as you noticed, and while you can explicitly destroy it, the next time it's referenced it'll be automatically (silently) re-created again... with whatever the original state is/was... pretty much like an auto-instantiated object, aka an As New
declaration.
So what you have there is more like an object hierarchy than a namespace structure - very, very similar to how you can drill down the Excel object model starting with Application
, and go do this:
Set someCell = Excel.Application.Workbooks(1).Worksheets(1).Range("A1")
Here the "namespace" is the Excel
library, Application
is the root object, and the rest of that expression is all member access - property getters, named after classes.
But the classes aren't in "namespaces"... the Worksheets
collection type (class) exists on its own, under the Excel
library: there being a Worksheets
property on the Application
class does not in any way, shape, or form, shield the class from a "name collision": if your user code has a class module named Worksheets
(and it very well can), then as per how VBA resolves identifier references, Dim foo As Worksheet
is going to be an instance of that custom class: the only valid qualifier is the library name (Excel
, or MyVBAProject
).
So, what you have there is a reasonable approach for building a relatively complex object model structure - but it won't (can't) replace or simulate a namespace. If you find yourself making "empty" classes, reconsider your design.
As for the last question, I don't see how having 100 predeclared custom objects might be any different than a project with 100 userforms: in both cases I'd wonder if there'd be a way to trim that down and generalize/reuse components, whether they be forms or classes.
What you want to avoid, is a predeclared object that holds state - because that state is effectively global now, and you have no control over what gets to change that state, where, and when: Application.Calculation
is a prime example of this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With