User Tools

Site Tools


vba:classes:iterator:index

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
vba:classes:iterator:index [03.03.2014 14:16:30]
yaslaw vba:classes:iterator renamed to vba:classes:iterator:index
vba:classes:iterator:index [04.09.2019 11:44:31] (current)
yaslaw
Line 1: Line 1:
 +<​const>​
 +    version=2.12.3
 +    vdate=04.09.2019
 +    fname=iterator.cls
 +    ns=%NAMESPACE%
 +    fpath=/​vba/​classes
 +</​const>​
 ====== [VBA] Iterator ====== ====== [VBA] Iterator ======
-{{:vba:classes:​iterator.cls|Download Iterator.cls}}+//Eine Iterator-Klasse um die verschiedenen Listenmöglichkeiten (Array, Collection, Dictioary etc.) alle gleich handhaben zu können// 
 +==Version %%version%% %%vdate%%== 
 + 
 +<WRAP round download 50%> 
 +><fc #​808080>//​Das Modul hat versteckte Attribute. Damit diese aktiv übernommen werden reicht es nicht aus, den Code in ein neues Modul zu kopieren. Man muss das Modul aus der Datei nach VBA importieren.//</​fc>​ 
 +>{{popup>:vba:vba_importfile.png|Bild zum Import}} 
 + 
 +{{..%%fname%%|Download %%fname%% (V-%%version%%)}}</​WRAP>​ 
  
 In VBA gibt es verschiedene Listen-Arten. Array, Collection und Dictionary. Wenn man noch mit %%RegExp%% arbeitet kommen %%MatchCollection%% und Match.Submatches dazu. Bei Recordset die Fields. In VBA gibt es verschiedene Listen-Arten. Array, Collection und Dictionary. Wenn man noch mit %%RegExp%% arbeitet kommen %%MatchCollection%% und Match.Submatches dazu. Bei Recordset die Fields.
Line 8: Line 23:
 Ich wollte ein einheitliches Konstrukt, durch dass ich bequem mittels Loop durchiterieren kann. Dabei kam die Iterator-Klasse heraus. Ich wollte ein einheitliches Konstrukt, durch dass ich bequem mittels Loop durchiterieren kann. Dabei kam die Iterator-Klasse heraus.
  
