Autor: Peter Haserodt  --- Aus Excel VBA - Gruppe: Tutorials

Felder - Arrays (1) - Einführung und LBound/UBound

Autor: Peter Haserodt - Erstellt: --      - Letzte Revision: --Gruppenthema: 3 Folgen 1 2 3 Sie sind in Folge:1

Felder in VBA - Einführung und LBound/UBound

Der Umgang mit Feldern ist wahrlich viel einfacher, als man gemeinhin glaubt.
Aber was isses denn nun, so ein Feld?

Letztendlich nichts anderes als eine Ansammlung von Variablen, die ich nicht über einen Namen anspreche sondern über Indizes!
Hat der Typ eben was von einfach geredet? Was soll das mit den Indizes?
Ein Index bei einem Feld ist einfach seine numerische Position.
Vereinfachtes Beispiel: Wenn Sie Worksheets(2) schreiben, beziehen Sie sich auf das zweite Arbeitsblatt.
Hier ist der Index 2.

So, und nun lassen Sie uns mit einem Beispiel anfangen, welches gleich anscheinend viele komplizierte Sachen mit sich bringt aber ganz simple ist.
Bevor Sie dieses Beispiel ausführen, bitte ich Sie, erst die 1. Analyse dazu zu lesen.
In einem allgemeinen Modul:
Option Explicit

Public Sub FeldTest1()
Dim fMeinFeld(2) As Long, i As Long
For i = 1 To 2
	fMeinFeld(i) = i + 1
Next i
For i = LBound(fMeinFeld) To UBound(fMeinFeld)
	MsgBox i & " : " & fMeinFeld(i)
Next i
End Sub
1. Analyse:

Betrachten wir uns zuerst den Ausdruck Dim fMeinFeld(2) as Long.
Würden wir die Klammern weglassen, und einfach schreiben:
Dim fMeinFeld as Long
dann hätten Sie keine Probleme damit. Ich hätte in diesem Fall eine Variable mit dem Namen fMeinFeld deklariert, die vom Typ Long ist, also eine Long Zahl aufnehmen kann.

Dadurch, dass wir die Deklaration aber mit () und einer Zahl in den Klammern geschrieben haben, verändert sich unsere Variable zu einem Feld.
Die große Frage ist nun, wieviele Zahlen kann unser Feld aufnehmen, schätzen Sie mal selber ab?
Nun, geschätzt? Dann führen Sie mal die Sub aus, bevor ich weiter erkläre.

Weitere Analyse:

Jetzt wollen wir mal ans Eingemachte gehen, da doch viel Unverständliches/Unbekanntes Ihnen noch um die Ohren fliegt.
Den ersten Teil - die erste For Schleife - können wir noch verstehen - oder?
Wir haben ja nun ein Feld, welches wir über seinen Index ansprechen können. Mit fMeinFeld(i) schreiben wir in das Feld an der i. Position. Als Wert schreiben wir einfach i + 1 hinein, damit wir irgendwas drin stehen haben.

Richtig unverständlich ist aber die zweite Schleife.
Dazu müssen wir etwas ausholen:
Mit der Deklaration fMeinFeld(2) as Long setzen wir nur die Obergrenze fest! Dies sagt nicht wirklich etwas aus, wo die Untergrenze liegt. Kurzum, die Frage ist, ob wir 2 oder 3 Elemente aufnehmen können.

Tatsächlich ist es so, dass wenn wir nicht besondere Vorkehrungen treffen - mehr dazu später, die Untergrenze immer 0 ist.
Mit der Deklaration fMeinFeld(2) sagen wir also primär erstmal:
Dieses Feld hat als höchsten ansprechbaren Index die zwei und als niedrigsten die 0. Somit ist die Frage von oben beantworter, wir können 3 Zahlen in unser Feld aufnehmen.

Die zweite Schleife:

Sieht sehr mystisch aus, oder?
Tatsächlich hätte ich auch schreiben können:
For i = 0 to 2
und es Ihnen etwas leichter machen können, wollte ich aber nicht, da ich von Natur aus gemein bin.
Wir lernen hier gleich zwei Funktionen kennen, die wir bei Feldern immer wieder benötigen.
Diese heißen LBound und UBound.
Und wenn wir diese mal kurz ins Deutsche versuchen zu übersetzen, kapieren wir sie auch sofort:

