VBA in Excel/ ByRef und ByVal
Zu ByRef und ByVal
BearbeitenVariablen können an Funktionen oder Unterprogramme übergeben, dort zu Berechnungen verwendet und mit geänderten Werten zurückgegeben werden. Entscheidend hierfür ist das Schlüsselwort der Parameter-Definition des aufnehmenden Unterprogramms.
VBA kennt die Parameterübergaben ByRef (Übergabe der Referenz auf die Speicherstelle mit dem Wert der Variablen) und ByVal (Übergabe des Wertes der Variablen). Im ersten Fall – das ist die Standardeinstellung, d.h. wenn keine Vorgabe erfolgt, wird der Parameter als ByRef behandelt – wird der Wert des Parameters weiterverarbeitet; Änderungen sind auch für das aufrufende Programm wirksam. Im zweiten Fall wird eine Kopie des Parameters übergeben; die Wirksamkeit beschränkt sich auf das aufgerufene Unterprogramm und der Parameter im aufrufenden Programm behält seinen ursprünglichen Wert.
Die Beispiele
BearbeitenAufruf einer benutzerdefinierten Funktion ohne ByRef/ByVal-Festlegung
BearbeitenDie Funktion errechnet anhand der übergebenen Parameter den Wert und gibt diesen an das aufrufende Programm zurück, wobei die übergebenen Parameter nicht geändert werden.
Sub CallFunction()
Dim dQM As Double
dQM = fncQM( _
Range("A2").Value, _
Range("B2").Value, _
Range("C2").Value)
MsgBox "Quadratmeter Außenfläche: " & _
Format(dQM, "0.000")
End Sub
Private Function fncQM( _
dLong As Double, dWidth As Double, dHeight As Double)
fncQM = 2 * (dLong * dWidth + _
dLong * dHeight + _
dWidth * dHeight)
End Function
Aufruf eines Unterprogramms ohne ByRef/ByVal-Festlegung
BearbeitenDas Unterprogramm wird mit den für die Berechnung notwendigen Parametern und zusätzlich mit einer 0-Wert-Double-Variablen, die als Container für das Berechnungsergebnis dient, aufgerufen. Alle Parameter gelten als ByRef, da kein Schlüsselwort verwendet wurde.
Sub CallMacro()
Dim dQM As Double
Call GetQm( _
dQM, _
Range("A2").Value, _
Range("B2").Value, _
Range("C2").Value)
MsgBox "Quadratmeter Außenfläche: " & _
Format(dQM, "0.000")
End Sub
Private Sub GetQm( _
dValue As Double, dLong As Double, _
dWidth As Double, dHeight As Double)
dValue = 2 * (dLong * dWidth + _
dLong * dHeight + _
dWidth * dHeight)
End Sub
Aufruf mit einer Integer-Variablen bei Anwendung von ByVal
BearbeitenDas Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablaufs des Unterprogramms, ohne dass sich im aufrufenden Programm der Variablenwert ändert.
Sub AufrufA()
Dim iRow As Integer, iStart As Integer
iRow = 2
iStart = iRow
Call GetRowA(iRow)
MsgBox "Ausgangszeile: " & iStart & _
vbLf & "Endzeile: " & iRow
End Sub
Private Sub GetRowA(ByVal iZeile As Integer)
Do Until IsEmpty(Cells(iZeile, 1))
iZeile = iZeile + 1
Loop
End Sub
Aufruf mit einer Integer-Variablen bei Anwendung von ByRef
BearbeitenDas Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablaufs des Unterprogramms, damit auch der Wert der Variablen im aufrufenden Programm.
Sub AufrufB()
Dim iRow As Integer, iStart As Integer
iRow = 2
iStart = iRow
Call GetRowB(iRow)
MsgBox "Ausgangszeile: " & iStart & _
vbLf & "Endzeile: " & iRow
End Sub
Private Sub GetRowB(ByRef iZeile As Integer)
Do Until IsEmpty(Cells(iZeile, 1))
iZeile = iZeile + 1
Loop
End Sub
Aufruf mit einer String-Variablen bei Anwendung von ByVal
BearbeitenDas Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablaufs des Unterprogramms, ohne dass sich im aufrufenden Programm der Variablenwert ändert.
Sub CallByVal()
Dim sPath As String, sStart As String
sPath = ThisWorkbook.Path
sStart = sPath
Call GetByVal(sPath)
MsgBox "Vorher: " & sStart & _
vbLf & "Nachher: " & sPath
End Sub
Private Sub GetByVal(ByVal sDir As String)
If Right(sDir, 1) <> "\" Then
sDir = sDir & "\"
End If
End Sub
Aufruf mit einer String-Variablen bei Anwendung von ByRef
BearbeitenDas Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablauf des Unterprogramms, damit auch der Wert der Variablen im aufrufenden Programm.
Sub CallByRef()
Dim sPath As String, sStart As String
sPath = ThisWorkbook.Path
sStart = sPath
Call GetByRef(sPath)
MsgBox "Vorher: " & sStart & _
vbLf & "Nachher: " & sPath
End Sub
Private Sub GetByRef(ByRef sDir As String)
If Right(sDir, 1) <> "\" Then
sDir = sDir & "\"
End If
End Sub
Aufruf mit einer Objekt-Variablen bei Anwendung von ByVal
BearbeitenDas Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablaufs des Unterprogramms, ohne dass sich im aufrufenden Programm der Variablenwert ändert.
Sub CallObjectA()
Dim rngA As Range, rngB As Range
Set rngA = Range("A1:A10")
Set rngB = rngA
Call GetObjectA(rngA)
MsgBox "Vorher: " & rngB.Address(False, False) & _
vbLf & "Nachher: " & rngA.Address(False, False)
End Sub
Private Sub GetObjectA(ByVal rng As Range)
Set rng = Range("F1:F10")
End Sub
Aufruf mit einer Objekt-Variablen bei Anwendung von ByRef
BearbeitenDas Unterprogramm wird mit einer Objekt-Variablen aufgerufen. Der Wert dieser Variablen, also der Verweis auf ein Objekt, verändert sich während des Ablaufs des Unterprogramms, damit auch der Wert der Objekt-Variablen im aufrufenden Programm. Das Objekt, auf das die Variable ursprünglich verwies, bleibt aber unverändert.
Sub CallObjectB()
Dim rngA As Range, rngB As Range
Set rngA = Range("A1:A10")
Set rngB = rngA
Call GetObjectB(rngA)
MsgBox "Vorher: " & rngB.Address(False, False) & _
vbLf & "Nachher: " & rngA.Address(False, False)
End Sub
Private Sub GetObjectB(ByRef rng As Range)
Set rng = Range("F1:F10")
End Sub