2017-01-23 1 views
2

Я вырвал код из более крупного блока и ему нужно передать рабочий лист ...Нужно ли передавать листок в качестве ByRef или ByVal?

Я не назначаю никакого нового значения для рабочего листа, но я вношу изменения в параметры разрыва страницы для этого лист. Нужно ли передавать его как 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 
+2

это может помочь http://www.windowsdevcenter.com/pub/a/oreilly/windows/ ron/objects.html –

ответ

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 параметра:

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 parameter is assigned

Параметр передается по значению, но ему присваивается новое значение/ссылка. Подумайте о создании локальной копии вместо этого, если вызывающий абонент не должен знать новое значение. Если вызывающий пользователь должен увидеть новое значение, вместо этого параметр должен быть принят ByRef, и у вас есть ошибка.

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

Procedure can be written as a function

Процедура, которая имеет только один параметр, передаваемый по ссылке, который назначается новое значение/ссылка перед процедурой выходов, использует параметр ByRef как возвращаемое значение: рассмотрим возможность сделать это функцией.

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

Parameter can be passed by value

Параметр, который передается по ссылке, и не назначается новое значение/ссылка, может быть передан по значению вместо этого.

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

Это случай wsReport здесь:

Parameter 'wsReport' can be passed by value

+0

Я использую Rubberduck, и именно это побудило меня задуматься над вопросом. В то время как переменной рабочего листа никогда не назначалось новое значение (ByVal было бы хорошо), тот факт, что изменения вносились в лист (изменения обычно требовали ByRef), заставляли меня задаться вопросом, была ли ByVal лучшей практикой для передачи объекта. – Rdster

+3

@Rdster Изменения внесены в лист, потому что копия указателя указывает на тот же рабочий лист, поэтому изменения, сделанные на листе * do * "распространяются", - это * - один и тот же объект. Но если вы передадите его «ByRef», тогда процедура может установить его в «Nothing», и когда он вернется к вызывающему, тогда вызывающий оператор потеряет указатель, потому что «ByRef» разрешил указателю «Установить» что-то еще. .. Надеюсь, что имеет смысл. также, yay Rubberduck! –

+0

@Rdster FWIW Я думаю, что мой ответ был бы более сфокусированным, если бы вопрос был помечен [tag: rubberduck] и конкретно спросил, почему Rubberduck предлагает передавать объекты по значению (я имею в виду, да, там есть тег Rubberduck на SO!) - don Не стесняйтесь спрашивать о любой другой проверке! –