Microsoft Excel

Excel und VBA: Formeln, Programmierung, Lösungen

Inhalt dieser Seite

Zu ByRef und ByVal

Variablen 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 und ByVal. 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.

Dies gilt nicht für Objekt-Variablen. Diese behalten auch bei der Verwendung des Schlüsselwortes ByRef in der aufrufenden Prozedur ihren ursprünglichen Wert.

Die Beispiele

  • Aufruf einer benutzerdefinierten Funktion ohne ByRef/ByVal-Festlegung



    Die 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



    Das 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



    Das Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablauf 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



    Das 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 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



    Das Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablauf 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



    Das 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



    Das Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablauf 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



    Das Unterprogramm wird mit einer Variablen aufgerufen. Der Wert dieser Variablen verändert sich während des Ablauf des Unterprogramms, ohne dass sich im aufrufenden Programm der Variablenwert ändert.

    Sub CallObjectB()
       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 GetObjectB(ByRef rng As Range)
       Set rng = Range("F1:F10")
    End Sub