将范围分配给数组时显式和隐式使用 ActiveSheet
Explicit and implicit use of ActiveSheet when assigning a range to an array
在考虑@Crouzilles 问题时: 我意识到 ActiveWorkbook.ActiveSheet
是否明确用于定义范围很重要。例如:
Dim arr1() As Variant
Dim arr2() As Variant
arr1 = Range("A1:B2")
arr2 = ActiveWorkbook.ActiveSheet.Range("A1:B2") 'Type mismatch
我假设右手边都是 return 一个 Range
对象,这将被转换成一个变体数组;但是,第二行生成类型不匹配错误:
Run-time error '13': Type mismatch
为了确保这两个语句确实 return 我检查了一个数组 TypeName()
:
Debug.Print TypeName(Range("A1:B2")) 'Range
Debug.Print TypeName(ActiveWorkbook.ActiveSheet.Range("A1:B2")) 'Range
我还检查了 Range("A1:B1").Worksheet.Name
属性 以确保 Range("A1:B2")
确实是对 ActiveWorkbook.ActiveSheet
.references
的引用
然后我尝试将 Range().Value
分配给两个变体的数组,这些变体正确执行:
arr1 = Range("A1:B2").Value
arr2 = ActiveWorkbook.ActiveSheet.Range("A1:B2").Value 'No error
这是有道理的,因为 .Value
将 Range
对象转换为变体数组....与 arr1
和 arr2
:[=32 的类型相同=]
Debug.Print TypeName(Range("A1:B2").Value) 'Variant()
Debug.Print TypeName(ActiveWorkbook.ActiveSheet.Range("A1:B2").Value) 'Variant()
更让我困惑的是,将两个变体显式分配给 Range
引用允许分配两个数组:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Range("A1:B2")
Set rng2 = ActiveWorkbook.ActiveSheet.Range("A1:B2")
arr1 = rng1
arr2 = rng2 'No error
谁能解释为什么 Range("A1:B2")
引用的 Range
对象可以隐式转换为变体数组,而 ActiveWorkbook.ActiveSheet.Range("A1:B2")
不能?
这与绑定和默认属性的使用有关。 Activesheet
return 是一个对象,而不是 Worksheet
所以之后的所有内容都是后期绑定的,而 Range(...)
实际上是 shorthand 对 Application.Range
所以它是早绑定。如果您声明一个工作表变量并将 ActiveSheet 分配给它,代码也可以工作:
Dim ws As Worksheet
Set ws = ActiveWorkbook.ActiveSheet
arr2 = ws.Range("A1:B2") ' works
将变量声明为 Variant
而不是 Variant()
也可以。
故事的寓意:始终明确属性您的意思!
来自 VBA 语言规范:
5.6.2.3 默认成员递归限制
如果 returned 对象有更多默认成员,则对其默认 属性 Get 或默认函数 return 另一个对象的对象求值可能会导致递归求值过程。如果评估为简单数据值且每个默认成员都有一个空参数列表,则通过此默认成员链的递归可能是隐式的,或者如果指定了专门参数化每个默认成员的索引表达式,则可能是显式的。
实现可以定义这种递归默认成员评估何时有效的限制。限制可能取决于诸如递归深度、空参数列表的隐式与显式规范、成员 return 特定 类 与 returning 对象或变体等因素,是否默认成员是函数与 属性 获取,以及表达式是否出现在赋值的左侧。
该实现可能会静态地确定此类评估无效,或者可能会在运行时评估期间引发错误 9(下标超出范围)或 13(类型不匹配)
在考虑@Crouzilles 问题时:ActiveWorkbook.ActiveSheet
是否明确用于定义范围很重要。例如:
Dim arr1() As Variant
Dim arr2() As Variant
arr1 = Range("A1:B2")
arr2 = ActiveWorkbook.ActiveSheet.Range("A1:B2") 'Type mismatch
我假设右手边都是 return 一个 Range
对象,这将被转换成一个变体数组;但是,第二行生成类型不匹配错误:
Run-time error '13': Type mismatch
为了确保这两个语句确实 return 我检查了一个数组 TypeName()
:
Debug.Print TypeName(Range("A1:B2")) 'Range
Debug.Print TypeName(ActiveWorkbook.ActiveSheet.Range("A1:B2")) 'Range
我还检查了 Range("A1:B1").Worksheet.Name
属性 以确保 Range("A1:B2")
确实是对 ActiveWorkbook.ActiveSheet
.references
然后我尝试将 Range().Value
分配给两个变体的数组,这些变体正确执行:
arr1 = Range("A1:B2").Value
arr2 = ActiveWorkbook.ActiveSheet.Range("A1:B2").Value 'No error
这是有道理的,因为 .Value
将 Range
对象转换为变体数组....与 arr1
和 arr2
:[=32 的类型相同=]
Debug.Print TypeName(Range("A1:B2").Value) 'Variant()
Debug.Print TypeName(ActiveWorkbook.ActiveSheet.Range("A1:B2").Value) 'Variant()
更让我困惑的是,将两个变体显式分配给 Range
引用允许分配两个数组:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Range("A1:B2")
Set rng2 = ActiveWorkbook.ActiveSheet.Range("A1:B2")
arr1 = rng1
arr2 = rng2 'No error
谁能解释为什么 Range("A1:B2")
引用的 Range
对象可以隐式转换为变体数组,而 ActiveWorkbook.ActiveSheet.Range("A1:B2")
不能?
这与绑定和默认属性的使用有关。 Activesheet
return 是一个对象,而不是 Worksheet
所以之后的所有内容都是后期绑定的,而 Range(...)
实际上是 shorthand 对 Application.Range
所以它是早绑定。如果您声明一个工作表变量并将 ActiveSheet 分配给它,代码也可以工作:
Dim ws As Worksheet
Set ws = ActiveWorkbook.ActiveSheet
arr2 = ws.Range("A1:B2") ' works
将变量声明为 Variant
而不是 Variant()
也可以。
故事的寓意:始终明确属性您的意思!
来自 VBA 语言规范:
5.6.2.3 默认成员递归限制
如果 returned 对象有更多默认成员,则对其默认 属性 Get 或默认函数 return 另一个对象的对象求值可能会导致递归求值过程。如果评估为简单数据值且每个默认成员都有一个空参数列表,则通过此默认成员链的递归可能是隐式的,或者如果指定了专门参数化每个默认成员的索引表达式,则可能是显式的。
实现可以定义这种递归默认成员评估何时有效的限制。限制可能取决于诸如递归深度、空参数列表的隐式与显式规范、成员 return 特定 类 与 returning 对象或变体等因素,是否默认成员是函数与 属性 获取,以及表达式是否出现在赋值的左侧。 该实现可能会静态地确定此类评估无效,或者可能会在运行时评估期间引发错误 9(下标超出范围)或 13(类型不匹配)