Array: Unterschied zwischen den Versionen
Pwania (Diskussion | Beiträge) |
Pwania (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
(23 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[Category:vba-wiki]] | |||
== Arrays kurz vorgestellt == | == Arrays kurz vorgestellt == | ||
Arrays sind ein- oder mehrdimensionale Datenfelder, in denen beliebig viele 'Zellen' mit Daten eines fom Entwickler vorgegebenen Datentyps untergebracht werden können. | |||
Die Größe eines Arrays (die Anzahl der verfügbaren Speicherplätze) muss vom Entwickler vorgegeben oder ermittelt werden, bevor diese Speicherplätze genutzt werden können. | |||
Arrays sind standardmäßig Null-basierend -- das bedeutet, dass das erste Element den Index 0 besitzt, das zweite Element den Index 1, und das letzte Element den Index Anzahl - 1. | Arrays sind standardmäßig Null-basierend -- das bedeutet, dass das erste Element den Index 0 besitzt, das zweite Element den Index 1, und das letzte Element den Index Anzahl - 1. | ||
Zeile 25: | Zeile 30: | ||
=== Statische Arrays === | === Statische Arrays === | ||
Bei statischen Arrays wird bei der Deklaration festgelegt, wie viele Speicherplätze das Array bereithalten soll. Die Größe des Arrays kann später niemals geändert werden, sie ist statisch. Dim strListWeekdays(6) As String In diesem Beispiel wird das Ausmaß des Arrays fest vorgegeben (0-6). Die Angabe '6' betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden 7 (!) Plätze für Daten reserviert. | Bei statischen Arrays wird bei der Deklaration festgelegt, wie viele Speicherplätze das Array bereithalten soll. | ||
Die Größe des Arrays kann später niemals geändert werden, sie ist statisch. | |||
<span style="Color:blue">Dim </span>strListWeekdays<span style="Color:gray">(6)</span><span style="Color:blue"> As String </span> | |||
In diesem Beispiel wird das Ausmaß des Arrays fest vorgegeben (0-6). | |||
Die Angabe '6' betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden 7 (!) Plätze für Daten reserviert. | |||
=== Dynamische Arrays === | === Dynamische Arrays === | ||
Bei dynamischen Arrays wird '''nicht''' bei der Deklaration festgelegt, wie viele Speicherplätze reserviert werden sollen. Dies ist insbesondere dann nützlich, wenn Sie die Anzahl der benötigten Speicherplätze erst ermitteln müssen. Dim strListOfNames() As String Dynamische Arrays müssen vor ihrer Verwendung mit 'ReDim' dimensioniert werden. Die angegebene Dimension entspricht NICHT der Anzahl der geforderten Elemente, sondern den obersten vergebenen Index. Bei einer Basis von '0' (Null) entspricht dies der Anzahl - 1. lngCount = 5 ReDim strListOfNames(lngCount - 1) Bei diesem Beispiel wird das Ausmaß des Arrays nach Ermittlung der benötigten Größe dimensioniert. Die Angabe '4' (5 - 1) betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden die gewünschten 5 (!) Plätze für Daten reserviert und erhalten die Indizes 0-4. | Bei dynamischen Arrays wird '''nicht''' bei der Deklaration festgelegt, wie viele Speicherplätze reserviert werden sollen. | ||
Dies ist insbesondere dann nützlich, wenn Sie die Anzahl der benötigten Speicherplätze erst ermitteln müssen. | |||
<span style="Color:blue">Dim </span>strListOfNames<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
Dynamische Arrays müssen vor ihrer Verwendung mit 'ReDim' dimensioniert werden. | |||
Die angegebene Dimension entspricht NICHT der Anzahl der geforderten Elemente, sondern den obersten vergebenen Index. Bei einer Basis von '0' (Null) entspricht dies der Anzahl - 1. | |||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">5</span> <span style="Color:blue"> | |||
ReDim </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> | |||
Bei diesem Beispiel wird das Ausmaß des Arrays nach Ermittlung der benötigten Größe dimensioniert. Die Angabe '4' (5 - 1) betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden die gewünschten 5 (!) Plätze für Daten reserviert und erhalten die Indizes 0-4. | |||
=== Dimensionierung mit ReDim === | |||
Wie bei 'Dynamische Arrays' erläutert, dient dieser Befehl dazu, ein dynamisches Array zu dimensionieren: | |||
<span style="Color:blue">Dim </span>strListOfNames<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">5</span> <span style="Color:blue"> | |||
ReDim </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> | |||
Dies kann beliebig oft wiederholt werden: | |||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">15</span> <span style="Color:blue"> | |||
ReDim </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> | |||
<span style="Color:green">'...</span> | |||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">27</span> <span style="Color:blue"> | |||
ReDim </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> | |||
=== Deklaration mit ReDim === | === Deklaration mit ReDim === | ||
'''Bitte beachten Sie folgendes:''' Der Befehl 'ReDim' kann nicht nur ein dynamisches Array neu dimensionieren, sondern zusätzlich auch deklarieren. Dies bedeutet, dass, wenn Sie beim 'ReDim' ein noch nicht mit 'Dim' deklariertes Array angeben, dieses beim 'ReDim' deklariert wird. Dies kann wiederum dazu führen, dass Schreibfehler im Variablennamen bei der 'ReDim'-Anweisung ignoriert werden und eine zweite, falsch geschriebene Variable entsteht: Dim strArray() As String ReDim strAray(2) ' strArray falsch geschrieben (nur ein 'r') strArray(0) = "Peter" ' Erzeugt Fehler, denn strArray wurde noch nicht dimensioniert! Das 'Option Explicit' hat auf dieses Verhalten keinen Einfluss, weil 'ReDim' auch deklarieren kann. | '''Bitte beachten Sie folgendes:''' Der Befehl 'ReDim' kann nicht nur ein dynamisches Array neu dimensionieren, sondern zusätzlich auch deklarieren. Dies bedeutet, dass, wenn Sie beim 'ReDim' ein noch nicht mit 'Dim' deklariertes Array angeben, dieses beim 'ReDim' deklariert wird. Dies kann wiederum dazu führen, dass Schreibfehler im Variablennamen bei der 'ReDim'-Anweisung ignoriert werden und eine zweite, falsch geschriebene Variable entsteht: | ||
<span style="Color:blue">Dim </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String | |||
ReDim </span>strAray<span style="Color:gray">(2)</span> <span style="Color:green">' strArray falsch geschrieben (nur ein 'r') -> ein zweites Array wird erzeugt, 'strAray' </span> | |||
strArray<span style="Color:gray">(0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Peter"</span> <span style="Color:green">' Erzeugt Fehler, denn strArray wurde noch nicht dimensioniert! </span> | |||
Das 'Option Explicit' hat auf dieses Verhalten keinen Einfluss, weil 'ReDim' auch deklarieren kann. | |||
== Die Dimensionen eines Arrays == | |||
Bei der Deklaration eines Arrays (mit Dim bzw. ReDim) wird dieses auch dimensioniert. Mit der Dimensionierung entscheidet der Entwickler, ob das Array sich über eine oder mehrere Dimensionen erstrecken soll. | |||
=== Eindimensionale Arrays === | |||
Eindimensionale Arrays können wir als Listen betrachten, die einer Kette oder Aneinanderreihung von Werten entspricht. | |||
Rot, Grün, Blau | |||
== Die Basis eines Arrays == | == Die Basis eines Arrays == | ||
Zeile 45: | Zeile 106: | ||
=== Eins-basierend === | === Eins-basierend === | ||
In der Regel muss bei Arrays, die nicht Null-basierend sind, bei der Dimensionierung angegeben werden, mit welchem Index das Array beginnen soll. Die Zeile Redim strArray(1 To 3) erzeugt demnach ein Array, dessen erstes Element den Index 1 hat. Der letzte Index beträgt 3, also enthält das Array drei Elemente mit den Indizes 1, 2 und 3. '''Bitte beachten:''' Wenn Sie ein Array aus einem Excel Zellenbereich einlesen, wird automatisch ein Eins-basiertes Array erstellt! '''Aber:''' Funktionen, welche Arrays zum Beispiel aus Listen erstellen (siehe [[#Array_aus_einer_Liste_erzeugen:_Split|Split]]), | In der Regel muss bei Arrays, die nicht Null-basierend sind, bei der Dimensionierung angegeben werden, mit welchem Index das Array beginnen soll. Die Zeile Redim strArray(1 To 3) erzeugt demnach ein Array, dessen erstes Element den Index 1 hat. Der letzte Index beträgt 3, also enthält das Array drei Elemente mit den Indizes 1, 2 und 3. | ||
'''Bitte beachten:''' Wenn Sie ein Array aus einem Excel Zellenbereich einlesen, wird automatisch ein Eins-basiertes Array erstellt! | |||
'''Aber:''' Funktionen, welche Arrays zum Beispiel aus Listen erstellen (siehe [[#Array_aus_einer_Liste_erzeugen:_Split|Split]]), setzen sich über die bestehende Dimensionierung hinweg und erzeugen automatisch ein Null-basierendes Array! | |||
=== Arrays mit frei definiertem Anfangs-Index === | === Arrays mit frei definiertem Anfangs-Index === | ||
Der Index des ersten Elementes eines Arrays kann bei der Dimensionierung frei angegeben werden, solange er kleiner als der Index des letzten Elementes ist: Redim strArray(-12 To 34) | Der Index des ersten Elementes eines Arrays kann bei der Dimensionierung frei angegeben werden, solange er kleiner als der Index des letzten Elementes ist: Redim strArray(-12 To 34) | ||
=== Modulweite Vorgabe mit 'Option Base' === | |||
Zusätzlich zur Festlegung der Basis bei der Dimensionierung von Arrays kann diese mit der Anweisung 'Option Base' auch modulweit vorgegeben werden. Als Wert kann 0 (was ja sowieso schon die Standard-Basis ist) und 1 angegeben werden. Andere Werte werden nicht akzeptiert und verursachen einen Kompilierungsfehler. | |||
Die Anweisung 'Option Base' muss wie 'Option Explicit' am Anfang jedes Modules angegeben werden, in der die Basis vorgegeben werden soll. | |||
Die Einschränkungen von 'Option Base' sind ziemlich restriktiv, weshalb wir von deren Verwendung abraten. | |||
; Vorteile | |||
* Eine modulweite Vorgabe der Basis 1 kann mit 'Option Base 1' erfolgen | |||
* Jedes Array in diesem Modul erhält dann automatisch die Basis 1 statt 0 | |||
* Einzelne Arrays können trotzdem mit einer eigenen Basis beginnen, wenn sie bei der Dimensionierung angegeben wird | |||
<span style="Color:blue"> ReDim </span>strArray<span style="Color:gray">(3</span><span style="Color:blue"> To </span><span style="Color:gray">5)</span><span style="Color:blue"> As String </span> <span style="Color:green">' der Anfangs-Index beträgt 3</span> | |||
; Nachteile | |||
* Um einen durchgängig gültigen Anfangsindex für alle Arrays auf 1 zu setzen, muss die Anweisung 'Option Base 1' in '''allen''' Modulen angegeben werden | |||
* Die Standard-Funktionen zur Erstellung bzw. Befüllung von Arrays (zum Beispiel 'Split') setzen sich über 'Option Base 1' hinweg und verwenden weiterhin die Basis 0! | |||
; Beispiele | |||
<span style="Color:blue">Option Explicit | |||
Option Base </span><span style="Color:gray">0</span> <span style="Color:green">' Standard</span> | |||
<span style="Color:blue"> | |||
Sub </span>ArrayBase<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> ReDim </span>strArray<span style="Color:gray">(5)</span> <span style="Color:green">' Reserviert 6 Plätze mit den Indizes 0, 1, 2, 3, 4, 5</span> | |||
Debug<span style="Color:gray">.</span>Print LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 0</span> | |||
Debug<span style="Color:gray">.</span>Print UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 5</span> | |||
strArray <span style="Color:gray">=</span> Split<span style="Color:gray">("Januar,Juni,Juli",</span> <span style="Color:gray">",")</span> | |||
Debug<span style="Color:gray">.</span>Print LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 0</span> | |||
Debug<span style="Color:gray">.</span>Print UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 2</span> | |||
<span style="Color:blue">End Sub</span> | |||
<span style="Color:blue">Option Explicit | |||
Option Base </span><span style="Color:gray">1</span> <span style="Color:green">' Alle Arrays sollen mit Index 1 beginnen</span> | |||
<span style="Color:blue"> | |||
Sub </span>ArrayBase<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> ReDim </span>strArray<span style="Color:gray">(5)</span> <span style="Color:green">' Reserviert 5 Plätze mit den Indizes 1, 2, 3, 4, 5</span> | |||
Debug<span style="Color:gray">.</span>Print LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 1</span> | |||
Debug<span style="Color:gray">.</span>Print UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 5</span> | |||
<span style="Color:green">' aber: !!</span> | |||
strArray <span style="Color:gray">=</span> Split<span style="Color:gray">("Januar,Juni,Juli",</span> <span style="Color:gray">",")</span> | |||
Debug<span style="Color:gray">.</span>Print LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 0!</span> | |||
Debug<span style="Color:gray">.</span>Print UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> <span style="Color:green">' 2!</span> | |||
<span style="Color:blue">End Sub</span> | |||
== Arrays mit Daten füllen == | == Arrays mit Daten füllen == | ||
Im folgenden Beispiel wird ein dynamisches Array erzeugt, dimensioniert und mit Daten gefüllt: Dim strListOfNames() As String Dim lngCount As Long lngCount = 5 ReDim strListOfNames(lngCount - 1) strListOfNames(0) = "Peter Paulsen" strListOfNames(1) = "Max Mustermann" strListOfNames(2) = "Maxine Musterfrau" strListOfNames(3) = "Kalle Blomquist" strListOfNames(4) = "Emil Tischbein" | Im folgenden Beispiel wird ein dynamisches Array erzeugt, dimensioniert und mit Daten gefüllt: | ||
<span style="Color:blue">Dim </span>strListOfNames<span style="Color:gray">()</span><span style="Color:blue"> As String | |||
Dim </span>lngCount<span style="Color:blue"> As Long </span> | |||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">5</span> <span style="Color:blue"> | |||
ReDim </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> | |||
strListOfNames<span style="Color:gray">(0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Peter Paulsen"</span> | |||
strListOfNames<span style="Color:gray">(1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Max Mustermann"</span> | |||
strListOfNames<span style="Color:gray">(2)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Maxine Musterfrau"</span> | |||
strListOfNames<span style="Color:gray">(3)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Kalle Blomquist"</span> | |||
strListOfNames<span style="Color:gray">(4)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Emil Tischbein"</span> | |||
== Dynamische Arrays nachträglich erweitern == | == Dynamische Arrays nachträglich erweitern == | ||
Bei einer erneuten Dimensionierung beachten Sie bitte, dass Sie den Zusatz 'Preserve' verwenden: lngCount = 7 ' ReDim strListOfNames(lngCount - 1) ' Dimensioniert auf neue Größe, löscht alle Daten ReDim | Bei einer erneuten Dimensionierung beachten Sie bitte, dass Sie den Zusatz 'Preserve' verwenden: | ||
lngCount <span style="Color:gray">=</span> <span style="Color:gray">7</span> | |||
<span style="Color:green">' ReDim strListOfNames(lngCount - 1) ' Dimensioniert auf neue Größe, löscht alle Daten </span> | |||
<span style="Color:blue">ReDim Preserve </span>strListOfNames<span style="Color:gray">(</span>lngCount <span style="Color:gray">-</span> <span style="Color:gray">1)</span> <span style="Color:green">' Preserve behält vorhandene Daten </span> | |||
strListOfNames<span style="Color:gray">(5)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Lotte Reininger"</span> | |||
strListOfNames<span style="Color:gray">(6)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Sandra Bullock"</span> | |||
Also: Wenn das Array eine neue Größe erhalten soll und alle bisherigen Einträge sollen | |||
* gelöscht werden, verwenden Sie '''KEIN''' 'Preserve' | |||
* erhalten bleiben, verwenden Sie 'Preserve' | |||
'''Anmerkung:''' Wenn Sie ein Array nachträglich verkleinern wollen, setzen Sie beim ReDim als Parameter genau wie beschrieben den neuen letzten (kleineren) Index ein. Wenn Sie hierbei 'Preserve' verwenden, werden die nun überflüssigen Einträge trotzdem gelöscht. | |||
== Daten aus einem Array auslesen == | == Daten aus einem Array auslesen == | ||
Die einzelnen Speicherplätze werden mit Angabe des Speicherindexes wieder ausgelesen: Debug.Print strArray(0) ' Gibt das erste Element im Direktbereich aus | Die einzelnen Speicherplätze werden mit Angabe des Speicherindexes wieder ausgelesen: | ||
Debug<span style="Color:gray">.</span>Print strArray<span style="Color:gray">(0)</span> <span style="Color:green">' Gibt das erste Element im Direktbereich aus</span> | |||
== Arrays zurücksetzen: Erase == | == Arrays zurücksetzen: Erase == | ||
Zeile 67: | Zeile 209: | ||
Der 'Erase'-Befehl setzt ein Array zurück. | Der 'Erase'-Befehl setzt ein Array zurück. | ||
* Bei statischen Arrays werden alle Elemente auf den Standardwert gesetzt. | * Bei statischen Arrays werden alle Elemente auf den Standardwert gesetzt. | ||
* Bei dynamischen Arrays werden sämtliche Elemente gelöscht. Erase strArray | * Bei dynamischen Arrays werden sämtliche Elemente gelöscht. | ||
Erase strArray | |||
== Arrays in Prozeduren übergeben und aus Funktionen erhalten == | == Arrays in Prozeduren übergeben und aus Funktionen erhalten == | ||
Zeile 73: | Zeile 217: | ||
=== Arrays als Übergabeparameter === | === Arrays als Übergabeparameter === | ||
Die Übergabe eines Arrays an eine Prozedur erfolgt wie bei der Dim-Anweisung (runde Klammern nach dem Variablennamen). Eine statische Dimensionierung ist hier nicht möglich! '''Bitte beachten:''' Arrays können '''NICHT''' 'ByVal' übergeben werden! Private Sub PrintArrayElements( | Die Übergabe eines Arrays an eine Prozedur erfolgt wie bei der Dim-Anweisung (runde Klammern nach dem Variablennamen). | ||
Eine statische Dimensionierung ist hier nicht möglich! | |||
'''Bitte beachten:''' Arrays können '''NICHT''' 'ByVal' übergeben werden! | |||
<span style="Color:blue">Private Sub </span>PrintArrayElements<span style="Color:gray">(</span><span style="Color:blue">ByRef </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span><span style="Color:gray">)</span> | |||
<span style="Color:blue"> Dim </span>lngLow<span style="Color:blue"> As Long</span><span style="Color:gray">,</span> lngUpper<span style="Color:blue"> As Long</span><span style="Color:gray">,</span> lngIndex<span style="Color:blue"> As Long</span> | |||
lngLow <span style="Color:gray">=</span> LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> | |||
lngUpper <span style="Color:gray">=</span> UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">)</span> | |||
<span style="Color:blue"> For </span>lngIndex <span style="Color:gray">=</span> lngLow<span style="Color:blue"> To </span>lngUpper | |||
Debug<span style="Color:gray">.</span>Print strArray<span style="Color:gray">(</span>lngIndex<span style="Color:gray">)</span> | |||
<span style="Color:blue"> Next </span>lngIndex<span style="Color:blue"> | |||
End Sub</span> | |||
=== Rückgabewert einer Funktion === | === Rückgabewert einer Funktion === | ||
Die runden Klammern werden in diesem Fall '''hinter''' den Datentyp gesetzt. In einer Funktion, welche ein Array zurückgeben soll, müssen Sie ein eigenes Rückgabe-Array innerhalb der Funktion füllen und dieses dann mithilfe des Funktionsnamens übergeben: Private Function LoadData() As String() Dim strReturn() As String ' Rückgabe-Array ReDim strReturn(2) strReturn(0) = "Maren" strReturn(1) = "Monika" strReturn(2) = "Melanie" LoadData = strReturn End Function Private Sub Test() PrintArrayElements LoadData() End Sub '''Bitte beachten:''' Eine Array-Funktion kann ausschließlich dynamisch deklariert werden. Folgendes führt zu einem Kompilierfehler: Private Function LoadData() As String(3) '''Wichtig:''' Wenn Sie ein Array aus einer Funktion in eine Variable übernehmen, darf diese Variable '''nicht''' ein statisches Array sein! Begründung: VBA darf das statische Array nicht beliebig erweitern oder verringern, kann jedoch bei der Funktion, welche ein Array zurückgibt, nicht prüfen, ob es mit der Größe des statisch vorgegebenen Array übereinstimmt. Folgendes klappt daher nicht: Private Sub Test() Dim strData(8) As String strData = LoadData() ' Die LoadData-Funktion gibt ein dynamisches Array zurück :-( PrintArrayElements strData End Sub Siehe auch [[Fehlermeldungen#Keine_Zuweisung_an_Datenfeld_m.C3.B6glich|Fehlermeldungen: Keine Zuweisung an Datenfeld möglich]]! | Die runden Klammern werden in diesem Fall '''hinter''' den Datentyp gesetzt. | ||
In einer Funktion, welche ein Array zurückgeben soll, müssen Sie ein eigenes Rückgabe-Array innerhalb der Funktion füllen und dieses dann mithilfe des Funktionsnamens übergeben: | |||
<span style="Color:blue">Private Function </span>LoadData<span style="Color:gray">()</span><span style="Color:blue"> As </span>String<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strReturn<span style="Color:gray">()</span><span style="Color:blue"> As String </span><span style="Color:green">' Rückgabe-Array</span> | |||
<span style="Color:blue"> ReDim </span>strReturn<span style="Color:gray">(2)</span> | |||
strReturn<span style="Color:gray">(0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Maren"</span> | |||
strReturn<span style="Color:gray">(1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Monika"</span> | |||
strReturn<span style="Color:gray">(2)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Melanie"</span> | |||
LoadData <span style="Color:gray">=</span> strReturn<span style="Color:blue"> | |||
End Function | |||
Private Sub </span>Test<span style="Color:gray">()</span> | |||
PrintArrayElements LoadData<span style="Color:gray">()</span><span style="Color:blue"> | |||
End Sub</span> | |||
'''Bitte beachten:''' Eine Array-Funktion kann ausschließlich dynamisch deklariert werden. Folgendes führt zu einem Kompilierfehler: | |||
<span style="Color:blue">Private Function </span>LoadData<span style="Color:gray">()</span><span style="Color:blue"> As </span>String<span style="Color:gray">(3)</span> | |||
'''Wichtig:''' Wenn Sie ein Array aus einer Funktion in eine Variable übernehmen, darf diese Variable '''nicht''' ein statisches Array sein! | |||
Begründung: VBA darf das statische Array nicht beliebig erweitern oder verringern, kann jedoch bei der Funktion, welche ein Array zurückgibt, nicht prüfen, ob es mit der Größe des statisch vorgegebenen Array übereinstimmt. | |||
Folgendes klappt daher nicht: | |||
<span style="Color:blue">Private Sub </span>Test<span style="Color:gray">()</span> <span style="Color:blue"> | |||
Dim </span>strData<span style="Color:gray">(8)</span><span style="Color:blue"> As String </span> | |||
strData <span style="Color:gray">=</span> LoadData<span style="Color:gray">()</span> <span style="Color:green">' Die LoadData-Funktion gibt ein dynamisches Array zurück :-( </span> | |||
PrintArrayElements strData <span style="Color:blue"> | |||
End Sub </span> | |||
Siehe auch [[Fehlermeldungen#Keine_Zuweisung_an_Datenfeld_m.C3.B6glich|Fehlermeldungen: Keine Zuweisung an Datenfeld möglich]]! | |||
== Mehrdimensionale Arrays == | == Mehrdimensionale Arrays == | ||
Ein eindimensionales Array können wir uns als Liste vorstellen, in der mehrere Einträge untereinander stehen. Ein zweidimensionales Array entspricht dann einer Tabelle, welche wir zeilen- und spaltenweise befüllen und ansprechen können. Ein dreidimensionales Array können wir uns wie einen Quader vorstellen, der aus vielen kleinen Würfeln besteht, welche jeweils Daten enthalten können. Oder als eine Sammlung von Tabellen, welche den Zustand einer Datenmenge zu einem unterschiedlichen Zeitpunkt darstellen (wie Messwerte, welche jedes Jahr in eine neue Tabelle einfließen und somit von Jahr zu Jahr vergleichbar sind). | Ein eindimensionales Array können wir uns als Liste vorstellen, in der mehrere Einträge untereinander stehen. | ||
Ein zweidimensionales Array entspricht dann einer Tabelle, welche wir zeilen- und spaltenweise befüllen und ansprechen können. | |||
Ein dreidimensionales Array können wir uns wie einen Quader vorstellen, der aus vielen kleinen Würfeln besteht, welche jeweils Daten enthalten können. Oder als eine Sammlung von Tabellen, welche den Zustand einer Datenmenge zu einem unterschiedlichen Zeitpunkt darstellen (wie Messwerte, welche jedes Jahr in eine neue Tabelle einfließen und somit von Jahr zu Jahr vergleichbar sind). | |||
=== Mehrdimensionale Arrays deklarieren === | === Mehrdimensionale Arrays deklarieren === | ||
Zeile 87: | Zeile 286: | ||
=== Statisches mehrdimensionales Array === | === Statisches mehrdimensionales Array === | ||
Die Dimensionen werden bei der Deklaration in der runden Klammer angegebene und durch Kommata getrennt: Dim strArrayStatic(3, 5) As String ' Zweidimensionales statisches Array Dim strArrayStatic(3, 5, 2) As String ' Dreidimensionales statisches Array | Die Dimensionen werden bei der Deklaration in der runden Klammer angegebene und durch Kommata getrennt: | ||
<span style="Color:blue">Dim </span>strArrayStatic<span style="Color:gray">(3,</span> <span style="Color:gray">5)</span><span style="Color:blue"> As String </span> <span style="Color:green">' Zweidimensionales statisches Array </span> | |||
<span style="Color:blue">Dim </span>strArrayStatic<span style="Color:gray">(3,</span> <span style="Color:gray">5,</span> <span style="Color:gray">2)</span><span style="Color:blue"> As String </span> <span style="Color:green">' Dreidimensionales statisches Array</span> | |||
=== Dynamisches mehrdimensionales Array === | === Dynamisches mehrdimensionales Array === | ||
Die Deklaration eines dynamischen mehrdimensionalen Arrays erfolgt identisch zur Deklaration eines dynamischen eindimensionalen Arrays: Dim strArrayDynamic() As String Die Angabe der verschiedenen Dimensionen erfolgt dann bei der Dimensionierung mit 'ReDim': ReDim strArrayDynamic(3, 5) ' Zweidimensionales dynamisches Array ReDim strArrayDynamic(3, 5, 2) ' Dreidimensionales dynamisches Array Private Sub TwoDimensionalArray() Dim strRow As String Dim lngRow As Long, lngColumn As Long ' Ein eindimensionales Array entspricht einer Liste ' Ein zweidimesionales Array entspricht einer Tabelle Dim strArrayStatic(3, 5) As String Dim strArrayDynamic() As String ' Deklaration eines dynamischen Arrays wie bei eindimensionalen Arrays ReDim strArrayDynamic(3, 4) ' 4 Zeilen, 5 Spalten strArrayDynamic(0, 0) = "Huhu" strArrayDynamic(0, 1) = "Haha" ' ... strArrayDynamic(2, 3) = "Irgendwo mittendrin" strArrayDynamic(3, 4) = "Ende" For lngRow = LBound(strArrayDynamic, 1) To UBound(strArrayDynamic, 1) For lngColumn = LBound(strArrayDynamic, 2) To UBound(strArrayDynamic, 2) strRow = strRow & "|" & strArrayDynamic(lngRow, lngColumn) & " " Next lngColumn Debug.Print strRow & " |" strRow = "" Next lngRow End Sub '''Wichtig:''' Sie können bei Arrays mit ReDim lediglich die letzte Dimension neu dimensionieren, alle vorangehenden Dimensionen müssen erhalten bleiben! | Die Deklaration eines dynamischen mehrdimensionalen Arrays erfolgt identisch zur Deklaration eines dynamischen eindimensionalen Arrays: | ||
<span style="Color:blue">Dim </span>strArrayDynamic<span style="Color:gray">()</span><span style="Color:blue"> As String </span> | |||
Die Angabe der verschiedenen Dimensionen erfolgt dann bei der Dimensionierung mit 'ReDim': | |||
<span style="Color:blue">ReDim </span>strArrayDynamic<span style="Color:gray">(3,</span> <span style="Color:gray">5)</span> <span style="Color:green">' Zweidimensionales dynamisches Array </span> | |||
<span style="Color:blue">ReDim </span>strArrayDynamic<span style="Color:gray">(3,</span> <span style="Color:gray">5,</span> <span style="Color:gray">2)</span> <span style="Color:green">' Dreidimensionales dynamisches Array </span> | |||
<span style="Color:blue"> | |||
Private Sub </span>TwoDimensionalArray<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strRow<span style="Color:blue"> As String </span> | |||
<span style="Color:blue"> Dim </span>lngRow<span style="Color:blue"> As Long</span><span style="Color:gray">,</span> lngColumn<span style="Color:blue"> As Long </span> | |||
<span style="Color:green">' Ein eindimensionales Array entspricht einer Liste </span> | |||
<span style="Color:green">' Ein zweidimesionales Array entspricht einer Tabelle </span> | |||
<span style="Color:blue"> Dim </span>strArrayStatic<span style="Color:gray">(3,</span> <span style="Color:gray">5)</span><span style="Color:blue"> As String Dim </span>strArrayDynamic<span style="Color:gray">()</span><span style="Color:blue"> As String </span> | |||
<span style="Color:green">' Deklaration eines dynamischen Arrays wie bei eindimensionalen Arrays </span> | |||
<span style="Color:blue"> ReDim </span>strArrayDynamic<span style="Color:gray">(3,</span> <span style="Color:gray">4)</span> <span style="Color:green">' 4 Zeilen, 5 Spalten </span> | |||
strArrayDynamic<span style="Color:gray">(0,</span> <span style="Color:gray">0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Huhu"</span> | |||
strArrayDynamic<span style="Color:gray">(0,</span> <span style="Color:gray">1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Haha"</span> | |||
<span style="Color:green">' ... </span> | |||
strArrayDynamic<span style="Color:gray">(2,</span> <span style="Color:gray">3)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Irgendwo mittendrin"</span> | |||
strArrayDynamic<span style="Color:gray">(3,</span> <span style="Color:gray">4)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Ende"</span> | |||
<span style="Color:blue"> For </span>lngRow <span style="Color:gray">=</span> LBound<span style="Color:gray">(</span>strArrayDynamic<span style="Color:gray">,</span> <span style="Color:gray">1)</span><span style="Color:blue"> To </span>UBound<span style="Color:gray">(</span>strArrayDynamic<span style="Color:gray">,</span> <span style="Color:gray">1)</span> | |||
<span style="Color:blue"> For </span>lngColumn <span style="Color:gray">=</span> LBound<span style="Color:gray">(</span>strArrayDynamic<span style="Color:gray">,</span> <span style="Color:gray">2)</span><span style="Color:blue"> To </span>UBound<span style="Color:gray">(</span>strArrayDynamic<span style="Color:gray">,</span> <span style="Color:gray">2)</span> | |||
strRow <span style="Color:gray">=</span> strRow & <span style="Color:gray">"|"</span> & strArrayDynamic<span style="Color:gray">(</span>lngRow<span style="Color:gray">,</span> lngColumn<span style="Color:gray">)</span> & <span style="Color:gray">" "</span> | |||
<span style="Color:blue"> Next </span>lngColumn | |||
Debug<span style="Color:gray">.</span>Print strRow & <span style="Color:gray">" |"</span> strRow <span style="Color:gray">=</span> <span style="Color:gray">""</span> | |||
<span style="Color:blue"> Next </span>lngRow <span style="Color:blue"> | |||
End Sub </span> | |||
'''Wichtig:''' Sie können bei Arrays mit ReDim lediglich die letzte Dimension neu dimensionieren, alle vorangehenden Dimensionen müssen erhalten bleiben! | |||
== Systemfunktionen für Arrays == | == Systemfunktionen für Arrays == | ||
Zeile 126: | Zeile 359: | ||
=== IsArray === | === IsArray === | ||
Die IsArray-Funktion prüft, ob der Inhalt einer Variablen ein Datenfeld ist. Diese Prüfung ist insbesondere dann sinnvoll, wenn die Variable ein Variant ist und deshalb nicht zwingend ein Array enthalten könnte. Dabei ist es unerheblich, ob das Array schon dimensioniert wurde bzw. Elemente enthält: Dim strText() As String Debug.Print IsArray(strText) ' True == Arrays und Excel Arbeitsblätter== Arrays können verwendet werden, um direkt auf Excel Tabelleninhalte zuzugreifen bzw. diese zu ändern. Dies kann zu deutlichen Verbesserungen der Laufzeit einer Lösung führen, weil dann nicht mehr auf die einzelnen Zellen eines Bereichs zugegriffen werden muss, sondern alle Zugriffe direkt auf den Hauptspeicher erfolgen können. | Die IsArray-Funktion prüft, ob der Inhalt einer Variablen ein Datenfeld ist. | ||
Diese Prüfung ist insbesondere dann sinnvoll, wenn die Variable ein Variant ist und deshalb nicht zwingend ein Array enthalten könnte. | |||
Dabei ist es unerheblich, ob das Array schon dimensioniert wurde bzw. Elemente enthält: | |||
<span style="Color:blue">Dim </span>strText<span style="Color:gray">()</span><span style="Color:blue"> As String </span> | |||
Debug<span style="Color:gray">.</span>Print IsArray<span style="Color:gray">(</span>strText<span style="Color:gray">)</span> <span style="Color:green">' True </span> | |||
== Arrays und Excel Arbeitsblätter== | |||
Arrays können verwendet werden, um direkt auf Excel Tabelleninhalte zuzugreifen bzw. diese zu ändern. | |||
Dies kann zu deutlichen Verbesserungen der Laufzeit einer Lösung führen, weil dann nicht mehr auf die einzelnen Zellen eines Bereichs zugegriffen werden muss, sondern alle Zugriffe direkt auf den Hauptspeicher erfolgen können. | |||
=== Werte aus einem Zellenbereich in ein Array einlesen === | === Werte aus einem Zellenbereich in ein Array einlesen === | ||
Hierzu muss ein Variant-Array verwendet werden, weil Excel in seinen Zellen verschiedene Datentypen aufnehmen kann (Text, Zahlen, Datumsangaben, ...). Es wäre zwar möglich, die Werte aus jeder Zelle einzeln auszulesen und dann in den vom Array erwarteten Datentyp umzuwandeln, dies kann jedoch nicht für ein komplettes Array in einem Schritt erfolgen. Dim varValues() As Variant varValues = Selection.Value ' bzw. varValues = Range("A1:F4").Value Hierbei bitte beachten: | Hierzu muss ein Variant-Array verwendet werden, weil Excel in seinen Zellen verschiedene Datentypen aufnehmen kann (Text, Zahlen, Datumsangaben, ...). | ||
Es wäre zwar möglich, die Werte aus jeder Zelle einzeln auszulesen und dann in den vom Array erwarteten Datentyp umzuwandeln, dies kann jedoch nicht für ein komplettes Array in einem Schritt erfolgen. | |||
<span style="Color:blue">Dim </span>varValues<span style="Color:gray">()</span><span style="Color:blue"> As Variant </span> | |||
varValues <span style="Color:gray">=</span> Selection<span style="Color:gray">.</span>Value <span style="Color:green">' bzw. varValues = Range("A1:F4").Value</span> | |||
Hierbei bitte beachten: | |||
* Die 'Value'-Eigenschaft gibt, obwohl sie in der Einzahl erscheint ('Value', nicht 'Values'!), im Zusammenhang mit einem Zellbereich alle Werte der einzelnen Zellen zurück. | * Die 'Value'-Eigenschaft gibt, obwohl sie in der Einzahl erscheint ('Value', nicht 'Values'!), im Zusammenhang mit einem Zellbereich alle Werte der einzelnen Zellen zurück. | ||
* Das Array wird automatisch von Excel korrekt dimensioniert. | * Das Array wird automatisch von Excel korrekt dimensioniert. | ||
Zeile 137: | Zeile 390: | ||
=== Werte aus einem Array in einen Zellenbereich schreiben === | === Werte aus einem Array in einen Zellenbereich schreiben === | ||
Beim Schreiben von Daten aus einem Array in einen Zellenbereich muss nicht zwingend ein Variant-Array verwendet werden, weil Excel in seine Zellen beliebige Daten aufnehmen kann. Bitte beachten Sie trotzdem, dass, wenn Sie zum Beispiel Zahlenwerte in Excel Zellen schreiben, die als Datumswerte formatiert sind, Excel diese Werte als Datumsangaben darstellt. Das Zellenformat hat immer Vorrang | Beim Schreiben von Daten aus einem Array in einen Zellenbereich muss nicht zwingend ein Variant-Array verwendet werden, weil Excel in seine Zellen beliebige Daten aufnehmen kann. | ||
Bitte beachten Sie trotzdem, dass, wenn Sie zum Beispiel Zahlenwerte in Excel Zellen schreiben, die als Datumswerte formatiert sind, Excel diese Werte als Datumsangaben darstellt. Das Zellenformat hat immer Vorrang! | |||
<span style="Color:blue">Dim </span>strValues<span style="Color:gray">()</span><span style="Color:blue"> As String </span> | |||
<span style="Color:blue"> | |||
ReDim </span>strValues<span style="Color:gray">(1</span><span style="Color:blue"> To </span><span style="Color:gray">3,</span> <span style="Color:gray">1</span><span style="Color:blue"> To </span><span style="Color:gray">5)</span> <span style="Color:green">' Eins-basierend </span> | |||
strValues<span style="Color:gray">(1,</span> <span style="Color:gray">1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Anfang"</span> | |||
strValues<span style="Color:gray">(1,</span> <span style="Color:gray">5)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Oben rechts"</span> | |||
strValues<span style="Color:gray">(2,</span> <span style="Color:gray">3)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Mitte"</span> | |||
strValues<span style="Color:gray">(3,</span> <span style="Color:gray">1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Unten links"</span> | |||
strValues<span style="Color:gray">(3,</span> <span style="Color:gray">5)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Ende"</span> | |||
Range<span style="Color:gray">("A1:E3").</span>Value <span style="Color:gray">=</span> strValues | |||
bzw. Null-basierend: | |||
<span style="Color:blue">Dim </span>strValues<span style="Color:gray">()</span><span style="Color:blue"> As String </span> | |||
<span style="Color:blue"> | |||
ReDim </span>strValues<span style="Color:gray">(2,</span> <span style="Color:gray">4)</span> <span style="Color:green">' Null-basierend </span> | |||
strValues<span style="Color:gray">(0,</span> <span style="Color:gray">0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Anfang"</span> | |||
strValues<span style="Color:gray">(0,</span> <span style="Color:gray">4)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Oben rechts"</span> | |||
strValues<span style="Color:gray">(1,</span> <span style="Color:gray">2)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Mitte"</span> | |||
strValues<span style="Color:gray">(2,</span> <span style="Color:gray">0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Unten links"</span> | |||
strValues<span style="Color:gray">(2,</span> <span style="Color:gray">4)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Ende"</span> | |||
Range<span style="Color:gray">("A1:E3").</span>Value <span style="Color:gray">=</span> strValues <span style="Color:green">' identisches Ergebnis zum Beispiel oben (1-basierend)</span> | |||
Hierbei bitte beachten: | |||
* Das Array, aus dem die Daten stammen, sollte zweidimensional angelegt sein. Die erste Dimension enthält die Zeilen, die zweite die Spalten. | * Das Array, aus dem die Daten stammen, sollte zweidimensional angelegt sein. Die erste Dimension enthält die Zeilen, die zweite die Spalten. | ||
* Die Daten aus einem eindimensionalen Array werden ausschließlich als Daten einer Zeile verstanden. | * Die Daten aus einem eindimensionalen Array werden ausschließlich als Daten einer Zeile verstanden. | ||
Zeile 149: | Zeile 427: | ||
=== ArrayContains: Ist ein Element enthalten? === | === ArrayContains: Ist ein Element enthalten? === | ||
VBA bietet keine eigene Möglichkeit an, zu prüfen, ob ein Element im Array (schon) enthalten ist. Die natürlichste Lösung könnte darin bestehen, mithilfe einer Schleife zu prüfen, ob eines der Elemente dem gesuchten Kriterium entspricht. Dies kann allerdings bei mehrfacher Ausführung bei einem größeren Array sehr zeitraubend sein. Eine effizientere Lösung besteht darin, das Array in eine Liste (Zeichenkette) umzuwandeln und dann nach dem Element zu suchen: Public Function ArrayContains(ByRef strArray() As String, ByVal strFind As String) As Boolean Dim strTest As String <span style="Color:green">' 'Join' wandelt das Array in eine Liste um. ' Als Trennzeichen dient hier das '|'-Symbol (kann beliebig | VBA bietet keine eigene Möglichkeit an, zu prüfen, ob ein Element im Array (schon) enthalten ist. | ||
Die natürlichste Lösung könnte darin bestehen, mithilfe einer Schleife zu prüfen, ob eines der Elemente dem gesuchten Kriterium entspricht. Dies kann allerdings bei mehrfacher Ausführung bei einem größeren Array sehr zeitraubend sein. | |||
Eine effizientere Lösung besteht darin, das Array in eine Liste (Zeichenkette) umzuwandeln und dann nach dem Element zu suchen: | |||
<span style="Color:blue">Public Function </span>ArrayContains<span style="Color:gray">(</span><span style="Color:blue">ByRef </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span><span style="Color:gray">,</span><span style="Color:blue"> ByVal </span>strFind<span style="Color:blue"> As String</span><span style="Color:gray">)</span><span style="Color:blue"> As Boolean</span> | |||
<span style="Color:blue"> Dim </span>strTest<span style="Color:blue"> As String</span> | |||
<span style="Color:green">' 'Join' wandelt das Array in eine Liste um.</span> | |||
<span style="Color:green">' Als Trennzeichen dient hier das '|'-Symbol (kann beliebig angepasst werden).</span> | |||
<span style="Color:green">' WICHTIG: Das Trennzeichen darf NICHT Teil eines Elementes des Arrays sein!</span> | |||
<span style="Color:green">' Im Zweifelsfall das Trennzeichen erweitern, wie '|~%§'.</span> | |||
strTest <span style="Color:gray">=</span> Join<span style="Color:gray">(</span>strArray<span style="Color:gray">,</span> <span style="Color:gray">"|")</span> | |||
<span style="Color:green">' Das Trennzeichen wird zusätzlich an Liste vorne und hinten angeheftet:</span> | |||
strTest <span style="Color:gray">=</span> <span style="Color:gray">"|"</span> & strTest & <span style="Color:gray">"|"</span> | |||
<span style="Color:green">' Nun wird in der Liste nach dem gesuchten Begriff (mit '*' erweitert und ebenfalls</span> | |||
<span style="Color:green">' in Trennzeichen eingehüllt) gesucht.</span> | |||
<span style="Color:green">' Mithilfe der umschließenden Trennzeichen wird sicher gestellt, dass ausschließlich</span> | |||
<span style="Color:green">' komplette Übereinstimmungen gefunden werden:</span> | |||
ArrayContains <span style="Color:gray">=</span> strTest<span style="Color:blue"> Like </span><span style="Color:gray">"*|"</span> & strFind & <span style="Color:gray">"|*"</span><span style="Color:blue"> | |||
End Function | |||
Private Sub </span>Test<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> ReDim </span>strArray<span style="Color:gray">(2)</span> | |||
strArray<span style="Color:gray">(0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Max Muster"</span> | |||
strArray<span style="Color:gray">(1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Berta Beispiel"</span> | |||
strArray<span style="Color:gray">(2)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Peter Paulsen"</span> | |||
Debug<span style="Color:gray">.</span>Print ArrayContains<span style="Color:gray">(</span>strArray<span style="Color:gray">,</span> <span style="Color:gray">"Max")</span> | |||
<span style="Color:green">' Falsch: Teilweise Übereinstimmung wird ignoriert</span> | |||
<span style="Color:green">' Die Liste '|Max Muster|Berta Beispiel|Peter Paulsen|' enthält nicht '|Max|'</span> | |||
Debug<span style="Color:gray">.</span>Print ArrayContains<span style="Color:gray">(</span>strArray<span style="Color:gray">,</span> <span style="Color:gray">"Max Muster")</span> <span style="Color:green">' Wahr</span> | |||
Debug<span style="Color:gray">.</span>Print ArrayContains<span style="Color:gray">(</span>strArray<span style="Color:gray">,</span> <span style="Color:gray">"Maxine Musterfrau")</span> <span style="Color:green">' Falsch</span> | |||
<span style="Color:blue">End Sub</span> | |||
=== Elemente in einem (String-)Array sortieren === | === Elemente in einem (String-)Array sortieren === | ||
Da die einzelnen Elemente in einem Array einen festen Platz haben, erfolgt die Sortierung über ein wiederholtes Austauschen einzelner Elemente mithilfe eines Zwischenspeichers (der Variablen strTemp). | Da die einzelnen Elemente in einem Array einen festen Platz haben, erfolgt die Sortierung über ein wiederholtes Austauschen einzelner Elemente mithilfe eines Zwischenspeichers (der Variablen strTemp). | ||
Wenn festgestellt wird, dass ein Element weiter hinten einsortiert sein sollte, wird der Wert des nächsten Elementes im Zwischenspeicher gelagert, das Element um eine Stelle nach hinten kopiert, und dann der gespeicherte Wert in das Original-Element übernommen. | |||
Dies wird so lange wiederholt, bis keine weiteren Verschiebungen mehr nötig sind (blnWasSorted bleibt wahr). | |||
<span style="Color:blue">Public Function </span>SortStringArray<span style="Color:gray">(</span><span style="Color:blue">ByRef </span>strArray<span style="Color:gray">()</span><span style="Color:blue"> As String</span><span style="Color:gray">)</span><span style="Color:blue"> As </span>String<span style="Color:gray">()</span> | |||
<span style="Color:green">' created 2016-02-22 p.wania</span> | |||
<span style="Color:blue"> Dim </span>strTemp<span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> Dim </span>strSorted<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> Dim </span>lngIndex<span style="Color:blue"> As Long</span> | |||
<span style="Color:blue"> Dim </span>blnWasSorted<span style="Color:blue"> As Boolean</span> | |||
<span style="Color:green">' Da das Original-Array als Referenz übergeben werden muss,</span> | |||
<span style="Color:green">' sollte in einem neuen Array sortiert werden,</span> | |||
<span style="Color:green">' damit das Original erhalten bleibt</span> | |||
strSorted <span style="Color:gray">=</span> strArray | |||
<span style="Color:blue"> Do</span> | |||
blnWasSorted <span style="Color:gray">=</span><span style="Color:blue"> True</span> | |||
<span style="Color:blue"> For </span>lngIndex <span style="Color:gray">=</span> LBound<span style="Color:gray">(</span>strSorted<span style="Color:gray">)</span><span style="Color:blue"> To </span>UBound<span style="Color:gray">(</span>strSorted<span style="Color:gray">)</span> <span style="Color:gray">-</span> <span style="Color:gray">1</span> | |||
<span style="Color:blue"> If </span>strSorted<span style="Color:gray">(</span>lngIndex<span style="Color:gray">)</span> <span style="Color:gray">></span> strSorted<span style="Color:gray">(</span>lngIndex <span style="Color:gray">+</span> <span style="Color:gray">1)</span><span style="Color:blue"> Then</span> | |||
blnWasSorted <span style="Color:gray">=</span><span style="Color:blue"> False</span> | |||
strTemp <span style="Color:gray">=</span> strSorted<span style="Color:gray">(</span>lngIndex<span style="Color:gray">)</span> | |||
strSorted<span style="Color:gray">(</span>lngIndex<span style="Color:gray">)</span> <span style="Color:gray">=</span> strSorted<span style="Color:gray">(</span>lngIndex <span style="Color:gray">+</span> <span style="Color:gray">1)</span> | |||
strSorted<span style="Color:gray">(</span>lngIndex <span style="Color:gray">+</span> <span style="Color:gray">1)</span> <span style="Color:gray">=</span> strTemp | |||
<span style="Color:blue"> End If</span> | |||
<span style="Color:blue"> Next </span>lngIndex | |||
<span style="Color:blue"> Loop Until </span>blnWasSorted <span style="Color:gray">=</span><span style="Color:blue"> True</span> | |||
SortStringArray <span style="Color:gray">=</span> strSorted<span style="Color:blue"> | |||
End Function</span> | |||
(Gutes Beispiel für ByRef und Rückgabewert!!) | |||
=== Arrays zusammenführen (Append) === | === Arrays zusammenführen (Append) === | ||
Function AppendArrays(ByRef strArray01() As String, ByRef strArray02() As String) As String() Dim lngIndex As Long, lngTargetIndex As Long lngTargetIndex = UBound( | Function AppendArrays(ByRef strArray01() As String, ByRef strArray02() As String) As String() | ||
Dim lngIndex As Long, lngTargetIndex As Long | |||
<span style="Color:blue">Function </span>AppendArrays<span style="Color:gray">(</span><span style="Color:blue">ByRef </span>strArray<span style="Color:gray">01()</span><span style="Color:blue"> As String</span><span style="Color:gray">,</span><span style="Color:blue"> ByRef </span>strArray<span style="Color:gray">02()</span><span style="Color:blue"> As String</span><span style="Color:gray">)</span><span style="Color:blue"> As </span>String<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strResult<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
<span style="Color:blue"> Dim </span>lngIndex<span style="Color:blue"> As Long</span><span style="Color:gray">,</span> lngTargetIndex<span style="Color:blue"> As Long</span> | |||
<span style="Color:green">' Erstellt eine Kopie, denn strArray01 wurde per Referenz übernommen (ByRef),</span> | |||
<span style="Color:green">' seine Originaldaten liegen also weiterhin in der aufrufenden Prozedur</span> | |||
<span style="Color:green">' und wurden entsprechend nicht verändert!</span> | |||
strResult <span style="Color:gray">=</span> strArray<span style="Color:gray">01</span> | |||
lngTargetIndex <span style="Color:gray">=</span> UBound<span style="Color:gray">(</span>strResult<span style="Color:gray">)</span> | |||
<span style="Color:blue"> ReDim Preserve </span>strResult<span style="Color:gray">(</span>UBound<span style="Color:gray">(</span>strResult<span style="Color:gray">)</span> <span style="Color:gray">+</span> UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">02)</span> <span style="Color:gray">-</span> LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">02)</span> <span style="Color:gray">+</span> <span style="Color:gray">1)</span> | |||
<span style="Color:blue"> For </span>lngIndex <span style="Color:gray">=</span> LBound<span style="Color:gray">(</span>strArray<span style="Color:gray">02)</span><span style="Color:blue"> To </span>UBound<span style="Color:gray">(</span>strArray<span style="Color:gray">02)</span> | |||
lngTargetIndex <span style="Color:gray">=</span> lngTargetIndex <span style="Color:gray">+</span> <span style="Color:gray">1</span> | |||
strResult<span style="Color:gray">(</span>lngTargetIndex<span style="Color:gray">)</span> <span style="Color:gray">=</span> strArray<span style="Color:gray">02(</span>lngIndex<span style="Color:gray">)</span> | |||
<span style="Color:blue"> Next </span>lngIndex | |||
AppendArrays <span style="Color:gray">=</span> strResult<span style="Color:blue"> | |||
End Function | |||
Sub </span>TestAppendArrays<span style="Color:gray">()</span> | |||
<span style="Color:blue"> Dim </span>strFirst<span style="Color:gray">()</span><span style="Color:blue"> As String</span><span style="Color:gray">,</span> strSecond<span style="Color:gray">()</span><span style="Color:blue"> As String</span> | |||
strFirst <span style="Color:gray">=</span> LoadNames | |||
<span style="Color:blue"> ReDim </span>strSecond<span style="Color:gray">(1)</span> | |||
strSecond<span style="Color:gray">(0)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Katrin"</span> | |||
strSecond<span style="Color:gray">(1)</span> <span style="Color:gray">=</span> <span style="Color:gray">"Stephanie"</span> | |||
strFirst <span style="Color:gray">=</span> AppendArrays<span style="Color:gray">(</span>strFirst<span style="Color:gray">,</span> strSecond<span style="Color:gray">)</span> | |||
<span style="Color:green">' AppendArrays strFirst, strSecond</span> | |||
<span style="Color:blue">End Sub</span> |
Aktuelle Version vom 28. Januar 2023, 00:30 Uhr
Arrays kurz vorgestellt
Arrays sind ein- oder mehrdimensionale Datenfelder, in denen beliebig viele 'Zellen' mit Daten eines fom Entwickler vorgegebenen Datentyps untergebracht werden können.
Die Größe eines Arrays (die Anzahl der verfügbaren Speicherplätze) muss vom Entwickler vorgegeben oder ermittelt werden, bevor diese Speicherplätze genutzt werden können.
Arrays sind standardmäßig Null-basierend -- das bedeutet, dass das erste Element den Index 0 besitzt, das zweite Element den Index 1, und das letzte Element den Index Anzahl - 1.
Die Elemente eines Arrays haben feste Plätze, Sie können also nicht nachträglich ein Element 'dazwischenschieben' (wie es bei einer Collection möglich ist). Sie müssen in einem solchen Fall erst alle darauffolgenden Elemente um einen Platz verschieben, damit das neue Element zwischen diese gesetzt werden kann.
Der Wert eines Speicherplatzes in einem Array kann jederzeit überschrieben werden.
Plätze, welchen keine Werte erhalten, bleiben weiterhin im Datenfeld erhalten.
Alternativen
Alternativ zu einem eindimensionalen Array (also einer Liste) können Sie auch eine Collection verwenden.
Die Collection ist etwas einfacher zu handhaben und oft leichter verständlich (sie ist zum Beispiel 1-basierend).
Ein Großteil der Auflistungen in den Anwendungs-Objekten basieren auf der Collection (zum Beispiel Application.Documents, ActiveDocument.Fields, etc.).
Bitte beachten Sie hierzu den Vergleich zwischen Collection und Array.
Eine Alternative zu mehrdimensionalen Arrays gibt es nicht.
Arrays deklarieren
Statische Arrays
Bei statischen Arrays wird bei der Deklaration festgelegt, wie viele Speicherplätze das Array bereithalten soll.
Die Größe des Arrays kann später niemals geändert werden, sie ist statisch.
Dim strListWeekdays(6) As String
In diesem Beispiel wird das Ausmaß des Arrays fest vorgegeben (0-6).
Die Angabe '6' betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden 7 (!) Plätze für Daten reserviert.
Dynamische Arrays
Bei dynamischen Arrays wird nicht bei der Deklaration festgelegt, wie viele Speicherplätze reserviert werden sollen.
Dies ist insbesondere dann nützlich, wenn Sie die Anzahl der benötigten Speicherplätze erst ermitteln müssen.
Dim strListOfNames() As String
Dynamische Arrays müssen vor ihrer Verwendung mit 'ReDim' dimensioniert werden.
Die angegebene Dimension entspricht NICHT der Anzahl der geforderten Elemente, sondern den obersten vergebenen Index. Bei einer Basis von '0' (Null) entspricht dies der Anzahl - 1.
lngCount = 5 ReDim strListOfNames(lngCount - 1)
Bei diesem Beispiel wird das Ausmaß des Arrays nach Ermittlung der benötigten Größe dimensioniert. Die Angabe '4' (5 - 1) betrifft den Index des letzten Elements, NICHT die Anzahl der Elemente! In diesem Fall werden die gewünschten 5 (!) Plätze für Daten reserviert und erhalten die Indizes 0-4.
Dimensionierung mit ReDim
Wie bei 'Dynamische Arrays' erläutert, dient dieser Befehl dazu, ein dynamisches Array zu dimensionieren:
Dim strListOfNames() As String lngCount = 5 ReDim strListOfNames(lngCount - 1)
Dies kann beliebig oft wiederholt werden:
lngCount = 15 ReDim strListOfNames(lngCount - 1) '... lngCount = 27 ReDim strListOfNames(lngCount - 1)
Deklaration mit ReDim
Bitte beachten Sie folgendes: Der Befehl 'ReDim' kann nicht nur ein dynamisches Array neu dimensionieren, sondern zusätzlich auch deklarieren. Dies bedeutet, dass, wenn Sie beim 'ReDim' ein noch nicht mit 'Dim' deklariertes Array angeben, dieses beim 'ReDim' deklariert wird. Dies kann wiederum dazu führen, dass Schreibfehler im Variablennamen bei der 'ReDim'-Anweisung ignoriert werden und eine zweite, falsch geschriebene Variable entsteht:
Dim strArray() As String ReDim strAray(2) ' strArray falsch geschrieben (nur ein 'r') -> ein zweites Array wird erzeugt, 'strAray' strArray(0) = "Peter" ' Erzeugt Fehler, denn strArray wurde noch nicht dimensioniert!
Das 'Option Explicit' hat auf dieses Verhalten keinen Einfluss, weil 'ReDim' auch deklarieren kann.
Die Dimensionen eines Arrays
Bei der Deklaration eines Arrays (mit Dim bzw. ReDim) wird dieses auch dimensioniert. Mit der Dimensionierung entscheidet der Entwickler, ob das Array sich über eine oder mehrere Dimensionen erstrecken soll.
Eindimensionale Arrays
Eindimensionale Arrays können wir als Listen betrachten, die einer Kette oder Aneinanderreihung von Werten entspricht.
Rot, Grün, Blau
Die Basis eines Arrays
Bitte denken Sie daran, bei Arrays, deren Basis nicht bekannt ist, die 'LBound'-Funktion zu verwenden, um den Index des ersten Elementes zu ermitteln.
Null-basierend
Wie schon besprochen, basieren 'natürliche' Arrays auf Null, das erste Element hat also den Index 0. Wenn Sie keine weitere Angabe bei der Dimensionierung machen bzw. die 'Split'-Funktion verwenden, um ein Array aus einer Liste erzeugen zu lassen, wird automatisch ein Null-basierendes Array erzeugt.
Eins-basierend
In der Regel muss bei Arrays, die nicht Null-basierend sind, bei der Dimensionierung angegeben werden, mit welchem Index das Array beginnen soll. Die Zeile Redim strArray(1 To 3) erzeugt demnach ein Array, dessen erstes Element den Index 1 hat. Der letzte Index beträgt 3, also enthält das Array drei Elemente mit den Indizes 1, 2 und 3.
Bitte beachten: Wenn Sie ein Array aus einem Excel Zellenbereich einlesen, wird automatisch ein Eins-basiertes Array erstellt!
Aber: Funktionen, welche Arrays zum Beispiel aus Listen erstellen (siehe Split), setzen sich über die bestehende Dimensionierung hinweg und erzeugen automatisch ein Null-basierendes Array!
Arrays mit frei definiertem Anfangs-Index
Der Index des ersten Elementes eines Arrays kann bei der Dimensionierung frei angegeben werden, solange er kleiner als der Index des letzten Elementes ist: Redim strArray(-12 To 34)
Modulweite Vorgabe mit 'Option Base'
Zusätzlich zur Festlegung der Basis bei der Dimensionierung von Arrays kann diese mit der Anweisung 'Option Base' auch modulweit vorgegeben werden. Als Wert kann 0 (was ja sowieso schon die Standard-Basis ist) und 1 angegeben werden. Andere Werte werden nicht akzeptiert und verursachen einen Kompilierungsfehler.
Die Anweisung 'Option Base' muss wie 'Option Explicit' am Anfang jedes Modules angegeben werden, in der die Basis vorgegeben werden soll.
Die Einschränkungen von 'Option Base' sind ziemlich restriktiv, weshalb wir von deren Verwendung abraten.
- Vorteile
- Eine modulweite Vorgabe der Basis 1 kann mit 'Option Base 1' erfolgen
- Jedes Array in diesem Modul erhält dann automatisch die Basis 1 statt 0
- Einzelne Arrays können trotzdem mit einer eigenen Basis beginnen, wenn sie bei der Dimensionierung angegeben wird
ReDim strArray(3 To 5) As String ' der Anfangs-Index beträgt 3
- Nachteile
- Um einen durchgängig gültigen Anfangsindex für alle Arrays auf 1 zu setzen, muss die Anweisung 'Option Base 1' in allen Modulen angegeben werden
- Die Standard-Funktionen zur Erstellung bzw. Befüllung von Arrays (zum Beispiel 'Split') setzen sich über 'Option Base 1' hinweg und verwenden weiterhin die Basis 0!
- Beispiele
Option Explicit Option Base 0 ' Standard Sub ArrayBase() Dim strArray() As String ReDim strArray(5) ' Reserviert 6 Plätze mit den Indizes 0, 1, 2, 3, 4, 5 Debug.Print LBound(strArray) ' 0 Debug.Print UBound(strArray) ' 5 strArray = Split("Januar,Juni,Juli", ",") Debug.Print LBound(strArray) ' 0 Debug.Print UBound(strArray) ' 2 End Sub
Option Explicit Option Base 1 ' Alle Arrays sollen mit Index 1 beginnen Sub ArrayBase() Dim strArray() As String ReDim strArray(5) ' Reserviert 5 Plätze mit den Indizes 1, 2, 3, 4, 5 Debug.Print LBound(strArray) ' 1 Debug.Print UBound(strArray) ' 5 ' aber: !! strArray = Split("Januar,Juni,Juli", ",") Debug.Print LBound(strArray) ' 0! Debug.Print UBound(strArray) ' 2! End Sub
Arrays mit Daten füllen
Im folgenden Beispiel wird ein dynamisches Array erzeugt, dimensioniert und mit Daten gefüllt:
Dim strListOfNames() As String Dim lngCount As Long lngCount = 5 ReDim strListOfNames(lngCount - 1) strListOfNames(0) = "Peter Paulsen" strListOfNames(1) = "Max Mustermann" strListOfNames(2) = "Maxine Musterfrau" strListOfNames(3) = "Kalle Blomquist" strListOfNames(4) = "Emil Tischbein"
Dynamische Arrays nachträglich erweitern
Bei einer erneuten Dimensionierung beachten Sie bitte, dass Sie den Zusatz 'Preserve' verwenden:
lngCount = 7 ' ReDim strListOfNames(lngCount - 1) ' Dimensioniert auf neue Größe, löscht alle Daten ReDim Preserve strListOfNames(lngCount - 1) ' Preserve behält vorhandene Daten strListOfNames(5) = "Lotte Reininger" strListOfNames(6) = "Sandra Bullock"
Also: Wenn das Array eine neue Größe erhalten soll und alle bisherigen Einträge sollen
- gelöscht werden, verwenden Sie KEIN 'Preserve'
- erhalten bleiben, verwenden Sie 'Preserve'
Anmerkung: Wenn Sie ein Array nachträglich verkleinern wollen, setzen Sie beim ReDim als Parameter genau wie beschrieben den neuen letzten (kleineren) Index ein. Wenn Sie hierbei 'Preserve' verwenden, werden die nun überflüssigen Einträge trotzdem gelöscht.
Daten aus einem Array auslesen
Die einzelnen Speicherplätze werden mit Angabe des Speicherindexes wieder ausgelesen:
Debug.Print strArray(0) ' Gibt das erste Element im Direktbereich aus
Arrays zurücksetzen: Erase
Der 'Erase'-Befehl setzt ein Array zurück.
- Bei statischen Arrays werden alle Elemente auf den Standardwert gesetzt.
- Bei dynamischen Arrays werden sämtliche Elemente gelöscht.
Erase strArray
Arrays in Prozeduren übergeben und aus Funktionen erhalten
Arrays als Übergabeparameter
Die Übergabe eines Arrays an eine Prozedur erfolgt wie bei der Dim-Anweisung (runde Klammern nach dem Variablennamen).
Eine statische Dimensionierung ist hier nicht möglich!
Bitte beachten: Arrays können NICHT 'ByVal' übergeben werden!
Private Sub PrintArrayElements(ByRef strArray() As String) Dim lngLow As Long, lngUpper As Long, lngIndex As Long lngLow = LBound(strArray) lngUpper = UBound(strArray) For lngIndex = lngLow To lngUpper Debug.Print strArray(lngIndex) Next lngIndex End Sub
Rückgabewert einer Funktion
Die runden Klammern werden in diesem Fall hinter den Datentyp gesetzt.
In einer Funktion, welche ein Array zurückgeben soll, müssen Sie ein eigenes Rückgabe-Array innerhalb der Funktion füllen und dieses dann mithilfe des Funktionsnamens übergeben:
Private Function LoadData() As String() Dim strReturn() As String ' Rückgabe-Array ReDim strReturn(2) strReturn(0) = "Maren" strReturn(1) = "Monika" strReturn(2) = "Melanie" LoadData = strReturn End Function Private Sub Test() PrintArrayElements LoadData() End Sub
Bitte beachten: Eine Array-Funktion kann ausschließlich dynamisch deklariert werden. Folgendes führt zu einem Kompilierfehler:
Private Function LoadData() As String(3)
Wichtig: Wenn Sie ein Array aus einer Funktion in eine Variable übernehmen, darf diese Variable nicht ein statisches Array sein!
Begründung: VBA darf das statische Array nicht beliebig erweitern oder verringern, kann jedoch bei der Funktion, welche ein Array zurückgibt, nicht prüfen, ob es mit der Größe des statisch vorgegebenen Array übereinstimmt.
Folgendes klappt daher nicht:
Private Sub Test() Dim strData(8) As String strData = LoadData() ' Die LoadData-Funktion gibt ein dynamisches Array zurück :-( PrintArrayElements strData End Sub
Siehe auch Fehlermeldungen: Keine Zuweisung an Datenfeld möglich!
Mehrdimensionale Arrays
Ein eindimensionales Array können wir uns als Liste vorstellen, in der mehrere Einträge untereinander stehen.
Ein zweidimensionales Array entspricht dann einer Tabelle, welche wir zeilen- und spaltenweise befüllen und ansprechen können.
Ein dreidimensionales Array können wir uns wie einen Quader vorstellen, der aus vielen kleinen Würfeln besteht, welche jeweils Daten enthalten können. Oder als eine Sammlung von Tabellen, welche den Zustand einer Datenmenge zu einem unterschiedlichen Zeitpunkt darstellen (wie Messwerte, welche jedes Jahr in eine neue Tabelle einfließen und somit von Jahr zu Jahr vergleichbar sind).
Mehrdimensionale Arrays deklarieren
Statisches mehrdimensionales Array
Die Dimensionen werden bei der Deklaration in der runden Klammer angegebene und durch Kommata getrennt:
Dim strArrayStatic(3, 5) As String ' Zweidimensionales statisches Array Dim strArrayStatic(3, 5, 2) As String ' Dreidimensionales statisches Array
Dynamisches mehrdimensionales Array
Die Deklaration eines dynamischen mehrdimensionalen Arrays erfolgt identisch zur Deklaration eines dynamischen eindimensionalen Arrays:
Dim strArrayDynamic() As String
Die Angabe der verschiedenen Dimensionen erfolgt dann bei der Dimensionierung mit 'ReDim':
ReDim strArrayDynamic(3, 5) ' Zweidimensionales dynamisches Array ReDim strArrayDynamic(3, 5, 2) ' Dreidimensionales dynamisches Array Private Sub TwoDimensionalArray() Dim strRow As String Dim lngRow As Long, lngColumn As Long ' Ein eindimensionales Array entspricht einer Liste ' Ein zweidimesionales Array entspricht einer Tabelle Dim strArrayStatic(3, 5) As String Dim strArrayDynamic() As String ' Deklaration eines dynamischen Arrays wie bei eindimensionalen Arrays ReDim strArrayDynamic(3, 4) ' 4 Zeilen, 5 Spalten strArrayDynamic(0, 0) = "Huhu" strArrayDynamic(0, 1) = "Haha" ' ... strArrayDynamic(2, 3) = "Irgendwo mittendrin" strArrayDynamic(3, 4) = "Ende" For lngRow = LBound(strArrayDynamic, 1) To UBound(strArrayDynamic, 1) For lngColumn = LBound(strArrayDynamic, 2) To UBound(strArrayDynamic, 2) strRow = strRow & "|" & strArrayDynamic(lngRow, lngColumn) & " " Next lngColumn Debug.Print strRow & " |" strRow = "" Next lngRow End Sub
Wichtig: Sie können bei Arrays mit ReDim lediglich die letzte Dimension neu dimensionieren, alle vorangehenden Dimensionen müssen erhalten bleiben!
Systemfunktionen für Arrays
Array aus einzelnen Werten erstellen: Array
Die Array-Funktion erstellt einen Variant-Array aus den beliebig vielen übergebenen Werten. varArray = Array("Peter", "Paul", "Jonas", "Leon", "Brigitte", "Leonie", "Sandra", "Katrin") Unterschiede zur Split-Funktion:
- Die Array-Funktion kann keine Liste von Elementen entgegennehmen, Elemente müssen getrennt übergeben werden.
- Die Array-Funktion kann ausschließlich auf Arrays, welche vom Datentyp Variant sind, angewendet werden.
- Die Array-Funktion kann auch Zahlen, Datumsangaben etc. entgegennehmen.
Array aus einer Liste erzeugen: Split
Erzeugt aus einer Liste mit Werten ein Array. Das Trennzeichen kann angegeben werden (Standard: Leerzeichen). strArray = Split("Peter,Paul,Jonas,Leon,Brigitte,Leonie,Sandra,Katrin", ",") Die Split-Funktion arbeitet ausschließlich mit Zeichenketten. Arrays vom Typ Long können daher zum Beispiel nicht mit der Split-Funktion befüllt werden! lngArray = Split("10 20 30", " ") ' Fehlermeldung: Typen unverträglich!
Array in eine Liste umwandeln: Join
Erzeugt eine Liste aus einem Array mit Werten. Das Trennzeichen kann angegeben werden (Standard: Leerzeichen). strList = Join(strArray, vbCrLf)
Elemente herausfiltern: Filter
Erzeugt ein neues (String) Array, welches nur die Elemente enthält, welche die gesuchte Zeichenkette enthalten.
strArray = Split("Peter, Paul, Jonas, Leon, Brigitte, Leonie, Sandra, Katrin", ", ") strArray = Filter(strArray, "on") Debug.Print Join(strArray, ", ") ' Jonas, Leon, Leonie
Oder ein Array, welches nur die Elemente enthält, welche nicht die gesuchte Zeichenkette enthalten.
strArray = Split("Peter, Paul, Jonas, Leon, Brigitte, Leonie, Sandra, Katrin", ", ") strArray = Filter(strArray, "on", False) Debug.Print Join(strArray, ", ") ' Peter, Paul, Brigitte, Sandra, Katrin
IsArray
Die IsArray-Funktion prüft, ob der Inhalt einer Variablen ein Datenfeld ist.
Diese Prüfung ist insbesondere dann sinnvoll, wenn die Variable ein Variant ist und deshalb nicht zwingend ein Array enthalten könnte.
Dabei ist es unerheblich, ob das Array schon dimensioniert wurde bzw. Elemente enthält:
Dim strText() As String Debug.Print IsArray(strText) ' True
Arrays und Excel Arbeitsblätter
Arrays können verwendet werden, um direkt auf Excel Tabelleninhalte zuzugreifen bzw. diese zu ändern.
Dies kann zu deutlichen Verbesserungen der Laufzeit einer Lösung führen, weil dann nicht mehr auf die einzelnen Zellen eines Bereichs zugegriffen werden muss, sondern alle Zugriffe direkt auf den Hauptspeicher erfolgen können.
Werte aus einem Zellenbereich in ein Array einlesen
Hierzu muss ein Variant-Array verwendet werden, weil Excel in seinen Zellen verschiedene Datentypen aufnehmen kann (Text, Zahlen, Datumsangaben, ...).
Es wäre zwar möglich, die Werte aus jeder Zelle einzeln auszulesen und dann in den vom Array erwarteten Datentyp umzuwandeln, dies kann jedoch nicht für ein komplettes Array in einem Schritt erfolgen.
Dim varValues() As Variant varValues = Selection.Value ' bzw. varValues = Range("A1:F4").Value
Hierbei bitte beachten:
- Die 'Value'-Eigenschaft gibt, obwohl sie in der Einzahl erscheint ('Value', nicht 'Values'!), im Zusammenhang mit einem Zellbereich alle Werte der einzelnen Zellen zurück.
- Das Array wird automatisch von Excel korrekt dimensioniert.
- Das Array wird nicht Null-basierend, sondern Eins-basierend sein (der unterste Index ist die 1)!
Werte aus einem Array in einen Zellenbereich schreiben
Beim Schreiben von Daten aus einem Array in einen Zellenbereich muss nicht zwingend ein Variant-Array verwendet werden, weil Excel in seine Zellen beliebige Daten aufnehmen kann.
Bitte beachten Sie trotzdem, dass, wenn Sie zum Beispiel Zahlenwerte in Excel Zellen schreiben, die als Datumswerte formatiert sind, Excel diese Werte als Datumsangaben darstellt. Das Zellenformat hat immer Vorrang!
Dim strValues() As String ReDim strValues(1 To 3, 1 To 5) ' Eins-basierend strValues(1, 1) = "Anfang" strValues(1, 5) = "Oben rechts" strValues(2, 3) = "Mitte" strValues(3, 1) = "Unten links" strValues(3, 5) = "Ende" Range("A1:E3").Value = strValues
bzw. Null-basierend:
Dim strValues() As String ReDim strValues(2, 4) ' Null-basierend strValues(0, 0) = "Anfang" strValues(0, 4) = "Oben rechts" strValues(1, 2) = "Mitte" strValues(2, 0) = "Unten links" strValues(2, 4) = "Ende" Range("A1:E3").Value = strValues ' identisches Ergebnis zum Beispiel oben (1-basierend)
Hierbei bitte beachten:
- Das Array, aus dem die Daten stammen, sollte zweidimensional angelegt sein. Die erste Dimension enthält die Zeilen, die zweite die Spalten.
- Die Daten aus einem eindimensionalen Array werden ausschließlich als Daten einer Zeile verstanden.
- Wenn Sie die Werte aus einem eindimensionalen Array übernehmen, werden sie in die erste Zeile des Zellenbereichs übernommen.
- Wenn der Zellenbereich eine Spalte statt einer Zeile umfasst, wird nur der erste Wert übernommen un in den weiteren Zeilen wiederholt.
- Beim Schreiben der Werte aus einem Array ist die Basis (0 oder 1) unerheblich (siehe beide Varianten des Beispiels).
- Wichtig: Achten Sie darauf, dass der Bereich, in welchen die Daten geschrieben werden sollen, korrekt dimensioniert ist. Wenn Sie ihn zum Beispiel zu groß wählen, können in den überflüssigen Zellen Fehler angezeigt werden.
Eigene Lösungen für Arrays
ArrayContains: Ist ein Element enthalten?
VBA bietet keine eigene Möglichkeit an, zu prüfen, ob ein Element im Array (schon) enthalten ist.
Die natürlichste Lösung könnte darin bestehen, mithilfe einer Schleife zu prüfen, ob eines der Elemente dem gesuchten Kriterium entspricht. Dies kann allerdings bei mehrfacher Ausführung bei einem größeren Array sehr zeitraubend sein.
Eine effizientere Lösung besteht darin, das Array in eine Liste (Zeichenkette) umzuwandeln und dann nach dem Element zu suchen:
Public Function ArrayContains(ByRef strArray() As String, ByVal strFind As String) As Boolean Dim strTest As String ' 'Join' wandelt das Array in eine Liste um. ' Als Trennzeichen dient hier das '|'-Symbol (kann beliebig angepasst werden). ' WICHTIG: Das Trennzeichen darf NICHT Teil eines Elementes des Arrays sein! ' Im Zweifelsfall das Trennzeichen erweitern, wie '|~%§'. strTest = Join(strArray, "|") ' Das Trennzeichen wird zusätzlich an Liste vorne und hinten angeheftet: strTest = "|" & strTest & "|" ' Nun wird in der Liste nach dem gesuchten Begriff (mit '*' erweitert und ebenfalls ' in Trennzeichen eingehüllt) gesucht. ' Mithilfe der umschließenden Trennzeichen wird sicher gestellt, dass ausschließlich ' komplette Übereinstimmungen gefunden werden: ArrayContains = strTest Like "*|" & strFind & "|*" End Function Private Sub Test() Dim strArray() As String ReDim strArray(2) strArray(0) = "Max Muster" strArray(1) = "Berta Beispiel" strArray(2) = "Peter Paulsen" Debug.Print ArrayContains(strArray, "Max") ' Falsch: Teilweise Übereinstimmung wird ignoriert ' Die Liste '|Max Muster|Berta Beispiel|Peter Paulsen|' enthält nicht '|Max|' Debug.Print ArrayContains(strArray, "Max Muster") ' Wahr Debug.Print ArrayContains(strArray, "Maxine Musterfrau") ' Falsch End Sub
Elemente in einem (String-)Array sortieren
Da die einzelnen Elemente in einem Array einen festen Platz haben, erfolgt die Sortierung über ein wiederholtes Austauschen einzelner Elemente mithilfe eines Zwischenspeichers (der Variablen strTemp).
Wenn festgestellt wird, dass ein Element weiter hinten einsortiert sein sollte, wird der Wert des nächsten Elementes im Zwischenspeicher gelagert, das Element um eine Stelle nach hinten kopiert, und dann der gespeicherte Wert in das Original-Element übernommen.
Dies wird so lange wiederholt, bis keine weiteren Verschiebungen mehr nötig sind (blnWasSorted bleibt wahr).
Public Function SortStringArray(ByRef strArray() As String) As String() ' created 2016-02-22 p.wania Dim strTemp As String Dim strSorted() As String Dim lngIndex As Long Dim blnWasSorted As Boolean ' Da das Original-Array als Referenz übergeben werden muss, ' sollte in einem neuen Array sortiert werden, ' damit das Original erhalten bleibt strSorted = strArray Do blnWasSorted = True For lngIndex = LBound(strSorted) To UBound(strSorted) - 1 If strSorted(lngIndex) > strSorted(lngIndex + 1) Then blnWasSorted = False strTemp = strSorted(lngIndex) strSorted(lngIndex) = strSorted(lngIndex + 1) strSorted(lngIndex + 1) = strTemp End If Next lngIndex Loop Until blnWasSorted = True SortStringArray = strSorted End Function
(Gutes Beispiel für ByRef und Rückgabewert!!)
Arrays zusammenführen (Append)
Function AppendArrays(ByRef strArray01() As String, ByRef strArray02() As String) As String() Dim lngIndex As Long, lngTargetIndex As Long
Function AppendArrays(ByRef strArray01() As String, ByRef strArray02() As String) As String() Dim strResult() As String Dim lngIndex As Long, lngTargetIndex As Long ' Erstellt eine Kopie, denn strArray01 wurde per Referenz übernommen (ByRef), ' seine Originaldaten liegen also weiterhin in der aufrufenden Prozedur ' und wurden entsprechend nicht verändert! strResult = strArray01 lngTargetIndex = UBound(strResult) ReDim Preserve strResult(UBound(strResult) + UBound(strArray02) - LBound(strArray02) + 1) For lngIndex = LBound(strArray02) To UBound(strArray02) lngTargetIndex = lngTargetIndex + 1 strResult(lngTargetIndex) = strArray02(lngIndex) Next lngIndex AppendArrays = strResult End Function Sub TestAppendArrays() Dim strFirst() As String, strSecond() As String strFirst = LoadNames ReDim strSecond(1) strSecond(0) = "Katrin" strSecond(1) = "Stephanie" strFirst = AppendArrays(strFirst, strSecond) ' AppendArrays strFirst, strSecond End Sub