在VBA中确定了范围?

Mat*_*don 11 com vba scoping

假设您在名为的模块中有此代码Module1:

Option Explicit

Private Type TSomething
    Foo As Integer
    Bar As Integer
End Type

Public Something As TSomething
Run Code Online (Sandbox Code Playgroud)

在等效的C#代码中,如果您创建了Something字段public,代码将不再编译,因为可访问不一致 - 字段的类型比字段本身更不易访问.这是有道理的.

但是在VBA中,您可以使用以下代码Module2:

Sub DoSomething()
    Module1.Something.Bar = 42
    Debug.Print Module1.Something.Bar
End Sub
Run Code Online (Sandbox Code Playgroud)

并且在键入时获得IntelliSense,它会编译,运行并输出42.

为什么?从COM的角度来看,它是如何工作的?它是语言规范的一部分吗?

Thu*_*ame 3

根据我的评论,VBA 公开了一个私有类型,就像它公开了一个私有枚举一样。

VBA 假设您可以在使用上下文中使用 TypeInfo,但它不允许您声明或创建这些类型或枚举的实例。

这个C++ 答案提供了部分信息:

访问控制应用于名称

名称的访问说明符与其类型无关

但将标准模块中的私有类型视为“PublicNotCreatable”类类的东西可能很有用。如果您提供公共包装器,则可以在主机模块外部访问该类型。

但是当类型位于公共类模块中时,VBA 的处理方式有所不同!

这是你的Module1扩展:

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
Run Code Online (Sandbox Code Playgroud)

Module2扩展:

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
Run Code Online (Sandbox Code Playgroud)