我已经构建了一个类,需要将数据记录到单元格中.因此我写了一个这样做的函数.代码如下:
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
Run Code Online (Sandbox Code Playgroud)
我还设置了一个按钮来触发这个过程:
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
Run Code Online (Sandbox Code Playgroud)
我认为这两种方法是相同的,但显然它们不是.为什么?变量tgtCell不是一个对象吗?
请注意,下面的方法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
Run Code Online (Sandbox Code Playgroud)
出现困难,因为调用到tmpData.ItemToCell需要的左值(即它是一个ByRef参数),但调用语句不是一个函数调用,所以括号不是调用的括号,而是分组的括号.这在VBA中可能是一个令人困惑的问题.
分组括号的作用是返回变量的值tgtCell而不是其存储位置,并隐式计算Range对象的默认成员Value.但是,当您偶然发现方法2时,有些情况下VBA 不会隐式评估默认成员.是的,这让每个人都感到困惑; 不要感到孤单.
最小化此烦恼发生的一种方法是将函数和子(和Set/Let属性)的参数明确指定为ByVal,除非您实际希望将更改的值传递回调用者.这赢得了:
但是,您的情况是罕见的,这无济于事.在这种情况下,最好不要在方法调用中添加括号,直到VBA抱怨它们缺席,这通常只适用于函数而不是Subs和Property Setters/Letters.
总结:
- 参数应明确指定为ByVal(而不是默认的ByRef),除非您确实传回计算值(在这种情况下,Function是更好的实现并且通常足够)或者语言要求您通过一个ByRef参数.
- 当VBA抱怨缺席时,括号只应用于方法调用.