我刚刚解决了一个问题,我将“Set”关键字放在定义行中,但我想知道的是“为什么”?
基本上,我这样做:
Dim startCell, iCell as Range
For Each iCell in Range(whatever)
If iCell.value <>"" Then
Set startCell = Cells(iCell.Row + 1, iCell.Column)
End If
Next iCell
如果省略“Set”关键字,代码仍然编译正常,但在局部变量窗口中,我看到它的类型更改为“String”而不是“Variant / Object / Range”。为什么会这样?
答案 0 :(得分:14)
这就是原因。当你这样说:
Dim startCell, iCell As Range
你认为你做到了这一点:
Dim startCell As Range, iCell As Range
但你真正做的是:
Dim startCell 'As Variant, by default
Dim iCell As Range
这是典型的VBA错误。大多数VBA程序员已经做到了,这就是为什么大多数VBA程序员依赖于每Dim
语句只声明一个变量(即每行一个)。否则很容易犯这个错误,之后很难发现它。
因此,对于Dim startCell
,您已隐式将变量声明为Variant类型(相当于Dim startCell As Variant
)。
当你说出来时:
Set startCell = Cells(iCell.Row + 1, iCell.Column)
Variant获取参考分配(Range)右侧的东西类型。但是,当你这样说时:
startCell = Cells(iCell.Row + 1, iCell.Column)
没有Set
关键字,您没有为变量startCell
分配引用,而是赋值,它现在获取右侧值的类型。那是什么类型的?好吧,Range对象的默认属性是Value
,因此您将获得Cells(iCell.Row + 1, iCell.Column).Value
的类型。如果该单元格包含字符串,那么您将获得一个字符串。
答案 1 :(得分:3)
Set
用于指定对象的引用,Let
(或简单赋值)以指定对象的值(如果有)
Dim a As Variant
Set a = ActiveSheet.Cells(1)
'TypeName(a) = Range, a now contains reference to the cell's range
a = ActiveSheet.Cells(1)
'TypeName(a) = Double or String, whatever is in the Cell, a contains the cell's value
答案 2 :(得分:1)
将对象分配给变量时,必须使用 Set 关键字。 Cells(iCell.Row + 1, iCell.Column)
正在返回范围对象,因此必须使用设置,否则您将获得所有人最喜欢的VBA错误:91: Object variable or With block variable not set
。
编辑:
Range对象也有一个默认的返回属性,即&#39; Value&#39;属性。如果您只是参考范围(&#34; A1&#34;),则需要使用范围&#39; Value&#39;作为变体的默认值。这就是为什么在提前知道数据类型时应避免使用变体的原因。