Is scoping broken in VBA? Is scoping broken in VBA? vba vba

Is scoping broken in VBA?


As per my comment, VBA exposes a private Type, just like it exposes a Private Enum.

VBA assumes you can make use of the TypeInfo in the consuming context, but it won't allow you to declare or create instances of those types or enums.

This C++ answer is partly informative:

Access Control is applied to names

The access specifier for the name has nothing to do with it's type

But it's perhaps useful to think of a Private Type in a standard module, as something like a "PublicNotCreatable" class. If you provide a public wrapper, then the type is accessible outside the host module.

But VBA handles things differently when the Type is in a Public Class Module!

Here's your Module1 expanded:

Option ExplicitPrivate Type TSomething    Foo As Integer    Bar As IntegerEnd TypePublic Type TOtherThing    Foo As Integer    Bar As IntegerEnd TypePublic Type TWrapperThing  Something As TSomethingEnd TypePublic Something As TSomethingPublic Otherthing As TOtherThingPublic Wrapperthing As TWrapperThingPublic Function GetSomething() As TSomething  GetSomething.Foo = 1End FunctionPublic Function GetOtherthing() As TOtherThing  GetOtherthing.Foo = 1End Function

And Module2 expanded:

Option ExplicitSub DoThings()'Compile Error: User-defined type not defined  'Dim oSomething As TSomething  Dim vSomething As Variant    Dim oOtherthing As Module1.TOtherThing  Dim vOtherthing As Variant  Dim oWrapperthing As Module1.TWrapperThing    Module1.Something.Foo = 42  Module1.Otherthing.Foo = 42  Module1.Wrapperthing.Something.Foo = 42  'Compile Error: Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions  'vSomething = Module1.Something  'vOtherthing = Module1.Otherthing    oOtherthing = Module1.Otherthing  oOtherthing.Foo = 43    'Is 43 > 42?  Debug.Assert oOtherthing.Foo > Module1.Otherthing.Foo  'Compile Errors: "GetSomething" User-defined type not defined  'Module1.GetSomething.Foo = 42  'Module1.GetSomething().Foo = 42    Module1.GetOtherthing.Foo = 42  Module1.GetOtherthing().Foo = 42End Sub