我从一个更大的块中打破了一些代码,需要将工作表传递给它......
我没有为工作表分配任何新值,但我正在更改该工作表的分页符设置。我需要将其作为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
答案 0 :(得分:6)
两者都可以,但对于语义正确的代码,更喜欢按值(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
如果变量通过引用传递,但从未在过程体中重新分配,则可以按值传递。
如果变量通过引用传递,并在过程的主体中重新分配,那么该过程可能会写为Function
,并且实际上返回修改后的值
如果一个变量按值传递,并在一个过程的主体中重新分配,那么调用者就不会看到这些变化 - 这会使代码变得可疑;如果某个过程需要重新分配ByVal
参数值,那么如果代码定义了自己的局部变量并且分配 而不是ByVal
参数,则代码的意图会变得更清晰: / p>
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插件,可以分析您的代码并查看这些内容:
参数按值传递,但会分配一个新值/引用。如果调用者不应该知道新值,请考虑制作本地副本。如果调用者应该看到新值,那么该参数应该通过ByRef传递,并且你有一个错误。
<子> http://rubberduckvba.com/Inspections/Details/AssignedByValParameterInspection 子>
只有一个参数通过引用传递的过程在过程退出之前分配了一个新的值/引用,使用ByRef参数作为返回值:考虑将其改为函数。
<子> http://rubberduckvba.com/Inspections/Details/ProcedureCanBeWrittenAsFunctionInspection 子>
通过引用传递并且未分配新值/引用的参数可以通过值传递。
<子> http://rubberduckvba.com/Inspections/Details/ParameterCanBeByValInspection 子>
这是wsReport
的情况: