为什么在使用For Each Next循环之前没有必要设置对象变量?

Gee*_*aky 4 excel vba excel-vba

我正在研究这个简单的宏,但我不明白为什么ws在使用For Each ... Next循环之前没有必要设置用对象引用命名的对象变量.我的逻辑是:

Dim ws As worksheet只需创建内存空间来保存worksheet对象引用.所以到目前为止我担心的是,它是一个空的对象变量.它还没有对象引用.仅指定了其"数据类型".

所以当我们ws在行中引用时For each ws In ActiveWorkbook.Worksheets,是不是ws变量在技术上是空的???? 我们不应该有一些行,ws = ActiveSheet以便变量实际上包含对工作表的对象引用?如此迷茫.

Sub FormatFormulas()
    Dim ws As worksheet
    On Error Resume Next
    For Each ws In ActiveWorkbook.Worksheets
        With ws.Cells.SpecialCells(xlCellTypeFormulas)
            .NumberFormat = ”#,##0”
            .Interior.ColorIndex = 36
            .Font.Bold = True
        End With
    Next ws
End Sub
Run Code Online (Sandbox Code Playgroud)

Com*_*ern 6

For Each循环中的运行时行为在VBA语言规范的5.4.2.4节中详细说明.

对于数组:

  • 如果声明的数组类型是Object,则<bound-variable-expression>是Set -assigned到数组中的第一个元素.否则,<bound-variable-expression>被Let-assigned到数组中的第一个元素.
  • 设置<bound-variable-expression>后,执行<statement-block>.如果存在<nested-for-statement>,则执行该命令.
  • 一旦<statement-block>和<nested-for-statement>已经完成执行,<bound-variable-expression>将被分配给数组中的下一个元素(如果是,则为Set-assigned)一个Object数组).当且仅当数组中没有更多元素时,<for-each-statement>的执行才会立即完成.否则,再次执行<statement-block>,然后执行<nested-forstatement>,并重复此步骤.

对于其他可枚举类型(在您的情况下Workbook.Worksheets),这是运行时行为:

  • <collection>的数据值必须是对支持实现定义的枚举接口的外部对象的对象引用.<bound-variable-expression>是以实现定义的方式为Let集合或Set-assigned分配给<collection>中的第一个元素.
  • 设置<bound-variable-expression>后,执行<statement-block>.如果存在<nested-for-statement>,则执行该命令.
  • 一旦<statement-block>和<nested-for-statement>完成执行,<bound-variable-expression>就会以实现定义的方式设置为<collection>中的下一个元素.如果<collection>中没有更多元素,则<for-each-statement>的执行立即完成.否则,再次执行<statement-block>,然后执行<nested-for-statement>(如果存在),并重复此步骤.

在您的情况下,这基本上归结为编译器生成的隐式调用,在第一次和每次迭代进入循环时执行以下赋值.一旦它被编译就会有类似的东西(实际上它比检查更复杂Nothing):

Set ws = ActiveWorkbook.Worksheets.[_NewEnum]
Do While ws Is Not Nothing
    With ws.Cells.SpecialCells(xlCellTypeFormulas)
        .NumberFormat = "#,##0"
        .Interior.ColorIndex = 36
        .Font.Bold = True
    End With
    Set ws = ActiveWorkbook.Worksheets.[_NewEnum]
Loop
Run Code Online (Sandbox Code Playgroud)

请注意,这就是为什么在迭代它时不应该更改集合的内容的原因 - 通过调用检索下一个元素[_NewEnum].这意味着底层集合返回的项目一次"生成"一个,因此更改循环内集合的内容将影响返回哪些项目或可能导致错误([_NewEnum]特定于实现的行为) .