Say you have this code in a module called
Option Explicit Private Type TSomething Foo As Integer Bar As Integer End Type Public Something As TSomething
In equivalent C# code if you made the
public, the code would no longer compile, because of inconsistent accessibility – the type of the field being less accessible than the field itself. Which makes sense.
However in VBA you could have this code in
Sub DoSomething() Module1.Something.Bar = 42 Debug.Print Module1.Something.Bar End Sub
And you get IntelliSense while typing it, and it compiles, and it runs, and it outputs
Why? How does it even work, from a COM standpoint? Is it part of the language specs?
Practice As Follows
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!
Option Explicit Private Type TSomething Foo As Integer Bar As Integer End Type Public Type TOtherThing Foo As Integer Bar As Integer End Type Public Type TWrapperThing Something As TSomething End Type Public Something As TSomething Public Otherthing As TOtherThing Public Wrapperthing As TWrapperThing Public Function GetSomething() As TSomething GetSomething.Foo = 1 End Function Public Function GetOtherthing() As TOtherThing GetOtherthing.Foo = 1 End Function
Option Explicit Sub 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 = 42 End Sub