Home > Artikel > Ausgabe 6/2015 > Datentypen konvertieren unter VBA

Datentypen konvertieren unter VBA

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Ohne Variablen kommt fast keine Programmiersprache aus. Variablen wiederum sind an bestimmte Datentypen gebunden, die die Programmiersprache vorgibt. Die Anforderung, den Wert einer Variablen in den einer anderen Variablen unterschiedlichen Typs zu überführen, stellt sich über die Parameter von Funktionen häufig. Was es dabei zu beachten gibt, beleuchten wir in diesem Beitrag.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1506_Konvertierungen.accdb

Datentypen unter VBA

Imgrunde müssten Sie sich unter VBA keine Gedanken über Dateitypen machen. Denn der Standarddatentyp ist hier der Variant. Wenn in den Modulen Ihrer Datenbank kein Option Explicit im Modulkopf steht, so nimmt VBA für jede Variable automatisch an, dass es sich um einen Variant handelt. Sie brauchen die Variablen dann weder über Dim-Anweisungen zu deklarieren, noch ihren Datentyp vorzubestimmen. VBA versucht dann intern selbst, den Datentyp zu erraten. Denn ein Variant ist natürlich kein wirklicher Datentyp, sondern eine Kapselung von allen erdenklichen Typen. Ob Text, Zahl, Datum oder Objekt, alle können im Variant unterkommen, ohne dass dem Programmierer bewusst wird, was hier im Hintergrund geschieht.

VBA leitet aus der Wertzuweisung ab, um welchen Typ es sich handeln dürfte. Bei

sText = "ACCESS BASICS"

ist durch die Anführungszeichen deutlich gemacht, dass es sich um einen String handelt. VBA speichert den Text nun als Variant, der intern ein Kennzeichen enthält, welches mit dem Marker für einen String versehen wird. Die eigentlichen Daten werden je nach Typ in einer bestimmten Datenstruktur abgelegt, über die man ebenfalls nichts erfährt. Ein Zeiger auf die Struktur macht den Variant vollständig.

Nicht immer ist die Sache jedoch so eindeutig. Nehmen Sie etwa diese Wertzuweisung:

Dim A As Variant

A = 123

Was nimmt VBA hier als Datentyp an? Dass es sich um eine Zahl handelt, ist nicht schwer zu erraten. Doch liegt hier ein Long-Wert vor, ein Integer, oder ein Double-Wert?

Sie sind nicht auf Spekulationen angewiesen, denn die Funktion TypeName von VBA kann Auskunft darüber geben, wie VBA die Variable sieht:

Debug.Print TypeName ( A)

> "Integer"

Hoffentlich liegt es hier richtig! Denn folgende Formel könnte zu einem Fehler wegen Überlaufs führen:

A = A * A * A

Debug.Print A, TypeName(A)

Eine Fehlermeldung tritt jedoch nicht auf. Das Ergebnis wird korrekt angezeigt, und der Datentyp ist auf Long gewechselt. Ähnlich verhält es sich mit

Debug.Print TypeName (A / 3)

> "Double"

Aber auch dies ist möglich:

A = "123"

Debug.Print TypeName (A)

A = A / 3

Debug.Print TypeName (A)

> "String"

"Double"

Obwohl hier VBA zunächst einen String annimmt, stolpert es im nächsten Schritt über den Teilungsoperator und verwandelt deshalb schnell den Datentyp in Double, um die Berechnung durchführen zu können.

Anderes Beispiel:

A = 123

Debug.Print TypeName(A)

A = A & "ACCESS"

Debug.Print A, TypeName(A)

> "Integer"

"String"

Durch den Verknüpfungsoperator & für Strings errät VBA, dass das Ergebnis ebenfalls ein String sein muss, weshalb der Wert der Integer-Variablen A intern zunächst in einen String umgewandelt und schließlich der hartkodierte Text angefügt wird.

VBA scheint also ziemlich intelligent zu sein, wenn es um das Erraten der benötigten Datentypen geht. Das geht auch solange gut, wie Sie lediglich die VBA-Bibliothek selbst benutzen. Sobald Sie aber auch andere Bibliotheken verwenden, etwa die Datenzugriffsbibliothek DAO, ist VBA häufig überfordert.

Denn bei der Zuweisung eines Variablenwerts etwa zum Feldinhalt einer Tabelle weiß VBA unter Umständen nichts über den Datentyp, den Sie beim Entwurf der Tabelle für das Feld vorsahen. Hier kann es zu Fehlern wegen nicht übereinstimmender Datentypen kommen, oder zu Fehlern durch Überläufe.

Option Explicit

Um solche undurchsichtigen Fehler zu vermeiden, setzen Sie besser in den Modulkopf jedes Ihrer Module ein Option Explicit. Das weist VBA an, jede im Programmcode auftauchende Variable zu überprüfen und deren Deklaration zu suchen. Findet es keine, so tritt beim Kompilieren eine entsprechende Fehlermeldung auf. Das manuelle Einsetzen der Option-Explicit-Anweisung können Sie sich sparen, wenn Sie in den Optionen von VBA (Menü Extras) den Eintrag Variablendeklaration erforderlich aktivieren (siehe Bild 1). Dann nämlich setzt VBA beim Neuanlegen eines Moduls die Anweisung automatisch in den Modulkopf.

Optionen von VBA: Einschalten der Notwendigkeit für Variablendatentypen

Bild 1: Optionen von VBA: Einschalten der Notwendigkeit für Variablendatentypen

Die Variablendeklarationen können Sie, je nach deren Gültigkeitsbereich, in den Modulkopf setzen, oder in die einzelnen Funktionsroutinen. Die Stelle spielt dabei keine Rolle. Eine Dim-Anweisung kann auch irgendwo mitten im Funktionstext stehen.

Die Schlüsselwörter für die Deklarationen lauten Dim, Private, Public, Friend und Static. Static ist nur innerhalb von Routinen erlaubt, Public, Friend und Private nur im Modulkopf.

Neben dem Namen der Variablen ist zusätzlich deren Datentyp anzugeben:

Dim A As Long

A = 123

Ganz stimmt das allerdings nicht, denn auch ein schnödes

Dim A

ist möglich. In diesem Fall nimmt VBA für A aber den Typ Variant an. Die Typbezeichnung lässt sich auch durch ein Kürzel ersetzen:

Dim A$

etwa deklariert die Variable als String. Die Kürzel im Überblick:

& String (Text)

% Integer (16bit-Integer)

& Long (32bit-Integer)

^ LongLong (64bit-Integer;

        nur unter Office 64 verfügbar)

# Double (Fließkomma, genau)

! Single (Fließkomma, einfach)

@ Currency (Währung)

Diese Kürzel machen den Programmcode allerdings schlecht lesbar.

Das strikte Erfordernis zur Variablendeklaration führt nun natürlich dazu, dass die Beispiele von oben nicht mehr alle funktionieren. Ist die Variable A als Long deklariert, so kann ihr natürlich kein durch Division zustande gekommener Double-Wert mehr zugewiesen werden. Die interne beim Variant von VBA vorgenommene Konversion schränkt sich damit ein, ist aber nicht außer Kraft gesetzt. Denn dies etwa geht nach wie vor fehlerfrei über die Bühne:

Dim A As Integer

Dim B As Long

B = 123

A = B

VBA weiß hier über beide Datentypen Bescheid, überprüft die Werte der Variablen und kann dann den einen Wert erfolgreich in den anderen überführen, solange der Bereich nicht überläuft, was beim Long-Wert 123 der nicht der Fall ist.

Wenn man sich auf die eingebaute Intelligenz von VBA aber nicht verlassen will, dann gibt einen ganzen Satz von Konvertierungsfunktionen, die die Bibliothek VBA bereithält.

VBA-Conversion

Rufen Sie den Objektkatalog im VBA-Editor auf, setzen die Combobox links oben auf die Bibliothek VBA und markieren die Klasse Conversion. Rechts werden Ihnen nun sämtliche Konvertierungsmethoden aufgelistet (Bild 2). Die reinen Konvertierfunktionen beginnen alle mit dem Präfix C. Angehängt daran ist ein Kürzel für den Ergebnisdatentyp der Funktion. CBool etwa hat als Ergebnis einen Boolean-Wert, CLng einen Long und CDate ein Datum.

Der VBA-Objektkatalog mit der für Konvertierungen zuständigen VBA-Klasse Conversion