-{{tabinclude>:vba:classes:iterator:definition+Am besten mal die [[#​anwendungsbeispiele|Anwendungsbeispiele]] anschauen um zu verstehen um was es geht. 
-:vba:classes:iterator:​beispiele+ 
-:vba:classes:iterator:code}}+Die folgenden Listen sind ausprogrammiert:​ 
 +\\ Array,  
 +Collection(([[http://​msdn.microsoft.com/​de-de/​library/​yb7y698k%28v=vs.90%29.aspx|Collection bei MSDN]])), 
 +Dictionary(([[http://​msdn.microsoft.com/​en-us/​library/​x4k5wbx4%28v=vs.84%29.aspx|Dictionary bei MSDN]])), 
 +%%RegExp.MatchCollection%%(([[http://​msdn.microsoft.com/​en-us/​library/​system.text.regularexpressions.matchcollection%28v=vs.110%29.aspx|MatchCollection bei MSDN]])),  
 +%%RegExp.Submatches%%,​  
 +DAO.Recordset,​  
 +DAO.Fields 
 +DAO.QueryDef 
 +DAO.TableDef 
 +Excel.Workbook ​ (Die Sheets) 
 +Excel.Sheets 
 +FSO.Folder 
 + 
 +===== Definitionen ===== 
 +==== Enumerator ==== 
 +=== itParams === 
 +<code vb>'/** 
 +' * Parameter zur Steuerung des Verhalten des Iterators 
 +' * Die einzelnen Parameter sind mit + kombinierbar 
 +' */ 
 +Public Enum itParams 
 +    itNone = 0                          'Kein Parameter hat gültigkeit 
 +    itNothingAsEmptyList = 2 ^ 0        '​Leerer String, Nothing, Empty, Null wird als leere Liste akzeptiert und wirft kein Fehler 
 +    itListNextNoParamsAsToNext = 2 ^ 1  'Wenn bei listNext keine Parameter angeben werden, einfach eins vorrücken. 
 +    itErrorAtEmptyList = 2 ^ 2          '​Fehler generieren, wenn die iListe leer ist 
 +    itDaoValue = 2 ^ 3                  '​Field-Value anstelle von Field ausgeben 
 +    itIndexInsteadKey = 2 ^ 4                     '​Gibt bei den toX() Funktionen den Index anstelle des Keys zurück 
 +    itDefault = itNothingAsEmptyList + itListNextNoParamsAsToNext 
 +    [_LAST] = 4 
 +End Enum 
 +</​code>​ 
 + 
 +==== Properties ==== 
 +Die Eigenschaften der Klasse. 
 +\\ <​sup>​r</​sup>​ steht für Readable, <​sup>​w</​sup>​ für writable 
 + 
 +=== Properties zu den Daten === 
 +  ***source**<​sup>​rw</​sup>​ Quellliste, über die Iteriert wird (Array, Collection etc.) 
 +  ***current**<​sup>​r</​sup>​ Aktuelles Item 
 +  ***key**<​sup>​r</​sup>​ Aktueller Key 
 +  ***index**<​sup>​r</​sup>​ Aktueller Indes der Liste, beginnend mit dem listenspezifischen Anfang 
 +  ***absolutePosition**<​sup>​r</​sup>​ Absolute Position in der Liste, beginnend mit 0 
 +  ***BOF**<​sup>​r</​sup>​ Beginn of File. Wir sind vor dem ersten Eintrag 
 +  ***%%EOF%%**<​sup>​r</​sup>​ End of File. Wir sind nach dem letzten Eintrag  
 +  ***count**<​sup>​r</​sup>​ Anzahl Items in der Liste 
 +  ***isEmpty**<​sup>​r</​sup>​ Flag, ob überhaubt Einträge vorhanden sindcount=0 
 + 
 +=== Propierties zur Iteratorsteuerung === 
 +Diese Properties sind die Einzeilzuordnungen zu [[##​itparams|itparams]] 
 +  ***Params**<​sup>​rw</​sup>​ Die Parameter als Enum-Set 
 +  ***paramNothingAsEmptyList**<​sup>​rw</​sup>​ Leerer String, Nothing, Empty, Null wird als leere Liste akzeptiert und wirft kein Fehler 
 +  ***paramListNextNoParamsAsToNext**<​sup>​rw</​sup>​ Wenn bei listNext keine Parameter angeben werden, einfach eins vorrücken. 
 +  ***paramErrorAtEmptyList**<​sup>​rw</​sup>​ Fehler generieren, wenn die iListe leer ist 
 +  ***paramDaoValue**<​sup>​rw</​sup>​ Field-Value anstelle von Field ausgeben 
 +  ***paramIndexInsteadKey**<​sup>​rw</​sup>​ Gibt bei den toX() Funktionen den Index anstelle des Keys zurück 
 + 
 +==== Methoden ==== 
 +=== Collection Class Methodes === 
 +Diese Funktionen dienesn dazu, dass die Klasse wie eine Collection genutzt werden kann. 
 +\\ [[http://​msdn.microsoft.com/​en-us/​library/​aa262338%28v=vs.60%29.aspx]] 
 + 
 +== NewEnum() == 
 +<code vb>'/​** 
 +' * Der NewEnum wird für die For Each.. Next Schleife verwendet 
 +' * 
 +' * Diese Funktion hat das Attribut "'​Attribute NewEnum.VB_UserMemId = -4" 
 +' * !! Diese Iterierung hat keinen Einfluss auf die aktuelle Position !! 
 +' * 
 +' * @return Das nächste element 
 +' */ 
 +Public Function NewEnum() As IUnknown 
 +</​code>​ 
 + 
 +== item() == 
 +<code vb>'/​** 
 +' * Entspricht dem item()-Befehl der Listenobjekte 
 +' * Alle 3 Propert-Funktionen aben das versteckte Attribut "​Attribute item.VB_UserMemId = 0" 
 +' * Dadurch kann mittels it(1), it("​MyFeild"​),​ it!MyField etc darauf zugegriffen werden. 
 +' * 
 +' * !! Das Verhalten dieser Funktion ist NICHT standartisiert. Sie entspricht dem entsprechenden Verhalten der Source !! 
 +' * 
 +' * @param ​ Variant Index/Key 
 +' * @return Variant 
 +' */ 
 +Public Property Get item(ByVal iIndex As Variant) As Variant 
 +</​code>​ 
 + 
 + 
 +=== Initialisierungs-Methoden === 
 +== initialize() == 
 +<code vb>'/​** 
 +' * Initialisuert den Iterator 
 +' * @param ​ Variant ​    Die Liste, über welche Iteriert werden soll 
 +' * @param ​ itParams ​   Parameters 
 +' * @return Boolean ​    trueiList ist eine Liste und hat Werte 
 +' */ 
 +Public Static Function initialize( _ 
 +        ByRef iList As Variant, _ 
 +        Optional ByVal iParams As itParams = itDefault _ 
 +) As Boolean 
 +</​code> ​  
 + 
 +== initializeRs() == 
 +Die Parameters findest du [[#​itparams|hier]]. Sie sind mit + kombinierbar. 
 +<code vb>'/​** 
 +' * Analog zu initialze. Erstellt aber direkt ein Recordset aus einem SQL 
 +' * @param ​ String ​     SLQ String 
 +' * @param ​ itParams ​   Parameters 
 +' * @return Boolean ​    trueiList ist eine Liste und hat Werte 
 +' */ 
 +Public Static Function initializeRs( _ 
 +        ByVal iSql As String_ 
 +        ​Optional ByVal iParams As itParams = itDefault _ 
 +) As Boolean</​code>​ 
 +=== Navigations-Methoden === 
 +== toNext() == 
 +<code vb>'/​** 
 +' * Geht zum nächsten Datensatz. Der Key und er Datensatz werden als Parameter zurückgegeben,​ EOF als Return-Value 
 +' * @param ​ Variant ​    Key oder pos des Items 
 +' * @param ​ Variant ​    Das Item himself 
 +' * @return Boolean ​    EOF 
 +Public Function toNext( _ 
 +        Optional ByRef oKey As Variant = Null, _ 
 +        Optional ByRef oItem As Variant = Null _ 
 +) As Boolean</​code>​ 
 + 
 +== toPrev() == 
 +<code vb>'/​** 
 +' * Geht zum nächsten Datensatz. Der Key und er Datensatz werden als Parameter zurückgegeben,​ EOF als Return-Value 
 +' * @param ​ Variant ​    Key oder pos des Items 
 +' * @param ​ Variant ​    Das Item himself 
 +' * @return Boolean ​    EOF 
 +Public Function toPrev( _ 
 +        Optional ByRef oKey As Variant = Null, _ 
 +        Optional ByRef oItem As Variant = Null _ 
 +) As Boolean</​code>​ 
 + 
 +== toFirst() == 
 +<code vb>'/​** 
 +' * Geht zum ersten Datensatz. 
 +' * Vorsicht, während reset() eins vor den ersten Datensatz geht, geht toFirst() bereits auf den ersten Datensatz 
 +' * Somit ists das eigentlich reset()+toNext() 
 +' * @param ​ Variant ​    Key oder pos des Items 
 +' * @param ​ Variant ​    Das Item himself 
 +' * @return Boolean ​    EOF 
 +Public Function toFirst( _ 
 +        Optional ByRef oKey As Variant = Null, _ 
 +        Optional ByRef oItem As Variant = Null _ 
 +) As Boolean</​code>​ 
 + 
 +== toLast() == 
 +<code vb>'/​** 
 +' * Geht zum nächsten Datensatz. Der Key und er Datensatz werden als Parameter zurückgegeben,​ EOF als Return-Value 
 +' * @param ​ Variant ​    Key oder pos des Items 
 +' * @param ​ Variant ​    Das Item himself 
 +' * @return Boolean ​    EOF 
 +Public Function toLast( _ 
 +        Optional ByRef oKey As Variant = Null, _ 
 +        Optional ByRef oItem As Variant = Null _ 
 +) As Boolean</​code>​ 
 + 
 +== toPosition() == 
 +<code vb>'/​** 
 +' * Geht zum nächsten Datensatz. Der Key und er Datensatz werden als Parameter zurückgegeben,​ EOF als Return-Value 
 +' * @param ​ Long        Absolute Position. Zwischen 0 und Count-1 
 +' * @param ​ Variant ​    Key oder index des Items 
 +' * @param ​ Variant ​    Das Item himself 
 +' * @return Boolean ​    EOF 
 +Public Function toPosition( _ 
 +        ByVal iAbsolutPosition As Long, _ 
 +        Optional ByRef oKey As Variant = Null, _ 
 +        Optional ByRef oItem As Variant = Null _ 
 +) As Boolean</​code>​ 
 + 
 +== listNext() == 
 +Siehe auch [[:vba:functions:list]] 
 +<code vb>'/​** 
 +' * Rückt den Zeiger um Eins vor und gibt die Elemente einer Unterliste aus. 
 +' * @paramArray Variant ​   Auflistung der Variablendie abgefüllt werden 
 +' * @return ​    EOF 
 +' */ 
 +Public Function listNext( _ 
 +        ParamArray oParams() As Variant _ 
 +) As Boolean</​code>​ 
 + 
 +== list() == 
 +Siehe auch [[:vba:functions:list]] 
 +<code vb>'/​** 
 +' * Ggibt die Elemente der aktuellen Unterliste aus. 
 +' * @paramArray Variant ​   Auflistung der Variablen, die abgefüllt werden 
 +' * @return EOF & BOF 
 +' */ 
 +Public Function list( _ 
 +        ParamArray oParams() As Variant _ 
 +) As Boolean</​code>​ 
 + 
 +== reset() == 
 +<code vb>'/​** 
 +' * Setzt den pos auf den Start-1 zurück, so dass bei einem toNext() der erste Datensatz kommt 
 +' */ 
 +Public Sub reset()</​code>​ 
 + 
 +== subIterator() == 
 +Wenn das Current-Objekt selber wieder iterierbar ist, kann mit dieser Methode direkt ein Iterator für das Objekt erstellt werden. 
 +<code vb>'/​** 
 +' * Gibt current als Iterator zurück 
 +' * @return Iterator 
 +' */ 
 +Public Property Get subIterator() As Iterator</​code>​ 
 + 
 +===== Iterierbare Listen ===== 
 +Die folgenden Datentypen werden vom Iterator als Liste erkannt und können iteriert werden 
 +  *Array 
 +  *Dictionary 
 +  *Collection 
 +  *%%RegExp.MatchCollection%% 
 +  *%%RegExp.Match%% 
 +  *Dao.Recordset 
 +  *Dao.Fields 
 +  *Dao.Field 
 +  *Properties 
 + 
 +===== Anwendungsbeispiele ===== 
 + 
 +Die Beispiele sind unvollständig. Die Klasse hat noch einiges mehr auf Lager. Finde es heraus oder frag nach. 
 + 
 +==== Iteration mit einem eindimensionalen Array ==== 
 +=== Einfachstes Beispiel mit einem Array === 
 +<code vb>​Public Sub testIt() 
 +    Dim arr()   As Variant        arr = Array(1, 2, 3) 
 +    Dim it      As New Iterator: ​   it.initialize arr 
 +     
 +    Do While it.toNext 
 +        Debug.Print it.key & ": " & it.current 
 +    Loop 
 +End Sub</code
 + 
 +=== Dito, aber der Wert wird als Variable verarbeitet === 
 +<code vb>​Public Sub testIt() 
 +    Dim arr()   As Variant: ​        arr = Array(1, 2, 3) 
 +    Dim it      As New Iterator: ​   it.initialize arr 
 +    Dim key     As Variant 
 +    Dim val     As Variant 
 +     
 +    Do While it.toNext(key,​ val) 
 +        Debug.Print key & ": " & val 
 +    Loop 
 +End Sub</​code>​ 
 + 
 +=== Von hinten nach vorne iterieren === 
 +<code vb>​Public Sub testIt() 
 +    Dim arr()   As Variant: ​        arr = Array(1, 2, 3) 
 +    Dim it      As New Iterator: ​   it.initialize arr 
 +  
 +    it.toEOF 
 +    Do While it.toPrev 
 +        Debug.Print it.KEY & ": " & it.current 
 +    Loop 
 +End Sub</​code>​ 
 + 
 +=== Und ein Array, der nicht bei 0 beginnt === 
 +<code vb>​Public Sub testIt() 
 +    Dim arr(3 To 4)   As Variant 
 +    Dim it      As New Iterator 
 +    Dim key     As Variant 
 +    Dim val     As Variant 
 +     
 +    arr(3) = 33 
 +    arr(4) = 44 
 +    it.initialize arr 
 +     
 +    Do While it.toNext(key,​ val) 
 +        Debug.Print key & ": " & val 
 +    Loop 
 +End Sub</​code>​ 
 + 
 +==== Iteration über einen 2 Dimensionalen Array ==== 
 +=== Mit direktem Auslesend er SubItems mit listNext() === 
 +<code vb>​Public Sub testIt() 
 +    Dim arr(3 To 4)   As Variant 
 +    Dim it      As New Iterator 
 +    Dim v1, v2, v3 
 +     
 +    arr(3) = Array(31, 32, 33) 
 +    arr(4) = Array(41, 42, 44) 
 +    it.initialize arr 
 +     
 +    Do While it.listNext(v1,​ v2, v3) 
 +        Debug.Print v1 & "​-"​ & v2 & "​-"​ & v3 
 +    Loop 
 +End Sub</​code>​ 
 +<​code>​31-32-33 
 +41-42-44</​code>​ 
 + 
 +==== Besipel mit MatchCoellection ==== 
 +<code vb>​Public Sub testIt() 
 +    Dim rx  As New regExp 
 +    Dim mc  As Variant 
 +    Dim it  As Iterator 
 +    Dim x, y 
 + 
 +    rx.Global = True 
 +    rx.pattern = "​([A-H])([1-8])"​ 
 + 
 +    Set mc = rx.execute("​Springer von A1 auf B3") 
 +    Set it = New Iterator: it.initialize mc 
 +    Do While it.toNext 
 +        Debug.Print it.current.value ​   'Den gesamten gefunden String ausgeben 
 +        it.list x, y                    'Die 2 Submatches auf x und y verteilen 
 +        Debug.Print x & ":"​ & y         '​x & y ausegeben 
 +    Loop 
 +End Sub</​code>​ 
 +<​code>​A1 
 +A:1 
 +B3 
 +B:​3</​code>​ 
 + 
 +==== Beispiele zu Recordset ==== 
 +=== Recordset durchiterieren === 
 +<code vb>​Public Sub testIt() 
 +    '​Initialiseren des Iterators über initializeRs 
 +    Dim it As New Iterator: it.initializeRs "​SELECT [id], [number_one],​ [number_two] FROM [_test]"​ 
 +     
 +    'Jede ID ausgeben 
 +    Do While it.toNext 
 +        Debug.Print it!id 
 +    Loop 
 +     
 +    it.reset ​   '​Postion zurücksetzen 
 +     
 +    'Die Felder des Recordsets direkt in die Variablen übertragen 
 +    Dim id, n1, n2 
 +    Do While it.listNext(id,​ n1, n2) 
 +        Debug.Print id, n1, n2 
 +    Loop 
 +     
 +End Sub</​code>​ 
 +<​code>​ 1  
 + 2  
 + 3  
 + 4  
 + ​1 ​            ​11 ​           21  
 + ​2 ​            ​12 ​           22  
 + ​3 ​            ​13 ​           23  
 + ​4 ​            ​14 ​           24</​code>​ 
 + 
 +=== FieldList durchiterieren - Ausgabe von current und value === 
 +<code vb>​Public Sub testIt() 
 +    Dim v As Variant 
 +     
 +    '​Initialiseren des Iterators über initializeRs 
 +    Dim it As New Iterator: it.initializeRs "​SELECT [id], [number_one],​ [number_two] FROM [_test]"​ 
 +     
 +    'Erste Zeile als [Fields] auslesen und neuen Iterator daruas erstellen 
 +    it.toFirst 
 +    Dim itFields As Iterator: Set itFields = it.subIterator 
 +            
 +    Debug.Print "== Ausgabe: Property current"​ 
 +    Do While itFields.toNext 
 +        print_r itFields.current 
 +    Loop 
 + 
 +    Debug.Print "== Ausgabe: Property value"​ 
 +    itFields.reset ​                 '​position zurücksetzen 
 +    Do While itFields.toNext 
 +        print_r itFields.value 
 +    Loop 
 + 
 +    Debug.Print "== Ausgabe: Referenziertes Property current, Iterator mit dem Parameter DaoValue"​ 
 +    itFields.reset ​                 '​position zurücksetzen 
 +    itFields.paramDaoValue = True   '​Paraeter DaoValue setzen um das Verhalten von current zu ändern 
 +    Do While itFields.toNext(,​ v)   '​Der zweite Parameter von toNext() entspricht dem current 
 +        print_r v 
 +    Loop 
 + 
 +End Sub</​code>​ 
 +<​code>​== Ausgabe Property current 
 +<​Field2> ​ ( 
 +    [OrdinalPosition] => <​Integer>​ 0 
 +    [name] => <​String>​ '​id'​ 
 +    [value] => <​Long>​ 1 
 +    [type] => <​Integer>​ 4 
 +
 +<​Field2> ​ ( 
 +    [OrdinalPosition] => <​Integer>​ 1 
 +    [name] => <​String>​ '​number_one'​ 
 +    [value] => <​Long>​ 11 
 +    [type] => <​Integer>​ 4 
 +
 +<​Field2> ​ ( 
 +    [OrdinalPosition] => <​Integer>​ 2 
 +    [name] => <​String>​ '​number_two'​ 
 +    [value] => <​Long>​ 21 
 +    [type] => <​Integer>​ 4 
 +
 +== Ausgabe Property value 
 +<​Long>​ 1 
 +<​Long>​ 11 
 +<​Long>​ 21 
 +== Ausgabe Property current, Iterator mit dem Parameter DaoValue 
 +<​Long>​ 1 
 +<​Long>​ 11 
 +<​Long>​ 21</​code>​ 
 + 
 +===== Code ===== 
 +<source '​%%fpath%%/​%%fname%%'​ vb> 
vba/classes/iterator/index.1393852590.txt.gz · Last modified: 03.03.2014 14:16:30 by yaslaw