Bound
steht für Grenze.
Dann haben wir einmal das L davor und einmal das U davor.
L
steht für Lower = Untere und U steht für Upper = Obere

Und schon ist alles Mystische fort wie nix.
Die Schleife heißt also übersetzt : Von der unteren Grenze des Feldes bis zur oberen Grenze des Feldes.
So einfach, wenn man es mal weiß.
Trotzdem habe ich Ihnen noch nicht alles über diese beiden Funktionen verraten, dies kommt später in dem Tutorial.

Und beim Ausführen der Schleife haben Sie ja gesehen, dass es 3 Msg Boxen gab. Und die erste hat als Wert auch 0 zurückgegeben, weil wir ja in der oberen Schleife nur die 1. und 2. Position gefüllt hatten.

Verdaut? Dann kann es ja weitergehen.

Halt, noch eine kleine Zwischenbemerkung:

Bevor bei Ihren weiteren Experimenten irgendetwas schief geht:
Was müssten Sie den machen, wenn Sie z.B. Strings in Ihr tolles Feld aufnehmen wollen.
Nun, dann müssen Sie es nicht als Long sondern als String definieren - aber das haben Sie ja gewußt!



Index Variationen

Wir wollen uns die Indizierung unseres fMeinFeld in Varianten anschauen.
Anstatt von fMeinFeld(2) hätte ich auch schreiben können: fMeinFeld(0 to 2)
Hier kommt mal wieder der berühmte Default zum Vorschein.

Wird also die Untergrenze nicht angegeben, wird automatisch 0 als Untergrenze gesetzt.
Stimmt dies?
In der Regel ja, im Besonderen nein!
Tatsächlich ist dies abhängig von einer zusätzlichen Variante einer Option.
Schreibe ich in einem Modul die Option :
Option Base 1

Dann ist in diesem Modul die Default Untergrenze nicht mehr 0 sondern 1 für meine Deklarierten Felder.

Dies können wir ganz einfach testen.
Nehmen Sie sich ein neues Modul und diesen Code hinein, er wird Ihnen fast bekannt vorkommen:
Option Explicit
Option Base 1

Public Sub FeldTest2()
Dim fMeinFeld(2) As Long, i As Long
For i = 1 To 2
	fMeinFeld(i) = i + 1
Next i
For i = LBound(fMeinFeld) To UBound(fMeinFeld)
	MsgBox i & " : " & fMeinFeld(i)
Next i
End Sub
Wenn Sie den Code ausführen, werden Sie sehen, dass wir nur noch 2 MsgBoxen haben.
Und wir wollen gleich noch einen Gegentest ausführen.
Schreiben Sie in das gleiche Modul:

Public Sub FeldTest3()
Dim fMeinFeld(0 To 2) As Long, i As Long
For i = 1 To 2
	fMeinFeld(i) = i + 1
Next i
For i = LBound(fMeinFeld) To UBound(fMeinFeld)
	MsgBox i & " : " & fMeinFeld(i)
Next i
End Sub
Hier haben wir die Untergrenze explizit deklariert mit 0 to 2 und somit tritt unser Option Base 1 nicht in Kraft!

Untergrenze nicht 0 - Von manchen verachtet aber ...

Dem Theoretiker ist es verhasst, eine andere Untergrenze als 0 zu haben. Mir als Praktiker geht es da etwas anders.
Da selbst VB6 und VBA hier nicht schlüssig sind (es gibt Steuerelemente, deren unterer Index 1 ist und nicht 0, dies hat sich erst in VB.Net geändert) sehe ich das schon differenziert.

