我从一个更大的块中打破了一些代码并需要将工作表传递给它...
我没有为工作表分配任何新值,但我正在更改该工作表的分页符设置.我需要将其作为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加入我很大程度上参与其中,它可以分析您的代码并查看以下内容:
参数按值传递,但会分配新值/引用.如果调用者不应该知道新值,请考虑制作本地副本.如果调用者应该看到新值,则应该通过ByRef传递参数,并且您有一个错误.
http://rubberduckvba.com/Inspections/Details/AssignedByValParameterInspection
在过程退出之前,只有一个参数通过引用传递的过程(在过程退出之前分配了一个新值/引用)使用ByRef参数作为返回值:考虑使其成为函数.
http://rubberduckvba.com/Inspections/Details/ProcedureCanBeWrittenAsFunctionInspection
通过引用传递但未分配新值/引用的参数可以通过值传递.
http://rubberduckvba.com/Inspections/Details/ParameterCanBeByValInspection
这就是wsReport
这里的情况:
两者都可以工作,但对于语义正确的代码,更喜欢通过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加入我很大程度上参与其中,它可以分析您的代码并查看以下内容:
参数按值传递,但会分配新值/引用.如果调用者不应该知道新值,请考虑制作本地副本.如果调用者应该看到新值,则应该通过ByRef传递参数,并且您有一个错误.
http://rubberduckvba.com/Inspections/Details/AssignedByValParameterInspection
在过程退出之前,只有一个参数通过引用传递的过程(在过程退出之前分配了一个新值/引用)使用ByRef参数作为返回值:考虑使其成为函数.
http://rubberduckvba.com/Inspections/Details/ProcedureCanBeWrittenAsFunctionInspection
通过引用传递但未分配新值/引用的参数可以通过值传递.
http://rubberduckvba.com/Inspections/Details/ParameterCanBeByValInspection
这就是wsReport
这里的情况: