Wenn Sie im voraus nicht wissen können, wie viele Parameter
einer Prozedur oder Funktion übergeben werden sollen, können Sie
ein so genanntes ParamArray
übergeben.
Sub ABC(ParamArray UnbekannteParameter() [As Variant])
Mögliche Aufrufe wären beispielsweise:
ABC 1, 2, 3, 4
ABC
ABC "Meier", "Müller", "Schulz"
ABC Now, Now -1, Now +1
Auf der Seite der Prozedur bzw. Funktion wird das ParamArray etwa
so ausgewertet:
Sub ABC(ParamArray UnbekannteParameter())
Dim l As Long
For l = 0 To UBound(UnbekannteParameter)
' mach was mit dem Element, z.B.:
Debug.Print UnbekannteParameter(l)
Next 'l
End Sub
Im Prinzip stellt eine Parameterdeklaration als ParamArray eine
Übergabe eines Arrays des Datentyps Variant dar, dessen Anzahl der
Elemente ja auch nicht vorher bekannt zu sein braucht. Die
vorstehende Deklaration wäre im Prinzip gleichbedeutend mit:
Sub ABC(Optional Params As Variant)
Und die möglichen Aufrufe, bei gleichen Daten wie oben, sähen
so aus:
ABC Array(1, 2, 3, 4)
ABC Array("Meier", "Müller", "Schulz")
ABC Array(Now, Now -1, Now +1)
Aber auch:
Dim Vars() As Variant
ReDim Vars(10 To 100)
'Füllen des Arrays
ABC Vars
Die Auswertung dieser Deklarations- und Aufrufvariante ist die
gleiche wie beim ParamArray, wobei allerdings die bei einem
beliebigen Array ebenfalls beliebige Untergrenze (LBound)
berücksichtigt werden muss:
Sub ABC(Optional Params As Variant)
Dim l As Long
For l = LBound(Params) To UBound(Params)
' mach was mit dem Element, z.B.:
Debug.Print Params(l)
Next 'l
End Sub
Ganz korrekt ist die Array-Auswertung jedoch nicht. Da hier
Params optional ist, kann es ja vorkommen, dass gar nichts
übergeben wird, wie auch beim ParamArray kein einziger Parameter
übergeben zu werden braucht. Bei der Auswertung des ParamArrays ist
das ohne Belang, denn neben der feststehenden Untergrenze von 0 ist
dann die Obergrenze ( UBound)
gleich -1. Die Auswertungsschleife wird also gar nicht erst
durchlaufen und ohne Laufzeitfehler übersprungen. Wird jedoch bei
der Variante mit dem optionalen Array nichts übergeben, wird ein
Laufzeitfehler ausgelöst. Wir müssen also zusätzlich die
tatsächliche Übergabe prüfen:
Sub ABC(Optional Params As Variant)
Dim l As Long
If Not IsMissing(Params) Then
For l = LBound(Params) To UBound(Params)
' mach was mit dem Element, z.B.:
Debug.Print Params(l)
Next 'l
End If
End Sub
Anzumerken wäre noch, dass ein ParamArray zwar zusätzlich neben
anderen, spezifizierten Parametern übergeben werden kann, aber da
die in einem ParamArray übergebenen Parameter per Definition immer
optional sind, kann es nur am Ende einer Parameterauflistung
auftreten:
Sub ABC(Param1[ As DatenTyp], Param2[ As DatenTyp], _
Param...[ As DatenTyp], _
ParamArray UnbekannteParameter()[ As Variant])
Eine nette Variante wäre, wenn in einem ParamArray einzelne
Werte als auch wiederum Arrays übergeben werden könnten und die
gesamte Datenmenge dennoch wie ein einziges Array ausgewertet werden
würde. Wenn dazu noch die in einem ParamArray enthalten Arrays
wiederum auf gleiche Weise verschachtelt sein könnten, also
wiederum gemischt Arrays und Einzelwerte enthalten könnten... etwa
so:
MixedParamArray 1, Array(2, 3), 4, 5, Array(6, Array(7, 8), 9), 10
Nun, die Lösung ist kein Problem:
Sub MixedParamArray(ParamArray Vars())
Dim l1 As Long
Dim l2 As Long
For l1 = 0 To UBound(Vars)
If IsArray(Vars(l1)) Then
For l2 = LBound(Vars(l1)) To UBound(Vars(l1))
MixedParamArray Vars(l1)(l2)
Next 'l2
Else
' Hier wird jedes (!) Element bearbeitet:
Print Vars(l1)
End If
Next 'l
End Sub
Das Prinzip ist einfach: Wird festgestellt, dass ein Element
selbst ein Array ist, wird dieses Array in einer Unterschleife
durchlaufen. Dabei ruft sich die Prozedur in einem so genannten
"rekursiven" Aufruf für jedes Element dieses Arrays der
Reihe selbst auf und übergibt dieses Element als ersten und
einzigen Parameter. Ist dieses Element selbst wiederum ein Array,
passiert bei diesem Zweitaufruf das gleiche erneut - jedes Element
wird daraufhin geprüft, ob es wieder ein Array ist und entsprechend
behandelt.
Räumen wir nun noch spaßeshalber die Möglichkeit ein, Collections
einzubeziehen:
Sub MixedParamArray(ParamArray Vars())
Dim l1 As Long
Dim l2 As Long
For l1 = 0 To UBound(Vars)
If IsArray(Vars(l1)) Then
For l2 = LBound(Vars(l1)) To UBound(Vars(l1))
MixedParamArray Vars(l1)(l2)
Next 'l2
ElseIf TypeOf Vars(l1) Is Collection Then
For l2 = 1 To Vars(l1).Count
MixedParamArray Vars(l1)(l2)
Next 'l2
Else
' Hier wird jedes (!) Element bearbeitet:
Print Vars(l1)
End If
Next 'l
End Sub

|