当前位置:  开发笔记 > 后端 > 正文

我是否需要将工作表作为ByRef或ByVal传递?

如何解决《我是否需要将工作表作为ByRef或ByVal传递?》经验,为你挑选了1个好方法。

我从一个更大的块中打破了一些代码并需要将工作表传递给它...

我没有为工作表分配任何新值,但我正在更改该工作表的分页符设置.我需要将其作为ByRef传递,还是ByVal足够好?

Private Sub SetPageBreaks(ByRef wsReport As Worksheet)
Dim ZoomNum As Integer

  wsReport.Activate
  ActiveWindow.View = xlPageBreakPreview
  ActiveSheet.ResetAllPageBreaks
  ZoomNum = 85
  With ActiveSheet
    Select Case wsReport.Name
      Case "Compare"
        Set .VPageBreaks(1).Location = Range("AI1")
        ZoomNum = 70
      Case "GM"
        .VPageBreaks.Add before:=Range("X1")
      Case "Drift"
        .VPageBreaks.Add before:=Range("T1")
      Case Else
        .VPageBreaks.Add before:=Range("U1")
    End Select
  End With
  ActiveWindow.View = xlNormalView
  ActiveWindow.Zoom = ZoomNum

End Sub

Mathieu Guin.. 8

两者都可以工作,但对于语义正确的代码,更喜欢通过value(ByVal)传递它.

当你按值传递的对象变量,你传递一个副本的的指针对象.

所以该过程使用的相同的对象(即调用者看到更改的属性值),除非它不允许Set指向其他东西 - 它可以,但它会在它自己的副本上执行和所以来电者不会受到影响.

Public Sub DoSomething()
    Dim target As Worksheet
    Set target = ActiveSheet
    Debug.Print ObjPtr(target)
    DoSomethingElse target
    Debug.Print ObjPtr(target)
End Sub

Private Sub DoSomethingElse(ByVal target As Worksheet)
    Debug.Print ObjPtr(target)
    Set target = Worksheets("Sheet12")
    Debug.Print ObjPtr(target)
    'in DoSomething, target still refers to the ActiveSheet
End Sub

另一方面...

Public Sub DoSomething()
    Dim target As Worksheet
    Set target = ActiveSheet
    Debug.Print ObjPtr(target)
    DoSomethingElse target
    Debug.Print ObjPtr(target)
End Sub

Private Sub DoSomethingElse(ByRef target As Worksheet)
    Debug.Print ObjPtr(target)
    Set target = Worksheets("Sheet12")
    Debug.Print ObjPtr(target)
    'in DoSomething, target now refers to Worksheets("Sheet12")
End Sub

通常,参数应按值传递.这只是一个不幸的语言怪癖ByRef是默认的(VB.NET修复).

对于非对象变量也是如此:

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByVal foo As Long)
    foo = 12
    'in DoSomething, foo is still 42
End Sub

和...

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByRef foo As Long)
    foo = 12
    'in DoSomething, foo is now 12
End Sub

如果变量通过引用传递,但从未在过程体中重新分配,则可以按值传递.

如果变量通过引用传递,并在过程的主体中重新分配,那么该过程可能会被写为a Function,并实际返回修改后的值.

如果变量按值传递,并在过程体中重新分配,则调用者不会看到更改 - 这会使代码可疑; 如果一个过程需要重新分配一个ByVal参数值,那么如果代码定义了自己的局部变量并且分配了而不是ByVal参数:

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByVal foo As Long)
    Dim bar As Long
    bar = foo
    '...
    bar = 12
    '...
End Sub

这些都是Rubberduck中的实际代码检查,因为VBE加入我很大程度上参与其中,它可以分析您的代码并查看以下内容:

ByVal参数已分配

参数按值传递,但会分配新值/引用.如果调用者不应该知道新值,请考虑制作本地副本.如果调用者应该看到新值,则应该通过ByRef传递参数,并且您有一个错误.

http://rubberduckvba.com/Inspections/Details/AssignedByValParameterInspection

过程可以编写为函数

在过程退出之前,只有一个参数通过引用传递的过程(在过程退出之前分配了一个新值/引用)使用ByRef参数作为返回值:考虑使其成为函数.

