范围和变量之间的差异作为范围变暗

new*_*240 4 excel vba

我已经构建了一个类,需要将数据记录到单元格中.因此我写了一个这样做的函数.代码如下:

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不是一个对象吗?

Pie*_*ens 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
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抱怨缺席时,括号只应用于方法调用.