在VBA中,dim和set有什么区别?

103

请原谅我,我是VBA的新手。

有时候我会使用

Dim r as Range
r = Range("A1")

有时候我使用

Set r = Range("A1")

这有什么区别?我应该在什么时候使用它?


我对此进行了两次编辑,但都被回滚了...只是为了讨论...第一次是从标题中删除“在VBA中”,因为这重复了一个我认为违反指南和多余的标记。第二次是删除[excel]标记,因为虽然给出了Excel示例,但核心问题并不特定于Excel。这是https://dev59.com/AnRC5IYBdhLWcg3wSu97的重复目标,该问题完全是关于此主题的普遍性问题。(也许应该将重复项实际上反过来...) - StayOnTarget
7个回答

88

除非涉及到对象引用,否则没有使用set的必要。在这种情况下只使用它是良好的编程习惯。对于所有其他简单数据类型,只需使用赋值运算符即可。但最好将所有变量都使用dim进行维度定义:

简单数据类型的示例包括integerlongbooleanstring。它们只是数据类型,并不具有自己的方法和属性。

Dim i as Integer
i = 5

Dim myWord as String
myWord = "Whatever I want"

一个object的示例是RangeWorksheetWorkbook。它们有自己的方法和属性。

Dim myRange as Range
Set myRange = Sheet1.Range("A1")

如果您尝试在不使用 Set 的情况下使用最后一行,VB 将会抛出一个错误。现在您已经声明了一个 object,您可以访问它的属性和方法。

myString = myRange.Value

3
请问您是参考哪个教程或书籍来理解这个问题的? - Ram
23
这个回答并没有真正解释“为什么”。 - kizzx2
1
VBA非常聪明,不像许多语言那样需要你告诉它你在做什么。然而,这会增加时间。如果你在所有不同的变量上使用了一整套不同的维度,那么时间就会累积起来。如果你告诉VBA当它看到一个变量时应该期望什么,那么它就不必计算了。此外,如果你告诉VBA一个变量是整数而不是字符串,那么它就不会占用太多RAM。虽然后者在普通小型VBA项目中可能不太有效,但这仍然是良好的编码实践。 - Rapid
在使用Set之前不声明变量,这样做可以吗? - solstice333

75

然而,我认为这并不是你真正想问的。

Sometimes I use:

    Dim r as Range
    r = Range("A1")
这样做是行不通的。没有Set,你会收到运行时错误#91 对象变量或 With 块变量未设置。这是因为你必须使用Set将变量值分配给对象引用。然后上面的代码就会起作用。
我认为下面的代码说明了你真正想问的内容。假设我们没有声明类型,让r成为Variant类型。
Public Sub test()
    Dim r
    debug.print TypeName(r)

    Set r = Range("A1")
    debug.print TypeName(r)

    r = Range("A1")
    debug.print TypeName(r)
End Sub

所以,让我们分解这里发生的事情。
  1. r is declared as a Variant

    `Dim r` ' TypeName(r) returns "Empty", which is the value for an uninitialized variant
    
  2. r is set to the Range containing cell "A1"

    Set r = Range("A1") ' TypeName(r) returns "Range"
    
  3. r is set to the value of the default property of Range("A1").

    r = Range("A1") ' TypeName(r) returns "String"
    
在这种情况下,Range 的默认属性是 .Value,因此以下两行代码是等效的。
r = Range("A1")
r = Range("A1").Value

如果想了解更多有关默认对象属性的内容,请查看Chip Pearson的“类的默认成员”


关于你的Set示例:

Other times I use

Set r = Range("A1")
这将无法正常工作,除非首先声明rRangeVariant对象...使用Dim语句-除非您未启用Option Explicit,但应该始终启用。否则,您正在使用未声明的标识符,它们都被隐式声明为Variants

@PierreClaverie 是的 :) 它包括了 DimSet 的原始引用。 - Wolf
3
@Wolf 不确定你是否知道,VBA语言参考现在在GitHub上维护。https://github.com/OfficeDev/VBA-content/blob/master/VBA/Language-Reference-VBA/readme.md - RubberDuck
@RubberDuck 我不知道(我是vb*的新手),感谢您添加这个注释。 - Wolf
不客气,@Wolf。我知道现在很难找到VBA和旧的VB6文档。 - RubberDuck

12

Dim:你正在定义一个变量(这里是一个类型为 Range 的变量 r)

Set:你正在设置属性(这里将 r 的值设置为 Range("A1") - 这不是一个类型,而是一个值)。

如果 r 是一个简单类型(如 int、string),那么你就不需要使用 set:

Dim r As Integer
r=5

4

Dim只是声明值和类型。

Set将一个值分配给变量。


2

如果一个变量被定义为一个对象,例如:Dim myfldr As Folder,那么就需要使用关键字“Set”来给它赋值。


1

Dim 是 Dimension 的缩写,用于在 VBA 和 VB6 中声明本地变量。

相反,Set 与变量声明无关。 Set 关键字用于将对象变量分配给新对象。

希望这为您澄清了区别。


0
根据VBA SET语句的帮助文档,它会设置一个对象的引用。因此,如果您更改属性,则实际对象也会发生更改。
Dim newObj as Object
Set var1=Object1(same type as Object)
Set var2=Object1(same type as Object)
Set var3=Object1(same type as Object)
Set var4=Object1(same type as Object)
Var1.property1=NewPropertyValue

其他变量属性也会改变,所以:

Var1.property1=Var2.property1=Var3.property1=Var4.property1=Object1.Property1=NewpropertyValue`

其实所有的变量都是一样的!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接