Eine Variable des Datentyps Variant kann alles sein, aber welcher Datentyp steckt in der Variant-Variablen nun eigentlich drin? Kontext In dem Artikel EXCEL 2010 VBA: Datentyp einer Variant-Variablen bestimmen - TypeName() wird eine Möglichkeit erläutert, wie man den Datentyp einer Variant-Varialben ermitteln kann. Da es viele Wege nach Rom gibt, wird hier die weitere Möglichkeit vorgestellt, das mit VarType() zu realisieren. Aufgabenstellung An die SUMMEn-Funktion von EXCEL kann eine beliebige Anzahl von Parametern übergeben werden und die Parameter können von unterschiedlichem Typ sein. In der Regel werden an eine Summenfunktion Range-Objekte (also Bereiche aus der Tabelle) oder Werte übergeben. Um was es sich handelt, muss also von der SUMMEn-Funktion selbst herausgefunden werden. In diesem Beispiel wird die Summen-Funktion nachempfunden, die Funktion hört auf den Namen MeineSumme. Wie bei der Originalfunktion von EXCEL, der Funktion SUMME, kann eine beliebige Anzahl von Parametern unterschiedlichen Datentyps übergeben werden. Für die Summenfunktion ist das wichtig, gilt es doch, auf ein Range-Objekt, das übergeben wird, anders zu reagieren als auf Zahlenwerte, die der Funktion mitgegeben werden. Dann muss noch geklärt werden, ob es sich wirklich um eine Zahl handelt, die man auch summieren kann. Hier die beispielhafte Aufgabenstellung auf einem EXCEL-Arbeitsblatt: 1 / 7
In Funktion EXCEL diesem - Das Die SUMME "MeineSumme" Fälschung: Original: Beispiel verwendet: werden =SUMME(A2:B3;B5;C5:C7;D9;B11:D11;C13) =MeineSumme(A2:B3;B5;C5:C7;D9;B11:D11;C13) aufsummiert. die Grün markierten Als Kontrollrechnung Bereiche und wird Zellen die Standardfunktion der selbstgeschriebenen von Bestimmung des Inhalts eine Variablen des Datentyps Variant mit der Funktion "TypeName()" Um die vollständige Funktionsweise der Funktion "MeineSumme" nachzuvollziehen, lesen Sie bitte den Artikel Die Verwendung von ParamArray. In der folgenden Beschreibung geht es nur um die Typbestimmung des Inhaltes einer Variant-Variablen. Die folgenden Erläuterungen beziehen sich auf den blau dargestellten Programmcode. 2 / 7
An die Funktion MeineSumme wird eine unbestimmte Anzahl an Parametern übergeben, der Empfänger der Parameter ist die Variable vbereich(), die als Variant typisiert ist. In dieser Variablen vbereich() können also Inhalte unterschiedlichen Typs stecken. Im Übergabeparameter vbereich() können somit alle möglichen Werte als auch Range-Objekte stecken, also gilt es, alle Range-Objekte von vbereich() herauszufiltern, die in der Funktion SummeRange() weiterverarbeitet werden. Diese zentrale Aufgabe übernimmt die VBA-Funktion VarType(). Steckt man eine Variable in VarType(), kommt als Rückgabeparameter ein Integer-Wert zurück, der den Typ der übergebenen Variablen charakterisiert. Dabei kann man als Entwickler auf die folgenden VBA-Konstenten reagieren, die bereits vordefiniert sind. Konstante Wert Beschreibung vbempty 0 Empty (nicht initialisiert) vbnull 1 Null (kein gültiger Dateninhalt) vbinteger 2 Integer vblong 3 Long integer vbsingle 4 Single-Variable vbdouble 5 Double-Variable vbcurrency 6 Währung vbdate 7 Datumswert vbstring 8 Zeichenkette vbobject 9 Objekt vberror 10 Fehlerwert vbboolean 11 Boolean vbvariant 12 Variant-Variable vbdataobject 13 Datenobjekt (in Zusammenhang mit Access) vbdecimal 14 Dezimal-Wert vbbyte 17 Byte-Wert vbuserdefinedtype 36 Anwenderdefinierter Variablentyp vbarray 8192 Array 3 / 7
Dies Analyse des Inhalts wird in der Select Case-Struktur vorgenommen. Je nachdem, was Typ ename() als Ergebnis zurückgibt, wird in unterschiedliche Vorgehensweisen verzweigt. Handelt es sich um einen Zahlenwert, wird die Zahl in der Variablen dsumme aufsummiert, handelt es sich um das Objekt Range, wird die Auswertung des Inhalts von Range in einer weiteren Funktion verarbeitet (die übrigens auch wieder den Ihnalt der einzelnen Range-Werte entsprechend des Typs untersucht). Man kann die Fallunterscheidung auch mit If.. Then.. Else bewerkstelligen, Select.. Case finde ich jedoch übersichtlicher. Nun folgt noch der Programmcode... Function MeineSumme(ParamArray vbereich() As Variant) As Double Dim lanzahleintraege As Long Dim lzaehleranzahleintraege As Long Dim dsumme As Double lanzahleintraege = UBound(vBereich()) ' Die Anzahl der übergebenen Parameter wird bestimmt ' ACHTUNG: da VBA die Indizierung bei 0 beginnt, kommt als Wert ' Anzahl-der-Einträge - 1 heraus, also bei 6 Elementen 5 4 / 7
dsumme = 0 ' Wert Initialisieren, ist eigentlich in VBA bei erstmaliger Verwendung nicht notwendig, ' aber eine alte Gewohnheit For lzaehleranzahleintraege = 0 To lanzahleintraege ' Hier werden die Werte in den einzelnen Ranges aufsummiert Select Case VarType(vBereich(lZaehlerAnzahlEintraege)) Case 8204:' Das Resultat 8.204 entspricht einem Range-Objekt dsumme = dsumme + SummeRange(vBereich(lZaehlerAnzahlEintraege)) Case Else: If IsNumeric(vBereich(lZaehlerAnzahlEintraege)) Then ' Prüfung, ob es sich um einen numerischen Wert handelt dsumme = dsumme + vbereich(lzaehleranzahleintraege) End If End Select Next lzaehleranzahleintraege MeineSumme = dsumme End Function Der Vollständige Programmcode Option Explicit Function SummeRange(ByVal vbereich As Range) As Double Dim lzeilen As Long 5 / 7
Dim lspalten As Long Dim lzaehlerzeilen As Long Dim lzaehlerspalten As Long Dim dsumme As Double lzeilen = vbereich.rows.count ' Die Anzahl Zeilen werden bestimmt lspalten = vbereich.columns.count ' Die Anzahl Spalten werden bestimmt dsumme = 0 ' Wert Initialisieren, ist eigentlich in VBA bei erstmaliger Verwendung nicht notwendig, ' aber eine alte Gewohnheit For lzaehlerzeilen = 1 To lzeilen ' Hier werden die Werte in den einzelnen Zellen aufsummiert For lzaehlerspalten = 1 To lspalten If IsNumeric(vBereich.Cells(lZaehlerZeilen, lzaehlerspalten).value) Then ' Prüfung, ob es sich ' um einen numerischen Wert handelt dsumme = dsumme + vbereich.cells(lzaehlerzeilen, lzaehlerspalten).value End If Next lzaehlerspalten Next lzaehlerzeilen SummeRange = dsumme End Function Function MeineSumme(ParamArray vbereich() As Variant) As Double Dim lanzahleintraege As Long Dim lzaehleranzahleintraege As Long Dim dsumme As Double lanzahleintraege = UBound(vBereich()) ' Die Anzahl der übergebenen Parameter wird bestimmt ' ACHTUNG: da VBA die Indizierung bei 0 beginnt, kommt als Wert ' Anzahl-der-Einträge - 1 heraus, also bei 6 Elementen 5 dsumme = 0 ' Wert Initialisieren, ist eigentlich in VBA bei erstmaliger Verwendung nicht 6 / 7
notwendig, ' aber eine alte Gewohnheit For lzaehleranzahleintraege = 0 To lanzahleintraege ' Hier werden die Werte in den einzelnen Ranges aufsummiert Select Case VarType(vBereich(lZaehlerAnzahlEintraege)) Case 8204: ' Das Resultat 8.204 entspricht einem Range-Objekt dsumme = dsumme + SummeRange(vBereich(lZaehlerAnzahlEintraege)) Case Else: If IsNumeric(vBereich(lZaehlerAnzahlEintraege)) Then ' Prüfung, ob es sich um einen numerischen Wert handelt dsumme = dsumme + vbereich(lzaehleranzahleintraege) End If End Select Next lzaehleranzahleintraege MeineSumme = dsumme End Function Schlussbetrachtung Auch dieses Beispiel können Sie sich herunterladen. Bitte beachten Sie auch den Folgenden Artikel: EXCEL 2010 VBA: Datentyp einer Variant-Variablen bestimmen - TypeName() 7 / 7