Wie stopft man eigentlich ein Array oder eine Collection in ein
PropertyBag-Objekt? Die Lösung zu dieser Fragestellung werden Sie
auf jeden Fall brauchen, wenn ein UserControl oder eine
serialisierbare Klasse (letzteres ab Visual Basic 6)
Daten-Elemente in das PropertyBag-Objekt schreiben soll, deren
Anzahl Sie nicht festlegen können (etwa Listen-Elemente wie bei
einer ListBox) und die als Array oder als Collection vorliegen. Mit
Ausnahme von Byte-Arrays können Sie nämlich weder Arrays noch
Collections direkt in der WriteProperty-Methode des
PropertyBag-Objekts wegschreiben lassen. Es hilft alles nichts - Sie
müssen die betreffenden Elemente alle einzeln wegschreiben und
umgekehrt wieder aus dem PropertyBag-Objekt auslesen.
Auf den ersten Blick mag die Aufgabe trivial erscheinen. Sie
durchlaufen einfach der Reihe nach alle Elemente des Arrays oder der
Collection und vergeben dafür einen einfachen numerischen
Zusatzschlüssel, unter dem Sie das Element dann der
WriteProperty-Methode übergeben:
Private Sub ..._WriteProperties(PropBag As PropertyBag)
Dim l As Long
With PropBag
For l = LBound(MeinArray) To UBound(MeinArray)
.WriteProperty "Test" & l, MeinArray(l)
Next ' l
End With
End Sub
Das Auslesen sollte dann folgendermaßen erfolgen können:
Private Sub ..._ReadProperties(PropBag As PropertyBag)
Dim l As Long
With PropBag
For l = ... ??????????????
Ja, wie viele Elemente sollen nun wieder ausgelesen werden? Okay,
sorgen wir also schon beim Wegschreiben dafür, dass die Anzahl der
Elemente später wieder ermittelt werden kann. Und ehe wir erneut
ins Stolpern geraten, schreiben wir besser Unter- und Obergrenze des
Arrays weg:
Private Sub ..._WriteProperties(PropBag As PropertyBag)
Dim l As Long
With PropBag
.WriteProperty "TestLBound", LBound(MeinArray), 0
.WriteProperty "TestUBound", UBound(MeinArray), 0
For l = LBound(MeinArray) To UBound(MeinArray)
.WriteProperty "Test" & l, MeinArray(l)
Next ' l
End With
End Sub
Jetzt klappt das soweit mit dem Auslesen:
Private Sub ..._ReadProperties(PropBag As PropertyBag)
Dim l As Long
Dim nLBound As Long
Dim nUBound As Long
With PropBag
nLBound = .ReadProperty("TestLBound", 0)
nUbound = .ReadProperty("TestUBound", 0)
ReDim MeinArray(nLBound To nUBound)
For l = nLBound To nUBound
MeinArray(l) = .ReadProperty("Test" & l)
Next ' l
End With
End Sub
Bei einer Collection brauchen Sie jedoch nur die Anzahl zu
berücksichtigen - die Untergrenze einer Collection ist ja immer
1. Das Prinzip auf eine Collection zu übertragen, sollte
eigentlich kein Problem für Sie darstellen, oder? Na gut, ich bin
ja nicht so...
Private Sub ..._WriteProperties(PropBag As PropertyBag)
Dim l As Long
With PropBag
.WriteProperty "TestCount", MeineCollection), 0
For i = 1 To MeineCollection.Count
.WriteProperty "Test" & l, MeineCollection(l)
Next ' l
End With
End Sub
Private Sub ..._ReadProperties(PropBag As PropertyBag)
Dim l As Long
Dim nCount As Long
With PropBag
nCount = .ReadProperty("TestCount", 0)
Set MeineCollection = New Collection
For l = 1 To nCount
MeineCollection.Add .ReadProperty("Test" & l)
Next ' l
End With
End Sub
So weit, so gut, aber... hatte ich nicht geschrieben:
"...auf den ersten Blick trivial..."? Nun, wenn Sie Arrays
einfacher Datentypen oder Collections, die gleichfalls nur Elemente
einfacher Datentypen enthalten, wegschreiben wollen, war es das
tatsächlich schon.
Enthalten Ihre Arrays jedoch Objekte, dann müssen Sie beim
Einlesen noch ein Set hinzufügen (beim Einlesen in eine Collection
erübrigt sich dies ja):
' ...
For l = nLBound To nUBound
Set MeinArray(l) = .ReadProperty("Test" & l)
Next ' l
' ...
Nun sind wir fertig, ja? Jawohl - wenn Sie es so eilig haben, das
gleich auszuprobieren, dann nur zu! Aber schimpfen Sie bitte nicht
auf mich, wenn das hier und da denn doch nicht so glatt über die
Bühne geht. Etwa, weil Ihre Arrays sowohl Objekte als auch Elemente
einfacher Datentypen enthalten. Oder weil womöglich die Elemente
eines Arrays oder einer Collection selbst wieder Arrays oder
Collections sind, die wiederum Arrays und/oder
Collections enthalten können, die wiederum Arrays und/oder
Collections enthalten können, die wiederum Arrays und/oder
Coll...
Überredet - und Sie lesen noch weiter? Fein, dann befassen wir
uns zunächst mit dem ersten Punkt meiner Befürchtungen, dem Mix
aus Objekten und anderen Elementen. Diesen Punkt abzuhaken ist auch
noch recht trivial - das Problem tritt ja auch nur beim Einlesen von
Arrays auf:
Private Sub ..._ReadProperties(PropBag As PropertyBag)
Dim l As Long
Dim nLBound As Long
Dim nUBound As Long
With PropBag
nLBound = .ReadProperty("TestLBound", 0)
nUbound = .ReadProperty("TestUBound", 0)
ReDim MeinArray(nLBound To nUBound)
On Error Resume Next
For l = nLBound To nUBound
Set MeinArray(l) = .ReadProperty("Test" & l)
If Err.Number Then
MeinArray(l) = .ReadProperty("Test" & l)
Err.Clear
End If
Next ' l
End With
End Sub
Richtig kompliziert wird es allerdings, wenn Sie absolut keine
Ahnung haben, was auf das PropertyBag-Objekt zukommen kann: ein
bunter Mix von einfachen Datentypen, Objekten, Arrays und
Collections, verschachtelt bis in unbekannte Tiefen...
Zur Bearbeitung von solchen Verschachtelungen eignet sich am
besten eine so genannte "Rekursion". Das bedeutet hier,
dass sich eine Prozedur nur genau eine Ebene vornimmt und zur
Bearbeitung der nächsttieferliegenden Ebene eine weitere Prozedur
aufruft - und zwar erneut sich selbst.
Das grundsätzliche Problem einer solchen Rekursion ist, dass sie
wissen muss, wann das Weitergeben nach unten ein Ende haben soll.
Anderenfalls könnte sich eine rekursive Prozedur immer weiter
selbst aufrufen, bis in alle Ewigkeit... oder bis der Speicher alle
ist. Bei der Bearbeitung unserer Arrays und Collections brauchen wir
das jedoch nicht zu fürchten, da ein Array definitiv eine
Obergrenze hat und eine Collection auch nur eine feststellbare
Anzahl an Elementen enthalten kann.
Als "Hülle" für die Rekursion dienen uns die beiden
folgenden öffentlichen Prozeduren in einem Standard-Modul:
Public Sub WritePropertiesEx(Item As Variant, Key As String, _
PropBag As PropertyBag)
zWriteItem Key, Item, PropBag
End Sub
Public Sub ReadPropertiesEx(Item As Variant, Key As String, _
PropBag As PropertyBag, Optional IsObj As Boolean)
zReadItem Item, Key, PropBag, IsObj
End Sub
Sie übergeben in beiden Fällen die wegzuschreibende Variable,
den gewünschten Schlüsselnamen und das vorhandene
PropertyBag-Objekt. Der Prozedur ReadPropertiesEx übergeben Sie
zusätzlich noch den Bool'schen Parameter IsObj. Ist der Wert dieses
Parameters nach der Bearbeitung der Prozedur gleich True, wissen
Sie, dass Ihnen im Parameter Item ein Objekt zurückgegeben wird und
Sie bei einer eventuellen weiteren Verwendung die Zuweisung mit Set
vornehmen müssen.
Private Sub ..._WriteProperties(PropBag As PropertyBag)
' ...
WritePropertiesEx MeineVariable, "Test", PropBag
' ...
End Sub
Private Sub ..._ReadProperties(PropBag As PropertyBag)
Dim nIsObject As Boolean
' ...
ReadPropertiesEx MeineVariable, "Test", PropBag
' ...
End Sub
Die beiden Prozeduren rufen nun jeweils das erste (und einzige)
Mal die jeweils zugehörige rekursive Prozedur auf, also zWriteItem
bzw. zReadItem. Schauen wir uns zunächst die Schreib-Prozedur an.
Private Sub zWriteItem(Key As String, Item As Variant, _
PropBag As PropertyBag)
Dim l As Long
Dim nBytes() As Byte
Zuerst wird geprüft, ob im Parameter Item ein Objekt übergeben
worden ist und ob es sich dabei um eine Collection oder um irgend
ein beliebiges Objekt handelt.
With PropBag
If IsObject(Item) Then
If TypeOf Item Is Collection Then
Im Falle einer Collection wird dann zunächst eine spezielle
Kennung in das PropertyBag-Objekt geschrieben, damit sich das
spätere Auslesen vereinfacht und eindeutiger handzuhaben sein wird.
.WriteProperty Key & "VarType", vbCollection, vbVariant
Da wir auch noch andere Kennungen benötigen, die einen
Variablentyp kennzeichnen, und wir dabei die Visual
Basic-Datentyp-Konstanten verwenden werden, erweitern wir die Reihe
der Konstanten. Welchen Wert wir dafür wählen, wäre eigentlich
egal - er dürfte nur nicht mit den VB-eigenen
Variablentyp-Konstanten kollidieren. Zwar ist die VB-Reihe nach oben
hin offen, aber wer weiß, ob da nicht irgendwann noch Werte
hinzukommen werden. Sicherer ist es dagegen, wenn wir die Reihe in
negativer Richtung erweitern. Wir definieren die Konstante im
Deklarationsteil des Moduls:
Private Const vbCollection = -1
Zur weiteren Bearbeitung der Collection dient die spezielle
Prozedur CollWriteProperties, die Sie als öffentliche Prozedur
sogar direkt verwenden können, wenn Sie sicher sein können, dass
das Ausgangselement eine Collection ist.
CollWriteProperties CColl(Item), Key & "_", PropBag
Da der Parameter der Prozedur für die Übergabe der Collection
als Datentyp Collection deklariert ist, stoßen wir hier auf eine
kleine Meuterei des Kompilers. Er verweigert die direkte Annahme des
als Variant übergebenen Collection-Objekts. Wie im Artikel Schnittstellen
"chamäleonieren" gezeigt, behelfen wir uns mit
einer selbstgebauten Konvertierung:
Private Function CColl(Collection As Variant) As Collection
Set CColl = Collection
End Function
Kümmern wir uns zunächst einmal nicht um die Bearbeitung der
Collection, sondern verfolgen wir das weitere Geschehen, falls das
Item-Element keine Collection ist. Die nächste Möglichkeit, die
wir hier berücksichtigen, wäre ein woher auch immer stammendes
weiteres PropertyBag-Objekt. Dieses lässt sich nämlich auch nicht
in ein anderes PropertyBag-Objekt schreiben. Der Umgang damit ist
jedoch einfach. Denn es bietet seinen Inhalt als Byte-Array in der
Eigenschaft Contents an. Wie bereits zu Anfang des Artikels
erwähnt, kann ein Byte-Array problemlos weggeschrieben werden
(weiß der Henker, warum das ausnahmsweise funktioniert). Zur
Kennzeichnung definieren wir eine weitere eigene
Variablentyp-Konstante (wieder im Deklarationsteil des Moduls)
Private Const vbPropertyBag = -2
und schreiben das Byte-Array weg:
ElseIf TypeOf Item Is PropertyBag Then
.WriteProperty Key & "VarType", vbPropertyBag, vbVariant
nBytes = Item.Contents
.WriteProperty Key, nBytes
Ist nun das Item-Element ein beliebiges anderes Objekt, könnte
es an sich, wie Sie es gewohnt sind, direkt in das
PropertyBag-Objekt geschrieben werden. Allerdings haben wir es hier
erneut mit einer Sabotage des Kompilers zu tun, diesmal mit einer
uns stillschweigend und verdeckt untergejubelten Feinheit. Stammt
nämlich das hier ja im Parameter als Variant übergebene
Item-Element von einer Picture-Eigenschaft eines Steuerelemets ab,
wird nicht etwa das Picture-Objekt weggeschrieben, sondern nur der
Long-Wert des Bitmap-Handles (siehe auch: "Wenn
Nichts nicht Nichts ist..."). Vermutlich liegt das
an schier verzweifelten erscheinenden Bemühungen der
VB-Entwickler-Crew, die Kompatibilität zur Picture-Eigenschaft der
Steuerelemente aus den 16-bittigen VB 3-Zeiten
zu wahren - damals enthielt diese nämlich lediglich das
Bitmap-Handle, und zum Objekt wurde sie erst ab VB 4.
Wir behelfen uns wieder mit einer expliziten Typ-Konvertierung.
Vorsorglich belassen wir diese "Explizitität" bei der
allgemeinen Konvertierung in ein Objekt (es könnte ja sein, dass
uns irgend jemand irgendwann noch andere "spinnerte"
Objekte unterzujubeln versucht). Das reicht offensichtlich für
jeden Objekt-Typ aus, und eine eigene Konvertierung in ein Objekt
des Typs StdPicture erübrigt sich somit glücklicherweise.
Private Function CObj(Obj As Variant) As Object
Set CObj = Obj
End Function
Nun können wir also weiter schreiben:
Else
On Error Resume Next
.WriteProperty Key, CObj(Item), Nothing
Doch für alle Fälle gehen wir noch einmal auf Nummer sicher.
Falls sich ein Objekt um keinen Preis serialisieren lassen will,
sind wir diejenigen, die nachgeben (schließlich sind wir ja klüger
als so ein Objekt...) und schreiben statt dessen nur Nothing in das
PropertyBag. Damit wahren wir wenigstens die Konsistenz der Anzahl
der weggeschriebenen Objekte und überlassen es dem die ganze
Geschichte wieder einlesenden Code (den Sie ja schreiben müssen,
und nicht ich...), sich über das Nothing zu wundern und
entsprechend zu reagieren.
If Err.Number Then
.WriteProperty Key, Nothing, Nothing
Err.Clear
End If
End If
Nun sind wir endlich soweit, uns um Arrays kümmern zu können.
ElseIf IsArray(Item) Then
.WriteProperty Key & "LBound", LBound(Item), 0
.WriteProperty Key & "UBound", UBound(Item), 0
Ordentlich, wie wir nun mal sind, schreiben wir auch den
Variablentyp des Arrays in das PropertyBag-Objekt. Denn dann können
wir später auch wieder Arrays des korrekten, ursprünglichen
Datentyps zurückerhalten.
.WriteProperty Key & "VarType", VarType(Item), vbVariant
Nun wie gehabt die Schreibaktion der Array-Elemente in der
bekannten Schleife:
For l = LBound(Item) To UBound(Item)
zWriteItem Key & l, Item(l), PropBag
Next 'l
Doch nicht ganz wie gehabt? Richtig, hier kommt die Rekursion ins
Spiel. Wir übergeben das jeweilige Array-Element einem erneuten
Aufruf der Prozedur zWriteItem (in deren erstem Aufruf wir uns ja
bei dieser Betrachtung nach wie vor befinden) und überlassen es
wiederum dieser, das Element zu prüfen und gegebenenfalls weiter zu
zerpflücken. Ein gutgemeinter Rat: Lesen Sie erst einmal weiter,
ehe Sie den Aufruf der Rekursion weiter verfolgen wollen und dazu
erneut zum Anfang der Beschreibung dieser Prozedur zurückhüpfen.
Die Rekursion lässt sich besser "live" im
Einzelschrit-Modus verfolgen (etwa im Beispiel-Projekt zu diesem
Artikel).
Hatte keine der Prüfungen bis hier hin Erfolg, sollten wir
schließlich annehmen können, dass es sich um ein Item-Element
eines einfachen Datentyps handelt.
Else
Select Case VarType(Item)
Case vbBoolean
.WriteProperty Key, CBool(Item)
Case vbCurrency
.WriteProperty Key, CCur(Item)
Case vbDate
.WriteProperty Key, CDate(Item)
Case vbDouble
.WriteProperty Key, CDbl(Item)
Case vbInteger
.WriteProperty Key, CInt(Item)
Case vbLong
.WriteProperty Key, CLng(Item)
Case vbSingle
.WriteProperty Key, CSng(Item)
Case vbString
.WriteProperty Key, CStr(Item)
Case vbVariant
.WriteProperty Key, Item
Case Else
.WriteProperty Key, vbEmpty
End Select
End If
Je nach Variablentyp des Variant-Item-Elements überführen wir
dieses mit den Cxxx-VB-Funktionen in den entsprechenden
Datentyp. Das ist reine PropertyBag-Routine. Für den Fall der
Fälle, dass kein Datentyp passen sollte, ja noch nicht einmal ein
Variant erkannt und akzeptiert wird, schreiben wir zur
Konsistenzwahrung ein vbEmpty in das PropertyBag-Objekt. Und damit
können wir jetzt die Prozedur abschließen:
End With
End Sub
Kommen wir nun zur Prozedur CollWriteProperties, die sich
speziell um das Wegschreiben einer Collection kümmert. Diese
gleicht wieder der oben bereits beschriebenen einfachen
Routinebehandlung einer Collection. Der Unterschied liegt lediglich
darin, dass auch hier der Variablentyp zusätzlich weggeschrieben
wird, und dass zur Bearbeitung der einzelnen Elemente die gerade
beschriebene rekursive Prozedur zWriteItem verwendet wird.
Public Sub CollWriteProperties(Coll As Collection, _
Key As String, PropBag As PropertyBag)
Dim l As Long
With PropBag
.WriteProperty Key & "VarType", vbCollection, vbVariant
.WriteProperty Key & "Count", Coll.Count, 0
If Coll.Count Then
On Error Resume Next
For l = 1 To Coll.Count
zWriteItem Key & l, Coll(l), PropBag
Next 'l
End If
End With
End Sub
Den Rückwärtsgang des PropertyBag-Objekts legen wir mit der
ebenfalls rekursiv verwendeten Prozedur zReadItem ein.
Private Sub zReadItem(Item As Variant, Key As String, _
PropBag As PropertyBag, IsObj As Boolean)
Dim nItem As Variant
Dim nVarType As Long
Dim l As Long
Dim nLBound As Long
Dim nUBound As Long
Dim nIsObject As Boolean
Dim nArray As Variant
Dim nBytes() As Byte
Wie bereits erwähnt, verfügt sie über den weiteren Parameter
IsObj, der die höherliegende Ebene darüber informiert, dass das in
Item zurückgebebene, ausgelesene Element ein Objekt ist. Damit beim
rekursiven Aufruf nichts schief geht, wird zuallererst der Wert des
Parameters vorsorglich auf False gesetzt.
IsObj = False
Dann versuchen wir anhand des übergebenen Schlüssels den
möglichen Vaiablentyp des Item-Elements auszulesen.
With PropBag
On Error Resume Next
nVarType = .ReadProperty(Key & "VarType", vbVariant)
If Err.Number Then
nVarType = vbVariant
Err.Clear
End If
On Error GoTo 0
Sollte der Variablentyp nicht gelesen werden können (wir haben
ja für einfache Elemente keinen weggeschrieben), nehmen wir einen
Variant-Datentyp an. Eine weitere Differenzierung ist gar nicht
notwendig, da wir ja nur ein Variant-Item im Parameter zurückgeben
können.
Werten wir nun den Variablentyp aus und kümmern wir uns als
erstes um Collections.
Select Case nVarType
Case vbCollection
Set Item = CollReadProperties(Key & "_", PropBag)
IsObj = True
Exit Sub
Auch hier haben wir wieder eine spezialisierte Prozedur zur Hand,
diesmal eine Funktion, die die komplett eingelesene Collection
zurückgibt. Wir setzen den Parameter IsObj gleich True und können
die rekursive Prozedur-Ebene an dieser Stelle bereits verlassen.
Case vbPropertyBag
nBytes = .ReadProperty(Key)
Set Item = New PropertyBag
Item.Contents = nBytes
IsObj = True
Exit Sub
Ähnlich kurz geht das Einlesen eines PropertyBag-Objekts
vonstatten. Wir wissen, dass wir ein Byte-Array einlesen können,
weisen dem Item-Element eine neu angelegte PropertyBag-Instanz zu,
und füllen dessen Inhalt mit dem Byte-Array. IsObj wird wieder
gleich True gesetzt und die Prozedur kann verlassen werden.
Case Else
If Not ((nVarType And vbArray) = vbArray) Then
Nun prüfen wir, ob wir es mit einem Array zu tun haben könnten.
Ist das nicht der Fall, bemühen wir uns (wie bereits bei den
einfachen Einlese-Routinen oben gezeigt), ein einfaches Item-Element
auszulesen. Wir versuchen zuerst ein Objekt auszulesen und vergessen
im Erfolgsfalle nicht, IsObj auf True zu setzen. Geht dieser
Leseversuch schief, lesen wir eben ein gewöhnliches Element ein. In
jedem dieser beiden Fälle verlassen wir danach die Prozedur.
On Error Resume Next
Set Item = .ReadProperty(Key)
If Err.Number = 0 Then
IsObj = True
Else
Item = .ReadProperty(Key, vbEmpty)
End If
Exit Sub
End If
End Select
Haben wir es letztlich mit einem Array zu tun, lesen wir
zunächst die Informationen über das Array aus.
nLBound = .ReadProperty(Key & "LBound", 0)
nUBound = .ReadProperty(Key & "UBound", 0)
Anhand des Variablentyps entscheiden wir nun den Datentyp, für
den das Array dimensioniert werden soll. Da eine alternative
Dimensionierung innerhalb einer Prozedur nicht möglich ist, lagern
wir diese in kleine Hilfsfunktionen aus, die jeweils ein Array des
gewünschten Typs zurückgeben und zugleich die Grenzen festlegen:
Select Case nVarType
Case vbArray Or vbVariant
nArray = zDimArrayVariant(nLBound, nUBound)
Case vbArray Or vbString
nArray = zDimArrayString(nLBound, nUBound)
Case vbArray Or vbBoolean
nArray = zDimArrayBoolean(nLBound, nUBound)
Case vbArray Or vbInteger
nArray = zDimArrayInteger(nLBound, nUBound)
Case vbArray Or vbLong
nArray = zDimArrayLong(nLBound, nUBound)
Case vbArray Or vbSingle
nArray = zDimArraySingle(nLBound, nUBound)
Case vbArray Or vbDouble
nArray = zDimArrayDouble(nLBound, nUBound)
Case vbArray Or vbCurrency
nArray = zDimArrayCurrency(nLBound, nUBound)
Case vbArray Or vbDate
nArray = zDimArrayDate(nLBound, nUBound)
Case vbArray Or vbObject
nArray = zDimArrayObject(nLBound, nUBound)
End Select
Als Beispiel für diese Funktionen zur Dimensionierung mag hier
die String-Variante reichen (im Modul zum Herunterladen sind
natürlich alle Varianten enthalten). Die Funktionen sind alle
gleich und ohne individuelle Besonderheiten aufgebaut:
Private Function zDimArrayString(ByVal LB As Long, _
ByVal UB As Long) As String()
Dim nArray() As String
ReDim nArray(LB To UB)
zDimArrayString = nArray
End Function
Nun marschieren wir durch die Anzahl der Elemente des Arrays.
Auch hier wieder kümmert sich ein rekursiver Aufruf der Prozedur
zReadItem um die einzelnen Elemente. Und je nach dem, was die
Objekt-Anzeige (für diese Ebene heißt sie lokal nIsObject)
anzeigt, wird das von der unteren Ebene zurückgegebene Item-Element
dem jeweiligen Array-Element mit oder ohne Set-Anweisung zugewiesen.
For l = nLBound To nUBound
zReadItem nItem, Key & l, PropBag, nIsObject
If nIsObject Then
Set nArray(l) = nItem
Else
nArray(l) = nItem
End If
Next 'l
End With
Als letztes weisen wir nun noch das Array dem Item-Element zur
Rückgabe an die höhergelegene Ebene zu und beenden die Prozedur.
Item = nArray
End Sub
Auch die spezialisierte Funktion CollReadProperties ist wieder
nach dem bekannten Schema ausgeführt und greift ebenfalls auf den
rekursiven Aufruf von zReadItem zurück.
Public Function CollReadProperties(Key As String, _
PropBag As PropertyBag) As Collection
Dim nCount As Long
Dim l As Long
Dim nColl As Collection
Dim nItem As Variant
Dim nVarType As Long
Dim nIsObject As Boolean
With PropBag
Set nColl = New Collection
On Error Resume Next
nVarType = .ReadProperty(Key & "VarType", vbVariant)
On Error GoTo 0
If nVarType = vbCollection Then
nCount = .ReadProperty(Key & "Count", 0)
If nCount Then
With nColl
For l = 1 To nCount
zReadItem nItem, Key & l, PropBag, nIsObject
.Add nItem
Next 'l
End With
End If
End If
End With
Set CollReadProperties = nColl
End Function
Damit wären wir am Ende der verschachtelten
"Eigenschaften-Schachtel" (PropertyBag mal etwas frei
übersetzt...) angekommen. Sollten Sie immer noch etwas ungläubig
staunen, beweist Ihnen das Beispiel-Projekt zum Herunterladen, dass
die Sache funktionert. Marschieren Sie ruhig einmal im
Einzelschritt-Modus durch das Beispiel und verfolgen Sie die
rekursiven Aufrufe von zWriteItem und zReadItem.
|