Ein Hauptargument ist aber unser Umgang mit Excel. Excel arbeitet nunmal in seinen Bereichen mit 1 Basierten Feldern. Die erste Zeile ist 1 und nicht 0 genauso die 1. Spalte. Dies ist gerade beim einlesen von Ranges in Felder nicht unerheblich. Zwar kann man dies programmtechnisch recht einfach lösen aber manchmal kann man es sich auch einfacher machen, als theoretisch zu arbeiten.
Was ich damit sagen will: Ich persönlich entscheide von Fall zu Fall in Excel VBA, welche Untergrenze ich habe.
Dies mag nicht der ideologisch richtige Weg sein, aber ich pfeife auf die Ideologie.
Entscheiden Sie es selbst für sich
Aber: Ich muss auf jeden Fall darauf hinweisen, dass nicht 0 basierte Felder ein Auslaufmodell sind. Wobei ich mir nicht vorstellen kann, dass in VBA6 sich dies jemals ändert - wie könnte es auch. Sollte sich aber irgendwann in VBA ein VBA.Net durchsetzen, dann sieht das ganz anders aus.



Auf zu neuen Dimensionen

Bisher haben wir langweilig mit eindimensionalen Feldern gearbeitet.
Felder sind aber nicht auf eine Dimension (einen Index) begrenzt, sondern können viele haben.
Gerade in Excel arbeiten wir häufig mit zweidimensionalen Feldern, da unsere Ranges ja auch zweidimensional (Zeile/Spalte) sind.

Und wieder ein simples Beispiel - und wir sehen gleich, was unser LBound und Ubound noch so alles kann:
Option Explicit


Public Sub FeldTest4()
Dim fMeinFeld(2, 3) As Long, i As Long, k As Long
For i = 1 To 2
	For k = 1 To 3
		fMeinFeld(i, k) = i * 100 + k
	Next k
Next i
For i = LBound(fMeinFeld, 1) To UBound(fMeinFeld, 1)
	For k = LBound(fMeinFeld, 2) To UBound(fMeinFeld, 2)
		MsgBox "i=" & i & " " & "k=" & k & " :" & fMeinFeld(i, k)
	Next k
Next i
End Sub
Analyse

Hier haben wir ein zweidimensionales Feld aufgebaut. Sie sollten es eigentlich jetzt schon verstehen.
Mehrere Dimensionen trenne ich durch ein Komma in der Klammer.
(Kleine Zwischenfrage, wieviele Zahlen kann unser Feld aufnehmen?)

Jedes einzele Element meines Feldes spreche ich nun über die zwei Indizes an!
Auch hier habe ich eine vollkommene sinnlose Zahlenzuweisung gemacht, einfach um irgendwas reinzubekommen.
Um dies über Schleifen zu erledigen, benötige ich nun zwei Schleifen, dies sollte aber verständlich sein.

Interessant ist unser LBound und UBound.
Während wir oben noch einfach z.B. LBound(fMeinFeld) benutzt haben, habe ich hier einen anderen Konstrukt.
Ich gebe noch an, auf welche Dimension sich meine LBound Funktion sich beziehen soll.
Übersetzt:
LBound(fMeinFeld,1) : Gib mir die Untergrenze der ersten Dimension.
LBound(fMeinFeld,2) : Gib mir die Untergrenze der zweiten Dimension.

Tatsächlich hätte ich anstatt LBound(fMeinFeld,1) auch LBound(fMeinFeld) schreiben können, da, wenn ich es nicht genau bezeichne, die erste Dimension genommen wird. Aber ich wollte halt mal richtig ordentlich sein. Passiert eh selten genug.

Und weiter?
Wenn Sie nun glauben, dass ich Ihnen Beispiele bis in die fünfte oder achte Dimension liefere, dann haben Sie falsch dimensioniert. Das sollten Sie nun selbst weiter testen können.

Und zum Schluss dieser Einführung:

Ich habe hier immer fMeinFeld benutzt. Dies ist meine ganz persönliche und absolut faule Schreibweise.
D.h., ich setze in meinen Codes in der Regel vor einer Feldvariablen ein kleines f.
Dies wird nicht zur Weiterverwendung empfohlen - aber nur wegen Ihnen ändere ich mein Schreibstil nicht.


Dieses Thema hat weitere Beiträge

Felder - Arrays (1) - Einführung und LBound/UBound
Felder - Arrays (2) - Inhalte
Felder - Arrays (3) - Redim und Redim Preserve

Weitere Artikel der Gruppe: Tutorials Aus Excel VBA
Nach oben
rechte seite