Variablen
Eine Variable ist ein Speicherort, an dem ein Wert abgelegt werden kann, der später in der Programmierung abgerufen oder verändert werden soll.
Variablen anlegen
Deklaration
Um eine Variable verwenden zu können, muss sie deklariert werden. Damit wird der Speicherort reserviert und der Name der Variable dient als Kennung, damit später auf genau diesen Wert zugegriffen werden kann.
Der reservierte Platz und die Art des Speicherplatzes wird mit dem angegebenen Datentyp bestimmt. So wird bei der Deklaration festgelegt, ob z. B. eine Zahl oder ein Text oder ein Datum gespeichert wird.
Den Datentyp kann man nur bei der Deklaration angeben und später nicht ändern.
Bei der Deklaration können mehrere Variablen in einer Zeile gemeinsam angegeben werden und werden dann durch Kommata voneinander getrennt:
Dim strName As String, strAddress As String Public FirstName As String, LastName As String, Phone as String
Bitte beachten:
- Sie können zwar mehrere Variablen von verschiedenen Datentypen in einer Zeile deklarieren, sollten dies jedoch vermeiden, um Ihres Programmcode nicht unnötig kompliziert zu gestalten!
- Wenn Sie mehrere Variablen in einer Zeile deklarieren, müssen Sie jedes Mal mit 'As' den Datentyp angeben, sonst wird die Variable als 'Variant' deklariert.
Datentyp
Der Datentyp wird bei allen Variablen mit dem Schüsselwort As
und dem Bezeichner des Datentyps angegeben.
Eine vollständige Liste der in VBA möglichen Datentypen finden Sie hier: Datentypen
Benennung
Um den Zweck der Variablen klar zu kennzeichnen, sollten Sie eindeutige, sprechende Namen wählen, welche jederzeit und für jedermann und innerhalb des Kontextes eine klare Bedeutung haben.
Beispiele:
Dim strFirstName As String, strLastName As String
Die Bezeichnung und der Datentyp, welcher Teil des Namens ist (im Beispiel das vorangestellte 'str') lassen keinen Zweifel zu, welche Daten diese Variablen enthalten.
Der Grund für die ausdrückliche Angabe des Datentyps auch im Variablennamen wird mit diesem Beispiel verdeutlicht:
Dim strItem As String Dim lngItem As Long Dim colCollection As New Collection colCollection.Add "One" colCollection.Add "Two" For lngItem = 1 To colCollection.Count strItem = colCollection.Item(lngItem) Next lngItem
Der Name 'Item' wird zweimal unabhängig voneinander belegt, einmal als Zeichenkette, die einen Wert entgegennimmt, und dann als Zählvariable für die For-Schleife. In beiden Fällen ist der Name 'Item' gerechtfertigt, durch das vorangestellte 'str' bzw. 'lng' können beide trotzdem klar voneinander unterschieden werden.
Weitere Angaben zur Bezeichnung des Datentyps im Variablennamen finden Sie im Anhang.
Reihenfolge
Die Reihenfolge, in der Datentypen deklariert werden, hat keine Auswirkung auf die Ausführung des Programmcodes, durchaus jedoch auf die Lesbarkeit für uns Programmierer!
Gewöhnen Sie es sich daher gerne an, Ihre Deklarationen immer in der gleichen Reihenfolge anzulegen, um später schnell ermitteln zu können, welche Variablen schon angelegt wurden und welche Rolle diese in dieser Prozedur spielen.
Die von mir persönlich verwendete Reihenfolge gestaltet sich folgendermaßen:
- Zeichenketten
- Zahlenwerte nach Größe sortiert (Integer, Long, Single, Double)
- Collections
- Eigene Objekte (zum Beispiel Klassen), Enums und benutzerdefinierte Datentypen
- Anwendungsobjekte wenn möglich nach Größe sortiert (zum Beispiel Bereich, Dokument, Anwendung in Word oder Zelle, Arbeitsblatt, Arbeitsmappe in Excel)
Der gespeicherte Wert
Abhängig von seinem Datentyp enthält der Speicherplatz einer Variablen bei der Deklaration einen leeren Wert:
Ursprünglicher Leerwert
- String: "" (Leerstring)
- Integer und Long: 0
- Single, Double, Currency etc.: 0.0
- Date: 00:00:00 (Uhrzeit!)
- Boolean: False (0)
- Array: abhängig vom Datentyp
- Collections, Objekte, Klassen: Nothing
Werte ändern
Bitte beachten: Anders als in vielen anderen Programmiersprachen können Sie in VBA nicht bei der Deklaration der Variablen einen Wert zuweisen. Folgendes ist also nicht möglich:
Dim strValue As String = "Hallo!" ' Verursacht einen Syntaxfehler!!!!!
Natürliche Datentypen
Um den Speicherplatz einer Variablen sinnvoll nutzen zu können, kann man ihm mit dem Ist Gleich-Operator (=) einen Wert zuweisen.
strValue = "Hallo!"
Objektvariablen
Objektvariablen bekommen mit dem zusätzlichen Schlüsselwort Set
eine Instanz des Objektes zugewiesen:
Dim objApplication As Application Set objApplication = Application
Klassenobjekte, UserFormen und Collections müssen erst mit dem Schlüsselwort New
neu erzeugt werden, bevor sie verwendet werden können:
Dim myVariables As clsVariables Set myVariables = New clsVariables myVariables.FirstName = "Max"
Dim myDialog As frmDialog Set myDialog = New frmDialog myDialog.Show
Dim colList As Collection Set colList = New Collection colList.Add "Value"
Wichtig: Anwendungsobjekte (Document, Workbook, Range, Font, ...) können nicht mit New
neu erzeugt werden, denn sie existieren schon, sobald die Anwendung gestartet wurde. Wenn Sie ein neues Dokument erzeugen möchten, verwenden Sie stattdessen folgende Vorgehensweise:
Dim doc As Document Set doc = Application.Documents.Add ' erzeugt ein neues Blanko-Dokument und übergibt es an die Variable 'doc'
Zusätzlich ist eine Kurzschreibweise möglich, welche eine Objektvariable bei der Deklaration Initialisiert.
Dim myVariables As New clsVariables myVariables.FirstName = "Max"
Dim myDialog As New frmDialog myDialog.Show
Dim colList As New Collection colList.Add "Value"
Diese Kurzschreibweise sollte jedoch nur dann verwendet werden, wenn absolut sicher ist, dass Sie das (Klassen-)Objekt, den Dialog oder die Collection auf jeden Fall verwenden werden.
Wenn Sie z. B. vor dem Anzeigen eines Dialoges sicher stellen müssen, dass der Dialog angezeigt werden kann, sollten Sie den Dialog erst dann Instanziieren, wenn Sie ihn auch anzeigen werden.
Dim dlg as frmDialog If DialogMustBeShown = True Then Set dlg = New frmDialog dlg.Show ' ... End If
Geltungsbereich, Lebensdauer und Formen der Deklaration
Jede Variable hat einen klar definierten Geltungsbereich, der sich aus dem Ort, an dem sie definiert wurde und den Schlüsselwörtern Private / Public ergibt:
Prozedurale Variable
Diese befindet sich innerhalb einer Prozedur (einer Funktion, einer Eigenschaft) und wird wie folgt mit dem Schlüsselwort Dim
deklariert:
Sub TemporaryProceduralVariable() Dim strVariable As String End Sub
Eine prozedurale Variable gilt ausschließlich innerhalb der Prozedur, in der sie definiert wurde. Die Werte sind nicht von anderen Prozeduren aus sichtbar oder veränderbar. Sobald die Prozedur verlassen wird, wird der Speicherplatz freigegeben, die Variable ist somit inklusive ihrem Wert gelöscht.
Statische prozedurale Variable
Eine mit dem Schlüsselwort Static
deklarierte prozedurale Variable hat den gleichen Geltungsbereich wie die mit Dim
deklarierte Variable, wird jedoch nach Verlassen der Prozedur nicht gelöscht, sondern bleibt solange erhalten, wie das Modul, in dem sich die Prozedur befindet, besteht (bei Modulen so lange das Projekt geladen ist, bei Klassen und UserForms so lange eine Instanz deren besteht).
Sub PermanentProceduralVariable() Static strVariable As String End Sub
So bleibt der Wert der Variable erhalten und kann bei nachfolgenden Aufrufen der Prozedur weiter verwendet werden.
Bitte beachten: Das Schlüsselwort Static
darf nicht außerhalb von Prozeduren verwendet werden.
Funktionsname
Der Name einer Funktion kann innerhalb der Funktion wie eine Variable (vom Datentyp der Funktion) verwendet werden und erfüllt zusätzlich den Zweck, den Rückgabewert der Funktion entgegenzunehmen.
Private Function ApplicationName() As String ApplicationName = Application.Name End Function
Der Wert der Variablen, die den Funktionsnamen trägt, kann ausschließlich innerhalb der Funktion geändert werden. Der Wert der Funktion kann wie folgt abgefragt werden:
Sub Example() Dim strAppName As String strAppName = ApplicationName() strAppName = ApplicationName End Sub
Die leeren runden Klammern hinter dem Funktionsnamen sind beim Aufruf optional, wenn keine Parameter erwartet werden.
Der Geltungsbereich der Funktion entspricht dem Geltungsbereich aller Prozeduren:
Private
kann nur innerhalb des (Klassen-)Moduls bzw. der UserForm verwendet werdenPublic
- in einem Modul: Kann jederzeit im gesamten Projekt verwendet werden
- in einer Klasse / einer UserForm: Kann von der Instanz der Klasse / der UserForm aufgerufen und verwendet werden
Modulweite Variablen
Modulweite Variablen können von allen Prozeduren innerhalb eines Moduls verwendet werden, weil sie außerhalb einer speziellen Prozedur deklariert werden.
Sie werden im Modulkopf, also vor der Definition der ersten Prozedur, deklariert.
Hier wir nicht das Schlüsselwort Dim
verwendet, sondern Private
:
Option Explicit Private strVariable As String Sub FirstSub() strVariable = "Hallo!" End Sub Sub SecondSub() MsgBox strVariable End Sub
Modulweite Variablen können nicht von Prozeduren in anderen Modulen ausgelesen oder beschrieben werden.
Bitte beachten: Modulweite und projektweite Variablen sollten nur in solchen Fällen eingesetzt werden, in denen sie sinnvoll sind, und nicht, um 'Variablen zu sparen'.
Wenn Variablen über längere Zeiträume und aus mehreren Quellen Werte behalten bzw. beziehen, kann leicht die Übersicht darunter leiden bzw. können sich unerwartete Werte in den Variablen befinden.
Der sinnvolle Einsatz von modulweiten und projektweiten Variablen wäre zum Beispiel für solche Werte, die über einen längeren Zeitraum erhalten bleiben sollen.
Projektweite Variablen
Wenn Sie Werte hinterlegen möchten, die in ihrem gesamten Projekt jederzeit zur Verfügung stehen, deklarieren Sie eine öffentliche Modulvariable mit dem Schlüsselwort Public
:
Option Explicit Public Variable As String
Auf diese Variable können Sie nun auch aus anderen Modulen, Klassen und Formen heraus zugreifen und von dort aus auch die Werte ändern.
Um Ihr Projekt übersichtlich zu gestalten, empfehlen wir, dass Sie projektweite Variablen, wenn möglich, in einem Modul sammeln.
Bitte beachten: Modulweite und projektweite Variablen sollten nur in solchen Fällen eingesetzt werden, in denen sie sinnvoll sind, und nicht, um 'Variablen zu sparen'.
Wenn Variablen über längere Zeiträume und aus mehreren Quellen Werte behalten bzw. beziehen, kann leicht die Übersicht darunter leiden bzw. können sich unerwartete Werte in den Variablen befinden.
Der sinnvolle Einsatz von modulweiten und projektweiten Variablen wäre zum Beispiel für solche Werte, die über einen längeren Zeitraum erhalten bleiben sollen.
Besondere Geltungsbereiche in Klassen und UserFormen
Da UserFormen eine besondere Form von Klassenmodulen sind und sich im Bezug auf Variablen identisch verhalten, werden wir in diesem Abschnitt nicht getrennt auf sie eingehen, sondern wie Klassen behandeln.
Prozedurale und private Klassen-Variablen
Prozedurale Variablen folgen den oben angegebenen Regeln; sie gelten ausschließlich innerhalb der Prozedur, in der sie definiert wurden. Mit Private
deklarierte Klassen-Variablen gelten ebenfalls ausschließlich innerhalb der Klasse bzw. der UserForm.
Öffentliche Klassenvariablen
Mit Public
deklarierte Klassen-Variablen stehen zusätzlich den Instanzen der Klasse zur Verfügung.
Sie können wie Eigenschaften eingesetzt werden, wenn man die Werte ungeprüft entgegennehmen kann und die Vergabe von neuen Werten nicht beeinflussen möchte.
Beispielklasse 'clsVariables':
Option Explicit Public FirstName As String, LastName As String, Phone As String Private strClassVariable As String Public Sub DoSomething() Dim strMyValue As String MsgBox FirstName End Sub
Beispielmodul 'modTest':
Option Explicit Sub Example() Dim myVariables As clsVariables Set myVariables = New clsVariables myVariables.FirstName = "Max" myVariables.LastName = "Muster" myVariables.Phone = "+49 123 4656789" myVariables.DoSomething End Sub
Darstellung im VBA-Editor: Ausschließlich die öffentlichen Variablen und Prozeduren stehen der Instanz myVariables
zur Verfügung:
Übergabeparameter
Wenn einer Prozedur ein Wert übergeben wird, wird dieser nach dem Prozedurnamen innerhalb der runden Klammern angegeben.
Mehrere Parameter werden durch Kommata getrennt.
Private Sub SingleParameter(ByVal lngValue As Long) End Sub Private Sub ListOfParameters(ByVal lngValue As Long, ByVal strValue As String, ByVal dteDate As Date) End Sub
ByVal
Der Geltungsbereich beschränkt sich mit dem Schlüsselwort ByVal
wie bei prozeduralen Variablen auf die Prozedur, der sie übergeben wird.
Private Sub ParameterByVal(ByVal lngValue As Long) ' ... lngValue = lngValue + 1 '.... End Sub Private Sub Test() Dim lngNumber As Long lngNumber = 5 ParametersByVal lngNumber Debug.Print lngNumber ' Der Wert ist immer noch 5 End Sub
Das bedeutet, dass die empfangende Prozedur eine neue Variable mit dem gewünschten Wert erhält. Wenn dieser Wert innerhalb der Prozedur geändert wird, betrifft diese Änderung NICHT die Variable in der absendenden Prozedur.
ByRef
Wird ein Parameter mit dem Schlüsselwort ByRef
übergeben, verhält sich die Variable innerhalb der Prozedur, an der sie übergeben wurde, identisch zu ByVal
.
Aber der Wert wird nicht in einer neuen Variablen übergeben, sondern über eine Referenz auf die aufrufende Variable:
Private Sub ParametersByRef(ByRef lngValue As Long) ' ... lngValue = lngValue + 1 '.... End Sub Private Sub Test() Dim lngNumber As Long lngNumber = 5 ParametersByRef lngNumber Debug.Print lngNumber ' Der Wert ist jetzt 6!!! End Sub
Über diese Referenz erhält also die aufgerufene Prozedur Zugriff auf den Original-Speicherplatz und kann dessen Wert direkt ändern. Dies kann selbstverständlich zu großer Verwirrung führen, wenn Sie nicht mit diesem Verhalten rechnen.
Bitte beachten: Wenn Sie bei einem Parameter keine zusätzliche Angabe machen, wird standardmäßig die Übergabe ByRef
vorgenommen!
Optionale Parameter
Generelles zu optionalen Parametern
Das Schlüsselwort 'Optional' gibt an, dass der beschriebene Parameter optional ist, also nicht zwingend angegeben werden muss.
In der Hilfe und in der Quickinfo (STRG + i) werden optionale Parameter in eckigen Klammern dargestellt.
Bei der 'MsgBox'-Funktion wird dies zum Beispiel deutlich: Der Prompt wird zwingend erwartet, alle weiteren Parameter sind optional und können bei Bedarf weggelassen werden.
MsgBox(Prompt, [Buttons As VbMsgBoxStyle = vbOKOnly], [Title], [HelpFile], [Context]) As VbMsgBoxResult
Bei einer eigenen Prozedur sieht das dann so aus:
Private Sub OptionalParameter(ByVal strNecessary As String, Optional ByVal lngOptional As Long) End Sub
Quickinfo:
OptionalParameter(ByVal strNecessary As String, [ByVal lngOptional As Long])
Sie können für einen optionalen Parameter einen Standardwert vergeben:
Private Sub OptionalParameter(ByVal strNecessary As String, Optional ByVal lngOptional As Long = 3) End Sub
Der Aufruf kann nun wie folgt durchgeführt werden:
OptionalParameter "Hallo"
oder mit zweitem Parameter
OptionalParameter "Hallo", 7
aber niemals
OptionalParameter ' Ganz ohne Parameter OptionalParameter , 7 ' Nur mit Angabe des zweiten Parameters
- Regeln
- Bitte die hier gezeigte Reihenfolge einhalten ('Optional' erscheint vor 'ByVal', 'ByRef' bzw. dem Namen des Parameters).
- Der Standardwert wird nach der Angabe des Datentyps platziert.
- Wichtig: Nach einem optionalen Parameter können ausschließlich weitere optionale Parameter erscheinen!!! Alle benötigten Parameter stehen damit am Anfang der Parameter-Liste, optionale am Ende.
Bitte beachten: Die 'IsMissing'-Funktion soll prüfen, ob einem optionalen Parameter ein Wert übergeben wurde. Dies klappt allerdings nur für Variant-Werte!
Tipp: Wenn Sie prüfen möchten, ob ein optionaler Parameter angegeben wurde, belegen Sie ihn mit einem unwahrscheinlichen oder unmöglichen Wert:
Beispiel: Hier wird der Standardwert für 'lngRoundToDigits' mit einem nicht möglichen Wert '-1' vorbelegt:
Public Function RandomDouble(ByVal dblBottom As Double, ByVal dblTop As Double, Optional ByVal lngRoundToDigits As Long = -1) As Double Randomize RandomDouble = dblBottom + Rnd() * (dblTop - dblBottom) ' Wenn die Funktion ohne Angabe der Anzahl der Nachkommastellen aufgerufen wird, beträgt der Wert weiterhin -1, ' welches nicht möglich ist, denn es gibt keine negativen Nachkommastellen. ' Statt nun also das Ergebnis auf eine Ganzzahl zu runden (welches bei 0 der Fall wäre), kann nun mit einer If-Abfrage das Runden komplett verhindert werden: If lngRoundToDigits >= 0 Then RandomDouble = Round(RandomDouble, lngRoundToDigits) End If End Function Private Sub Test() Debug.Print RandomDouble(0, 5) ' 3,75971466302872 (ungerundeter Wert) Debug.Print RandomDouble(0, 5, 0) ' 4 (auf ganze Zahl gerundet) Debug.Print RandomDouble(0, 5, 5) ' 3,75971 (auf 5 Nachkommastellen gerundet) End Sub
Arbeiten mit Optionalen Parametern
Bei Variant-Parametern können Sie mit der IsMissing-Funktion prüfen, ob der optionale Parameter übergeben wurde:
Public Sub DoSomething(Optional ByVal varWithThis As Variant) If IsMissing(varWithThis) = False Then MsgBox "Der Parameter wurde übergeben!" End If End Sub Private Sub TestDoSomething() DoSomething ' Kein Parameter ... DoSomething "Irgendwas" End Sub
Empfohlen wird jedoch, stattdessen mit dem Leerwert des Parameters oder einem unwahrscheinlichen Vorgabewert zu arbeiten:
Public Sub DoSomething(Optional ByVal strWithThis As String) If strWithThis <> "" Then MsgBox "Der Parameter wurde übergeben!" End If End Sub
Public Sub DoSomething(Optional ByVal lngWithThis As Long = - 43423442) If lngWithThis <> - 43423442 Then MsgBox "Der Parameter wurde übergeben!" End If End Sub
Der Vorteil dieser letzten Beispiele ist, dass Sie nicht ausschließlich mit Variant-Parametern arbeiten müssen, um dann mit 'IsMissing' festzustellen, ob der Parameter verwendet wurde.
Konstanten
Eine Konstante ist ein Speicherort, an dem ein fester Wert hinterlegt werden kann. Der Wert wird bei der Deklaration angegeben und kann danach nicht wieder geändert werden.
Deklaration und Wertzuweisung
Eine Konstante wird mit dem Schlüsselwort Const
deklariert, der Wert wird anschließend mit '=' zugewiesen:
Prozedurale Konstante:
Const strConstant As String = "Konstanter Wert" ' NICHT: Dim Const strConstant As String = "Konstanter Wert"
Alle weiteren Konstanten:
Private Const strConstant As String = "Konstanter Wert" Public Const Constant As String = "Konstanter Wert"
Bitte beachten: Bei konstanten Datumsangaben muss der Datumswert entweder als Zahl oder eindeutiger Datums-String angegeben werden. Eine Umwandlung mit der Funktion CDate() ist nicht möglich!
Const dteEstablished As Date = "1984-03-01" Const dteHired As Date = 36742
Datentypen
Da Konstanten ausschließlich bei der Deklaration den gewünschten Wert erhalten können, können sie ausschließlich natürliche Datentypen enthalten, also keine (Klassen-)Objekte, Types, Collections oder Arrays.
Eine vollständige Liste der in VBA verwendeten Datentypen finden Sie hier: Datentypen
Geltungsbereich und Lebensdauer
Geltungsbereich und Lebensdauer sind identisch zu den bei Variablen beschriebenen Geltungsbereichen und Lebensdauern. Das Schlüsselwort Static
ist jedoch nicht zulässig.