我已经构建了一个类,需要将数据记录到单元格中。因此我写了一个这样做的函数。 代码如下:
Option Explicit
Private sName As String
Public Property Let Name(ByVal strValue As String)
sName = strValue
End Property
Public Property Get Name() As String
Name = sName
End Property
Public Function ItemToCell(ByRef tgtCell As Range)
tgtCell = sName
End Function
我还设置了一个按钮来触发这个过程:
Private Sub CommandButton1_Click()
Dim tmpData As New MyClass
tmpData.Name = "Tom"
Dim tgtCell As Range
Set tgtCell = Worksheets("Sheet1").Range("A1")
'Method 1, this failed with error 424
tmpData.ItemToCell (tgtCell)
'Method 2, it works
tmpData.ItemToCell (Worksheets("Sheet1").Range("B1"))
End Sub
我认为这两种方法是相同的,但显然它们不是。 为什么?变量tgtCell不是一个对象吗?
答案 0 :(得分:5)
请注意,下面的方法1A,删除了括号,DOES按预期工作:
Public Sub CommandButton1_Click()
On Error GoTo EH
Dim tmpData As New MyClass
tmpData.Name = "Tom"
Dim tgtCell As Range
Set tgtCell = Worksheets("Sheet1").Range("A1")
'Method 1, this failed with error 424
tmpData.ItemToCell (tgtCell)
'Method 1A, this works
tmpData.ItemToCell tgtCell
'Method 2, it works
tmpData.ItemToCell (Worksheets("Sheet1").Range("B1"))
XT: Exit Sub
EH: MsgBox Err.Description, vbOKOnly, Err.Source
Resume Next
End Sub
出现困难的原因是调用到tmpData.ItemToCell
需要一个l值(即它是一个ByRef参数),但是调用语句不是一个函数调用,因此括号是不是调用的括号,而是分组的括号。这在VBA中可能是一个令人困惑的问题。
分组括号的效果是返回变量tgtCell
的值,而不是存储位置,并隐式评估Range对象的默认成员值 。但是,当你偶然发现方法2时,有些情况下VBA 不会隐式评估默认成员。是的,这让每个人都感到困惑;不要感到孤单。
最小化此烦恼发生的一种方法是明确指定函数和子(和Set / Let属性)的参数作为ByVal,除非您实际希望将更改的值传递回调用者。赢得胜利:
然而,您的情况是罕见的,这无济于事。在这种情况下,最好不要在方法调用中添加括号,直到VBA抱怨它们缺席,这通常只适用于函数而不是Subs和Property Setters / Letters。
总结:
- 参数应明确指定为ByVal(而不是默认的ByRef),除非您确实传回计算值(在这种情况下,Function是更好的实现并且通常足够)或者当语言要求您传递ByRef参数时。
- 当VBA抱怨缺席时,括号只应用于方法调用。