VBA循环中为数组赋值对象异常:所有元素指向同一对象
解决VBA循环中数组元素指向同一对象的问题
嘿,这个问题我太熟了——你踩中了VBA里Dim...As New这个经典的“坑”!咱们一步步拆解原因和解决办法:
为什么输出全是3?
VBA里的Dim obj As New Class1和其他语言的声明实例化逻辑不一样,它是延迟实例化的:只有当你第一次引用obj的时候,VBA才会创建一个Class1的实例。在你的循环里,第一次循环触发了实例创建,后续循环再用obj时,VBA不会新建对象,而是直接复用之前那个已经存在的实例。所以你每次循环都是给同一个对象的name属性赋值,最后一次赋值成3,数组里的所有元素自然都指向这个唯一的对象,输出全是3。
为什么去掉Set会报错?
因为Class1是对象类型,不是普通的值类型(比如Integer、String)。在VBA中,给对象类型的变量/数组元素赋值时,必须用Set关键字来建立引用关系;直接赋值是给值类型用的,所以会抛出“Object variable or with block variable not set”的错误。
正确的写法
要在循环里创建独立的对象,必须每次显式实例化新对象,把Dim和实例化操作分开:
Sub foo() Dim Arr(1 To 3) As Class1 Dim i As Integer Dim obj As Class1 ' 先声明对象变量,不立即实例化 For i = 1 To 3 Set obj = New Class1 ' 每次循环都创建一个全新的Class1实例 obj.name = i Set Arr(i) = obj ' 用Set把新对象的引用存入数组 Next For i = 1 To 3 Debug.Print Arr(i).name Next End Sub
运行这段代码,就能得到预期的1 2 3输出了。
你也可以把Dim obj As Class1放到循环内部(VBA允许在循环里声明变量),效果是完全一样的:
Sub foo() Dim Arr(1 To 3) As Class1 Dim i As Integer For i = 1 To 3 Dim obj As Class1 Set obj = New Class1 obj.name = i Set Arr(i) = obj Next For i = 1 To 3 Debug.Print Arr(i).name Next End Sub
关键要点总结
- 避免在VBA中用
Dim...As New的写法创建需要多次实例化的对象,它会复用同一个实例。 - 对象类型的赋值必须使用
Set关键字,值类型则不需要。 - 循环中创建独立对象,一定要每次用
Set obj = New 类名显式新建实例。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

