vba - 为什么某些类型缺少 `Set` 是运行时错误而不是编译错误?

标签 vba

给定以下 VBA 代码,假设 Something只是一个 VBA 类模块....

Public Type Foo
    SomeThing As Something
End Type

Public Sub TestFoo()
    Dim x As Foo
    With x
        'Correct way to do it
        Set .someThing = New Something
    End With

    With x
        'This is wrong but realized only as a RTE 
        '438: Object doesn't support this property or method
        .SomeThing = New Something
    End With
End Sub

相反,如果您将类型更改为 VBA.Collection如下:
Public Type Foo
    SomeThing As VBA.Collection
End Type

Public Sub TestFoo()
    Dim x As Foo

    With x
        .SomeThing = New VBA.Collection
    End With
End Sub

现在这是一个编译错误,带有 Argument Not Optional .这显然是错误的,但为什么它只是 VBA.Collection 的编译时错误? ?

最佳答案

这在 VBA 语言规范中进行了解释。 With 中赋值的语义 block 由语句是否为 Set 驱动。声明或 Let陈述。在这种情况下,它是 Let陈述:

With x
    .SomeThing = New Something
End With

请注意,在 VBA 语法中,关键字 Let是可选的(已过时):
let-statement = ["Let"] l-expression "=" expression

Set声明,Set关键字是必需的:
set-statement = "Set" l-expression "=" expression
With 的内部 block ,l-expression基本上是 UDT 成员,但如果 x 也适用完全相同的行为是直接使用的。

在评估 Let 时表达式,语义在 section 5.4.3.8 中描述:

Static Semantics.

This statement is invalid if any of the following is true:

  • <expression> cannot be evaluated to a simple data value (section 5.6.2.2 ).


之后到 5.6.2.2 (Evaluation to a simple data value) ,以下运行时语义适用(仅适用规则):

Runtime semantics.

At runtime, the simple data value’s value and value type are determined based on the classification of the expression, as follows:

  • If the expression’s value type is a specific class:

    • If the source object has a public default Property Get or a public default function, and this default member’s parameter list is compatible with an argument list containing 0 parameters, the simple data value’s value is the result of evaluating this default member as a simple data value.

    • Otherwise, if the source object does not have a public default Property Get or a public default function, runtime error 438 (Object doesn’t support this property or method) is raised.



因此 SomeThing As Something 的运行时错误 438 .

Collection , Let静态语义仍然适用,但它失败了 静态 5.6.2.2 的语义(给出编译错误)。同样,省略了前面不适用的语义:

Static semantics. The following types of expressions can be evaluated to produce a simple data value:

  • An expression classified as a value expression may be evaluated as a simple data value based on the following rules:

    • If the declared type of the expression is a specific class:

    • If this class has a public default Property Get or function and this default member’s parameter list is compatible with an argument list containing 0 parameters, simple data value evaluation restarts as if this default member was the expression.


Collection 的默认成员是一个函数 ( .Item ),它采用单个参数 Index .在这段代码中,没有提供参数,所以参数列表是不兼容的:
With x
    .SomeThing = New VBA.Collection
End With

因此 Argument Not Optional编译错误。

关于vba - 为什么某些类型缺少 `Set` 是运行时错误而不是编译错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52089215/

相关文章:

excel - Selection.Replace ("."for "-") 应用于 "dd.mm.yyyy"返回 "mm-dd-yyyy"

vba - 对于变量 = SheetName1 到 SheetName2

vba - 是否启用安全保护功能

vba - 应用程序.根据工作簿进行计算

Excel VBA ActiveWindow.Visible 隐藏错误的工作簿

vba - 以主题作为文件名保存邮件

vb.net - 通过 VB.net 为 Excel 使用 "cells"选择连续范围

选择行或列时 Excel 日期选择器子崩溃

excel - 根据 Excel 单元格值选中/取消选中 Listobx 项目

c++ - 在 VBA 中模仿 std::map<string, std::list<string>>