5

我刚刚解决了一个问题,我将“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”。为什么会这样?

4

3 回答 3

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。如果该单元格包含一个字符串,那么您将得到一个字符串。

于 2012-06-18T19:28:10.433 回答
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
于 2012-06-18T18:51:43.457 回答
1

将对象分配给变量时 必须使用Set关键字。Cells(iCell.Row + 1, iCell.Column)正在返回一个Range对象,因此必须使用Set91: Object variable or With block variable not set ,否则您将得到每个人都喜欢的 VBA 错误: .

编辑:

Range 对象也有一个默认的返回属性,即“Value”属性。如果您仅引用 Range("A1") ,它将将该范围 'Value' 作为变体的默认值。这就是为什么在提前知道数据类型时应避免使用变体的原因。

于 2012-06-18T18:50:03.003 回答