简体   繁体   English

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

[英]Difference between range and variable dim as range

I've built a class and need to record the data into a cell. 我已经构建了一个类,需要将数据记录到单元格中。 Therefore I write a function doing this. 因此我写了一个这样做的函数。 Codes below: 代码如下:

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

And I also set a button to trigger this process: 我还设置了一个按钮来触发这个过程:

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

I thought that these two methods were the same, but apparently they are not. 我认为这两种方法是相同的,但显然它们不是。 Why? 为什么? Isn't the variable tgtCell an object? 变量tgtCell不是一个对象吗?

Note that method 1A below, with the parentheses removed, DOES work as expected: 请注意,下面的方法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

The difficulty arises because the call to tmpData.ItemToCell requires an l-value (ie it is a ByRef argument) but the invocation statement IS NOT a function call, and so the parentheses are not the parentheses of invocation , but rather the parentheses of grouping . 之所以出现这种困难,是因为对tmpData.ItemToCell调用需要一个l值(即它是一个ByRef参数),但是调用语句不是一个函数调用,因此括号不是调用括号 ,而是分组括号 This can be a confusing issue in VBA. 这在VBA中可能是一个令人困惑的问题。

The effect of the parentheses of grouping is to return the value of the variable tgtCell rather than its storage location , and implicitly evaluating the default member Value of the Range object . 分组括号的作用是返回变量tgtCell而不是其存储位置 ,并隐式计算Range对象默认成员Value However, as you stumbled into with Method 2, there are circumstances where VBA does not implicitly evaluate the default member. 但是,当您偶然发现方法2时,有些情况下VBA 不会隐式评估默认成员。 Yes, it's confusing to everyone; 是的,这让每个人都感到困惑; don't feel alone. 不要感到孤单。

One way to minimize the occurrence of this annoyance is to explicitly specify parameters for Functions and Subs (And Set/Let properties) as ByVal unless you actually desire to pass back a changed value to the caller. 最小化此烦恼发生的一种方法是将函数和子(和Set / Let属性)的参数明确指定为ByVal,除非您实际希望将更改的值传递回调用者。 This wins by: 这赢得了:

  • eliminating many instances of this annoying feature; 消除了这个令人讨厌的功能的许多实例;
  • eliminating many subtle bugs when you treat the parameter as a local variable, and change its value expecting those changes to be local in scope, when they are actually non-local. 当您将参数视为局部变量时,消除许多微妙的错误,并且当它们实际上是非本地变量时,将其值更改为期望这些更改在范围内是本地的。

However, your circumstance is the rare one where this does not help. 但是,您的情况是罕见的,这无济于事。 In these case it is imply best to not add parentheses to method calls until VBA complains of their absence, which is generally just for Functions rather than Subs and Property Setters/Letters. 在这种情况下,最好不要在方法调用中添加括号,直到VBA抱怨它们缺席,这通常只适用于函数而不是Subs和Property Setters / Letters。

在此输入图像描述

In summary: 综上所述:
- Parameters should be explicitly specified as ByVal (rather than the default of ByRef) unless you really are passing back a calculated value (in which case a Function is a better implementation and usually sufficient) or when the language requires you to pass a ByRef argument. - 参数应明确指定为ByVal(而不是默认的ByRef),除非您确实传回计算值(在这种情况下,Function是更好的实现并且通常足够)或者当语言要求您传递ByRef参数时。
- Parentheses should only be used in method invocations when VBA complains of their absence. - 当VBA抱怨缺席时,括号只应用于方法调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM