Array: Unterschied zwischen den Versionen

Aus VBA-wiki
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
 
(9 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Category:vba-wiki]]
== Arrays kurz vorgestellt ==
== Arrays kurz vorgestellt ==


Zeile 200: Zeile 201:
== 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 206: 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 212: 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('''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
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 ==
Zeile 303: 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 314: 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. 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 Hierbei bitte beachten:
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 326: 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 erweitert werden). ' WICHTIG: Das Trennzeichen darf NICHT Teil eines Elementes des Arrays sein! ' Im Zweifelsfall das Trennzeichen erweitern, wie '|~%§'.</span> strTest = Join(strArray, "|") <span style="Color:green">' Das Trennzeichen wird zusätzlich an Liste vorne und hinten angeheftet:</span> strTest = "|" & strTest & "|" <span style="Color:green">' 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:</span> 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") <span style="Color:green">' Falsch: Teilweise Übereinstimmung wird ignoriert ' Die Liste '|Max Muster|Berta Beispiel|Peter Paulsen|' enthält nicht '|Max|'</span> Debug.Print ArrayContains(strArray, "Max Muster") <span style="Color:green">' Wahr</span> Debug.Print ArrayContains(strArray, "Maxine Musterfrau") <span style="Color:green">' Falsch</span> End Sub
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). 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 waren (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 ReDim strSorted(LBound(strArray) To UBound(strArray)) 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
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(strArray01) ReDim Preserve strArray01(UBound(strArray01) + UBound(strArray02) - LBound(strArray02) + 1) For lngIndex = LBound(strArray02) To UBound(strArray02) lngTargetIndex = lngTargetIndex + 1 strArray01(lngTargetIndex) = strArray02(lngIndex) Next lngIndex AppendArrays = strArray01 ' Erstellt eine Kopie, denn strArray01 wurde per Referenz übernommen (ByRef), ' seine Originaldaten liegen also weiterhin in der aufrufenden Prozedur ' und dürfen entsprechend nicht gelöscht! 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
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