Bild 2: Der VBA-Objektkatalog mit der für Konvertierungen zuständigen VBA-Klasse Conversion

Als Parameter kann diesen Funktionen grundsätzlich ein beliebiger Datentyp verabreicht werden. Der übergebene Parameter hat also den Typ Variant. Was VBA ohne Option Explicit intern macht, führen diese Funktionen dabei dezidiert aus.

Das Beispiel zum Verketten des Werts einer Long-Variablen mit einem Text müsste nun so geschrieben werden:

Dim A As Long

Dim B As String

A = 123

B = "ACCESS"

B = B & CStr(A)

CStr macht aus der Zahl 123 in A einen String "123", und dieser kann dann an die String-Variable B angehängt werden.

Beleuchten wir im Folgenden, was es mit den einzelnen Funktionen der Bibliothek auf sich hat.

Konvertierungsfunktionen in VBA-Routinen

Im Modul mdlConverter der Beispieldatenbank finden Sie etliche Funktionen, die wiederum die angesprochenen C-Funktionen von VBA verwenden. Listing 1 zeigt diese im Ausschnitt für die Konvertierung von Werten in Boolean- oder Byte-Werte. Alle weiteren Funktionen des Moduls sind ähnlich aufgebaut.

Function fBool(ByVal Value As Variant) As Boolean

     fBool = CBool(Value)

     Debug.Print TypeName(Value) & " > " & TypeName(fBool)

End Function

Function fByte(ByVal Value As Variant) As Byte

     fByte = CByte(Value)

     Debug.Print TypeName(Value) & " > " & TypeName(fByte)

End Function

Listing 1: Umwandeln von Werten in Boolean- oder Byte-Werte

Der Rückgabetyp der fBool-Funktion ist Boolean. Damit dieser Rückgabewert gesetzt werden kann, muss der als Variant übergebene Parameter Value über die CBool-Methode dezidiert umgewandelt werden. Die zweite Zeile gibt die Eingangs- und Ausgangsdatentypen im VBA-Direktfenster aus.

fByte vollzieht das Gleiche, nur wird hier in den Typ Byte gewandelt.

Interessant ist nun, was die Funktionen aus beliebigen Parameterwerten machen. Übergeben Sie fBool etwa die Zahl 1, so resultiert ein Wahr. Bei 0 folgt ein Falsch. Rufen Sie sie mit "ACCESS" als Parameter auf, dann weiß VBA nicht weiter und zeitigt eine Fehlermeldung wegen falschen Datentyps. Strings sind also verboten? Nein, denn ein "123" wird anstandslos in ein Wahr verwandelt, weil VBA hier eine Zahl im String erkennt. CBool kann also beliebige Zahlentypen verarbeiten und gibt immer dann ein Wahr aus, wenn der Wert von 0 abweicht.

Listing 2 zeigt drei Funktionen, die Werte in den Typ Integer umwandeln können. Zum Einsatz kommen können hier neben der Standardfunktion CInt nämlich auch noch die Methoden Int und Fix. Das Ergebnis unterscheidet sich allerdings je nach übergebenem Parameterwert. Rufen Sie die Hilfe zu VBA auf, indem Sie eine der Funktionen im Code markieren und F1 drücken. Die etwas diffizilen Erläuterungen zu den Unterschieden der Umwandlung brauchen an dieser Stelle nicht wiederholt zu werden.

Function fInt(ByVal Value As Variant) As Integer

     fInt = CInt(Value)

     Debug.Print TypeName(Value) & " > " & TypeName(fInt)

End Function

Function fInt2(ByVal Value As Variant) As Long

     fInt2 = Int(Value)

     Debug.Print TypeName(Value) & " > " & TypeName(fInt2)

End Function

Function fInt3(ByVal Value As Variant) As Long

     fInt3 = Fix(Value)

     Debug.Print TypeName(Value) & " > " & TypeName(fInt3)

End Function

Listing 2: Umwandeln von Werten in Integer-Werte

Einige der weiteren Routinen im Modul sind selbsterklärend. Experimentieren Sie einfach mit den übergebenen Parametern und den Rückgaben, um sich ein Bild von der Funktionsweise der C-Funktionen zu machen. Eingehendere Betrachtung sollte aber die Routine fVal erfahren (Listing 3).

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!