http://rubberduckvba.com/Inspections/Details/ProcedureCanBeWrittenAsFunctionInspection

参数可以按值传递

通过引用传递但未分配新值/引用的参数可以通过值传递.

http://rubberduckvba.com/Inspections/Details/ParameterCanBeByValInspection

这就是wsReport这里的情况:

参数'wsReport'可以通过值传递



1> Mathieu Guin..:

两者都可以工作,但对于语义正确的代码,更喜欢通过value(ByVal)传递它.

当你按值传递的对象变量,你传递一个副本的的指针对象.

所以该过程使用的相同的对象(即调用者看到更改的属性值),除非它不允许Set指向其他东西 - 它可以,但它会在它自己的副本上执行和所以来电者不会受到影响.

Public Sub DoSomething()
    Dim target As Worksheet
    Set target = ActiveSheet
    Debug.Print ObjPtr(target)
    DoSomethingElse target
    Debug.Print ObjPtr(target)
End Sub

Private Sub DoSomethingElse(ByVal target As Worksheet)
    Debug.Print ObjPtr(target)
    Set target = Worksheets("Sheet12")
    Debug.Print ObjPtr(target)
    'in DoSomething, target still refers to the ActiveSheet
End Sub

另一方面...

Public Sub DoSomething()
    Dim target As Worksheet
    Set target = ActiveSheet
    Debug.Print ObjPtr(target)
    DoSomethingElse target
    Debug.Print ObjPtr(target)
End Sub

Private Sub DoSomethingElse(ByRef target As Worksheet)
    Debug.Print ObjPtr(target)
    Set target = Worksheets("Sheet12")
    Debug.Print ObjPtr(target)
    'in DoSomething, target now refers to Worksheets("Sheet12")
End Sub

通常,参数应按值传递.这只是一个不幸的语言怪癖ByRef是默认的(VB.NET修复).

对于非对象变量也是如此:

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByVal foo As Long)
    foo = 12
    'in DoSomething, foo is still 42
End Sub

和...

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByRef foo As Long)
    foo = 12
    'in DoSomething, foo is now 12
End Sub

如果变量通过引用传递,但从未在过程体中重新分配,则可以按值传递.

如果变量通过引用传递,并在过程的主体中重新分配,那么该过程可能会被写为a Function,并实际返回修改后的值.

如果变量按值传递,并在过程体中重新分配,则调用者不会看到更改 - 这会使代码可疑; 如果一个过程需要重新分配一个ByVal参数值,那么如果代码定义了自己的局部变量并且分配了而不是ByVal参数:

Public Sub DoSomething()
    Dim foo As Long
    foo = 42
    DoSomethingElse foo
End Sub

Private Sub DoSomethingElse(ByVal foo As Long)
    Dim bar As Long
    bar = foo
    '...
    bar = 12
    '...
End Sub

这些都是Rubberduck中的实际代码检查,因为VBE加入我很大程度上参与其中,它可以分析您的代码并查看以下内容:

ByVal参数已分配

参数按值传递,但会分配新值/引用.如果调用者不应该知道新值,请考虑制作本地副本.如果调用者应该看到新值,则应该通过ByRef传递参数,并且您有一个错误.

http://rubberduckvba.com/Inspections/Details/AssignedByValParameterInspection

过程可以编写为函数

在过程退出之前,只有一个参数通过引用传递的过程(在过程退出之前分配了一个新值/引用)使用ByRef参数作为返回值:考虑使其成为函数.

http://rubberduckvba.com/Inspections/Details/ProcedureCanBeWrittenAsFunctionInspection

参数可以按值传递

通过引用传递但未分配新值/引用的参数可以通过值传递.

http://rubberduckvba.com/Inspections/Details/ParameterCanBeByValInspection

这就是wsReport这里的情况:

参数'wsReport'可以通过值传递


@Rdster对工作表进行了更改,因为指针的副本指向同一工作表,因此对工作表进行的更改*do*"传播" - 它*是*同一个对象.但是如果你传递它`ByRef`那么程序可以将它设置为`Nothing`并且当它返回到调用者时然后调用者丢失指针,因为`ByRef`允许指针被"设置"为其他东西...希望是有道理的.还有,yay Rubberduck!
推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有