Suggesties | SortedList |
1. Wat is een SortedList ? 2. Waarvoor een SortedList ? 3. Achtergrond van de SortedList 4. Maak een SortedList 4.1 Early binding 4.1.1 Local scope 4.1.2 Private scope 4.1.3 Public scope 4.2 Late binding 4.2.1 Local scope 4.2.2 Private scope 4.2.3 Public scope 5. Vul een SortedList 5.1 items toevoegen 5.1.1 Methode .Add 5.1.2 Methode .Item 5.3 Soorten Items 5.3.1 lege tekstreeks 5.3.2 gewone tekstreeks 5.3.3 niet-afdrukbaar teken 5.3.4 getal 5.3.5 datum 5.3.6 1-dimensionele array 5.3.7 meer-dimensionele array 5.3.8 object 5.3.9 controls in Userform 5.3.10 ActiveX controls 5.3.11 alle werkbladen 6. De omvang van een SortedList 7. Controle of een item voorkomt 7.1 Controle op sleutel 7.2 Controle op waarde 8.1 De index van een sleutel 8.2 De index van een waarde 9. Lezen van elementen 9.1 1 element met index 9.2 1 element met sleutel 9.3 1 element met sleutel-index < 9.4 alle waarden op index 9.5 alle sleutels op index 10 Wijzig een element 11 Sorteren van elementen 11.1 Aflopend sorteren 12 Verwijder elementen 12.1 1 element op sleutel 12.2 1 element op index 12.3 1 element op inhoud 12.4 alle elementen 13. Kopie van een SortedList 14. Trefwoorden |
Een SortedList in VBA is een verzamelobject: je kunt er allerlei verschillende zaken in opbergen: getallen, teksten, datums, arrays, ranges, variabelen en objecten. VBA heeft verschillende andere mogelijkheden om gegevens op te slaan: - een dictionary - een collection - een array variabele - een ActiveX ComboBox - een ActiveX ListBox - een Userform ComboBox - een Userform ListBox - een Arraylist De keuze voor een van deze methoden is afhankelijk van het te bereiken doel. In deze pagina wordt geen poging gedaan al deze methoden met elkaar te vergelijken. We beperken ons tot een bespreking van de mogelijkheden van de SortedList. Geen van de andere 'verzamel' methoden zoals Collection, Array of Dictionary heeft een sorteermethode. De sorteermethode van de SortedList is (naast die van de 'Arraylist') de enige mij bekende VBA-sorteermethode. Deze sorteermethode is erg snel. Dat kan een argument zijn om juist van een SortedList gebruik te maken. Een ander kenmerk van de Sortedlist is, dat ieder element een sleutel heeft. De Arraylist sorteert op de inhoud van de elementen, de Sortedlist sorteert op sleutel. 2. Waarvoor kun je een SortedList gebruiken ? Je kunt de SortedList gebruiken om gegevens uit allerlei bronnen bij elkaar te zetten en snel te bewerken omdat ze via de SortedList in het werkgeheugen geladen zijn en snel toegankelijk zijn.In plaats van gegevens te bewerken in een Excel-werkblad, een Word Document, een Powerpointpresentatie, doe je dat in het werkgeheugen. Daarvoor hoeft bijv. geen scherm ververst te worden, berekeningen uitgevoerd te worden, waardoor de SortedList snel is. 3. Waar komt de SortedList vandaan ? De SortedList maakt geen deel uit van de standaard VBA-bibliotheek.De SortedList is onderdeel van de bibliotheek System.Collections. Die bevindt zich in het bestand ....\WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb of in een vergelijkbare directory Je kunt via de VBEditor een aktieve verbinding leggen naar dit bestand door mscorlib.dll bij de Referenties aan te vinken (Extra/referenties... of Tools/References..) Als je een bestand waarin je gebruik maakt van een SortedList verspreidt, wordt meteen ook die verbinding naar deze bibliotheek meeverspreid. In VBA kun je op twee verschillende manieren die referentie maken ThisWorkbook.VBProject.References.AddFromFile "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" ThisWorkbook.VBProject.References.AddFromguid "{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}", 2, 4 Je kunt de code ook pas een verbinding laten leggen op het moment dat je de SortedList nodig hebt ('late binding'). Daarvoor gebruik je dan deze VBA code: createobject("System.Collections.SortedList") 4. Hoe maak je een SortedList ? Er zijn verschillende methoden om een SortedList aan te maken.Dat is afhankelijk van: - de manier waarop je naar de bibliotheek van de SortedList wil verwijzen: 'early binding' of 'late binding' - de 'scope' van de SortedList: wil je hem in 1 procedure of meer procedures gebruiken:'local scope','private scope','public scope' 4.1 Met referentie naar de bibliotheek: 'early binding' Als je de SortedList alleen maar nodig hebt in 1 macro of funktie kun je de definitie van de SortedList tot die procedure beperken.zonder toewijzing aan een variabele: With new SortedList .Add "aa1"
end withdim a_00 as New SortedList a_00.Add "aa1" set a_00 = New SortedList a_00.add "aa1" dim a_00 as Object set a_00= new SortedList a_00.add "aa1" dim a_00 as SortedList set a_00= new SortedList a_00.add "aa1" Dan dien je altijd met een variabele te werken. Die variabele moet je eerst in het declaratiegebied van de codemodule declareren. Je kunt het gegevenstype van de variabele voor een SortedList declareren als Object, SortedList of Variant. Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten. In het declaratiedeel van de codemodule zet je Dim a_00 Private a_00 Dim a_00 as Variant Private a_00 as Variant Dim a_00 as Object Private a_00 as Object Dim a_00 as SortedList Private a_00 as SortedList Set a_00 = New SortedList Dim a_00 As New SortedList Private a_00 as New SortedList Als je een SortedList toegankelijk wil maken voor alle procedures (macro's of funkties) in het werkboek, Userform, Macromodule of Classmodule maak je gebruik van Public Scope. Dan dien je altijd met een variabele te werken. 4.1.3.1 Gelijktijdige declaratie en toewijzing Om een variabele beschikbaar te maken in alle macro's en funkties van een codemodule moet je de variabele declareren in het declaratiegebied van de codemodule van een Macromodule.Vervolgens moet je aan de variabele een nieuwe instantie van de SortedList toewijzen. Wanneer je gebruik maakt van 'early binding' kan dat heel compact in één keer met deze code in het declaratiegebied. Public a_00 As New SortedList 4.1.3.2 Declaratie in het declaratiegebied en toewijzing in een procedure De variabele moet je eerst in het declaratiegebied van de codemodule van een macromodule declareren.Je kunt het gegevenstype van de variabele voor een SortedList declareren als Object, SortedList of Variant. Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten. In het declaratiegebied Public a_00 Public a_00 as Variant Public a_00 as Object Public a_00 as SortedList Wijs een nieuwe instantie van de SortedList toe aan de gedeclareerde variabele. set a_00 = new SortedList 4.2 Zonder referentie naar de bibliotheek: 'late binding' Als je de SortedList alleen maar nodig hebt in 1 macro of funktie kun je de definitie van de SortedList tot die procedure beperken.zonder toewijzing aan een variabele: With CreateObject("System.Collections.SortedList") .Add "aa1"
end withset a_00 = CreateObject("System.Collections.SortedList") a_00.Add "aa1" Dan dien je altijd met een variabele te werken. Die variabele moet je eerst in het declaratiegebied van de codemodule declareren. Je kunt het gegevenstype van de variabele voor een SortedList declareren als Object of Variant. Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten. Vervolgens wijs je in een procedure (macro of funktie) een nieuwe instantie van de SortedList toe aan de gedeclareerde variabele. In het declaratiedeel van de codemodule Dim a_00 Private a_00 Dim a_00 as Variant Private a_00 as Variant Dim a_00 as Object Private a_00 as Object Set a_00 = CreateObject("System.Collections.SortedList") Als je een SortedList toegankelijk wil maken voor alle procedures (macro's of funkties) in het werkboek, Userform, Macromodule of Classmodule maak je gebruik van Public Scope. Dan dien je altijd met een variabele te werken. De declaratie van die variabele dient te staan in het declaratiegebied van een macromodule (dus niet in de codemodule van een userform, werkblad, het werkboek of een klassemodule). In welke macromodule de declaratie staat maakt niet uit. Het gegevenstype voor de SortedlList kan zijn Variant of Object. Omdat er nog geen verbinding is gelegd met de SortedList-bibliotheek kun je het gegevenstype 'SortedList' niet gebruiken. In een procedure (macro of funktie) wijs je een nieuwe instantie van de SortedList toe aan de gedeclareerde variabele. In het declaratiedeel van de codemodule van een macromodule Public a_00 Public a_00 as Variant Public a_00 as Object set a_00 = CreateObject("System.Collections.SortedList") Voor het vervolg in deze pagina zal ik voor de overzichtelijkheid alleen gebruikmaken van de With ... End With methode in een 'late binding' situatie. Ieder element in een sortedlist heeft een sleutel (key) en een waarde. Een sleutel is uniek. De elementen in de SortedList worden op hun sleutel oplopend gesorteerd. Er zijn 2 methodes om elementen aan een SortedList toe te voegen: .Add en .Item("sleutel"). De methode .Add genereert een foutmelding als de sleutel al bestaat. De methode .Item("sleutel") vervangt het aan die sleutel gekoppelde element. De inhoud van een item kan van alles zijn: getallen, teksten, datums, arrays, ranges, variabelen, collections, dictionaries, een lege tekenreeks, niets en objecten Je kunt aan een SortedList alleen afzonderlijke items toevoegen (in tegenstelling tot de ArrayList). Het eerste argument van de method .Add bevat de sleutel, het tweede argument het element zelf. De methode .Add plaatst een item in de SortedList en sorteert het element op basis van de sleutel. De sortering heeft gevolgen voor het indexnummer van het element, niet voor de sleutel of de inhoud. With CreateObject("System.Collections.SortedList") .Add "eerste","inhoud"
.Add "1", New Collection
End With.Add "2",123 .Add "sleutel", Date .Add "laatste", Array("rood", "wit", "groen") De methode .Item plaatst een element in de SortedList en sorteert het nieuwe element op de sleutel. De sortering heeft gevolgen voor het indexnummer van het element, niet voor de sleutel of de inhoud. With CreateObject("System.Collections.SortedList") .Item("aa1")= 1234
End With.Item("aa2")= "tekst" .Item("aa4")= new Collection .Item("aa3")= Array("rood", "wit", "groen" 5.3 Elementen in een SortedList Nieuwe elementen worden meteen op sleutel gesorteerd aan de Sortedlist toegevoegd.De inhoud van een item kan van alles zijn: getallen, teksten, datums, arrays, ranges, variabelen, collections, dictionaries, een lege tekenreeks, niets en objecten Hieronder een aantal voorbeelden van elementen met verschillende soorten inhoud. With CreateObject("System.Collections.SortedList")
.Add "c_00" ,vbNullString
End With.Add "c_01","" With CreateObject("System.Collections.SortedList")
.Add "d_00", "abcde"
End With.Item("d_01")="fghi" 5.3.3 een niet-afdrukbaar teken With CreateObject("System.Collections.SortedList")
.Add "e_00", vbTab
End With.Item("e_01 ")=vbLf With CreateObject("System.Collections.SortedList")
.Add "f_00", 12345
End With.Item("f_01")= RGB(23, 45, 678) ' typename: Integer
' typename: Long 5.3.5 een datum (typename: Date) With CreateObject("System.Collections.SortedList")
.Add "g_00", Date
End With.Add "g_01", CDate("23-04-2012") .Item ("g_00")= DateSerial(2013, 10, 12) 5.3.6 een 1-dimensionele Array (typename: Variant()) With CreateObject("System.Collections.SortedList")
.Add "h_00", Array("aa1", "aa2", "aa3")
End With.Add "h_01", Split("bb1_cc1_dd1", "_") .Item("h_02")=Array("aa1", "aa2", "aa3") 5.3.7 een meer-dimensionele Array (typename: Variant())
With CreateObject("System.Collections.SortedList")
ReDim sn(6, 10)
End With.Add "i_00", sn .Item("i_01") = sn With CreateObject("System.Collections.SortedList")
.Add "j_00", Range("A1:K10")
End With.Item("j_01") = Range("A1:K10") 5.3.9 de controls in een userform With CreateObject("System.Collections.SortedList")
For Each it In Controls
End With.Add it.name, it
Next5.3.10 de ActiveX-controls in een werkblad With CreateObject("System.Collections.SortedList")
For Each it In Sheets("sheet1").OLEObjects
End With.Add it.name, it
Next5.3.11 alle werkbladen van een werkboek With CreateObject("System.Collections.SortedList")
For Each sh In Sheets
End With.Add sh.name, sh
Next.Item(.count)= sh 6. De omvang van een SortedList De eigenschap .Count geeft het aantal items van/in een SortedList weer.De eigenschap .Count geeft natuurlijk ook meteen het aantal sleutels in de SortedList weer. Voor de eigenschap .count heeft de SortedList ook nog twee equivalenten: .Values.Count en .Keys.Count. With CreateObject("System.Collections.SortedList")
For Each sh In Sheets
End With.Add sh.name, sh
Next.Item(.count) = sh msgbox .Count msgbox .Values.Count msgbox .Keys.Count 7.1.1 Controle of een sleutel in een SortedList voorkomt De eigenschap .Contains geeft aan of een bepaalde sleutel in een SortedList voorkomt: True of FalseWith CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
End WithIf Not .contains(it) Then .Add it, 1200
NextMsgBox .Contains("aa4") MsgBox .Contains("aa9") 7.1.2 Controle of een sleutel in een SortedList voorkomt: .ContainsKey De eigenschap .ContainsKey geeft aan of de SortedList een bepaalde sleutel bevat: True of False.Daarmee kun je voorkomen dat een bestaand item met een sleutel wordt overschreven, of dat een foutmelding wordt gegenereerd. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
End WithIf Not .ContainsKey(it) Then .Add it, 388
Next7.2 Controle of een bepaalde waarde in een SortedList voorkomt: .ContainsValue De eigenschap .ContainsValue geeft aan of de SortedList een bepaalde waarde bevat: True of False.Daarmee kun je voorkomen dat een bepaalde waarde aan twee verschillende sleutels wordt toegewezen. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
End WithIf Not .ContainsValue(it) Then .Add .count, it
Next8.1 Controle op welke positie een sleutel in een SortedList voorkomt: .IndexOfKey De eigenschap .IndexOfKey geeft aan op welke positie een sleutel in een SortedList staat.De eerste sleutel heeft indexnummer 0. Als een sleutel niet bestaat geeft deze methode -1 als resultaat. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa5", "aa6")
End WithIf Not .contains(it) Then .Add it, 2*.count
Nextmsgbox .IndexOfKey("aa4") 8.2 Controle op welke positie een waarde in een SortedList voorkomt: .IndexOfValue De eigenschap .IndexOfValue geeft aan op welke positie een waarde in een SortedList staat.Het eerste element heeft indexnummer 0. Als een waarde niet bestaat geeft deze methode -1 als resultaat. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa5", "aa6")
End WithIf Not .contains(it) Then .Add it, 2*.count
Nextmsgbox .IndexOfValue(6) 9. Lezen/ophalen van elementen 9.1 Lezen/ophalen van 1 element met de index: .GetByIndex en .GetValueList Aan de hand van het indexnummer kan de waarde van een element in de SortedList worden gelezen.Houd er rekening mee, dat het eerste item in een SortedList indexnummer 0 heeft. Er zijn 2 methoden om dit te doen: .GetByIndex en .GetValueList With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa5", "aa4", "aa6")
End With.Add it, 3*.count
Nextmsgbox .GetByIndex(0) msgbox .GetByIndex(.count-1) msgbox .GetByIndex(3) msgbox .GetValueList(0) msgbox .GetValueList(.count-1) msgbox .GetValueList(3) ' het eerste item
' het laatste item ' het 4e element in de SortedList 9.2 Lezen/ophalen van 1 element met de sleutel: .Item Aan de hand van de sleutel kan de waarde van een element in de SortedList worden gelezen.With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa5", "aa4", "aa6")
End With.Add it, 3*.count
Nextmsgbox .Item("aa4") 9.3 Lezen/ophalen van 1 een sleutel aan de hand van de gesorteerde index: .GetKey en .GetKeyList Aan de hand van de index kan een sleutel in de SortedList worden gelezen.De methode .GetKey en .Getkeylist zijn daarvoor geschikt. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa5", "aa4", "aa6")
End With.Add it, 6*.count
NextMsgbox .getkey(2) MsgBox .getkeylist()(2) In de SortedList zul je alle elementen in een lus af moeten lopen. De methoden .GetByIndex en .GetValueList zijn daarvoor geschikt. Het resultaat is een lijst met waarden, gesorteerd op basis van hun sleutels. De omgekeerde sorteervolgorde krijg je met een aflopende lus. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa5", "aa4", "aa6")
End With.Add it, 6*.count
NextFor j = 0 To .Count - 1 c00 = c00 & .GetByIndex(j)
Nextc01 = c01 & .GetValueList()(j) c02 = c02 & .GetByIndex(.count-1-j) c03 = c03 & .GetValueList()(.count-1-j) Msgbox c00 Msgbox c01 Msgbox c02 Msgbox c03 9.5 Lezen/ophalen van alle sleutels: .GetKey en .GetKeyList In tegenstelling tot de Dictionary heeft de SortedList geen eigenschap waarmee alle gesorteerde sleutels in één keer uitgelezen kunnen worden (.keys bij Dictionary).In de SortedList zul je alle sleutels in een lus af moeten lopen. De methoden .GetKey en .GetKeyList zijn daarvoor geschikt. Het resultaat is een lijst met gesorteerde sleutels. De omgekeerde sorteervolgorde krijg je met een aflopende lus. With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa3", "aa2", "aa6")
End With.Add .count, it
Nextfor j = 0 to .count-1
msgbox c00c00 = c00 & vblf & .getkey(j)
nextc01 = c01 & vbLf & .GetKeylist()(j) c02 = c02 & .GetKey(.count-1-j) c03 = c03 & .GetKeyList()(.count-1-j) msgbox c01 Msgbox c02 Msgbox c03 10. wijzig een element: .Item en .SetByIndex Een bestaand element in een Sorted kun je wijzigen door aan het .item een andere waarde of een andere inhoud toe te kennen.Het te wijzigen item kun je met de sleutel of met de index benaderen. Als de sleutel bekend is kun je de methode .Item gebruiken. Als de index bekend is is de methode .SetByIndex aangewezen. Met de sleutel: With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa8", "aa12", "aa6")
End With.Add it, it
Nextmsgbox .Item("aa3") .Item("aa3")=1235 msgbox .Item("aa3") With CreateObject("System.Collections.SortedList") For Each it In Array("aa1", "aa2", "aa3", "aa8", "aa12", "aa6")
End With.Add it
Nextmsgbox .GetByIndex(3) .SetByIndex(3)="bb20" msgbox .GetByIndex(3) De SortedList evalueert zelf of er sprake moet zijn van een numerieke sortering of een tekstsortering. Een mengeling van gegevenstypen van sleutels leidt tot een foutmelding. tekstsortering With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa13", "aa22", "aa6")
End With.Add it, .count
Nextfor j = 0 to .count-1 c00 = c00 & vblf & .getkey(j)
nextmsgbox c00 With CreateObject("System.Collections.SortedList")
For Each it In Array(12, 112, 2, 34, 305, 302)
End With.Add .count, it
NextFor j = 0 to .count-1 c00 = c00 & vblf & .getkey(j)
nextmsgbox c00 Wil je de items aflopend terugkrijgen dan moet je ze aflopend opvragen. With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa13", "aa22", "aa6")
End With.Add it, .count
Nextfor j = .count-1 to 0 step -1 c00 = c00 & vblf & .GetByIndex(j)
nextmsgbox c00 With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa13", "aa12", "aa6")
End With.Add it, .count
NextFor j = .count-1 to 0 step -1 c00 = c00 & vblf & .GetKey(j)
nextmsgbox c00 12. verwijder elementen uit een SortedList 12.1 verwijder 1 element op basis van de sleutel: .Remove De methode .Remove verwijdert 1 element uit de SortedList.In het argument geef je de naam van de sleutel op. Als het element met de opgegeven inhoud niet bestaat negeert de methode de opdracht; VBA genereert geen foutmelding. Verwijder het eerste item met de waarde "aa3": With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa8", "aa3", "aa12", "aa6")
End With.Add it, .count*5
NextMsgBox .Count .Remove "aa3" MsgBox .Count 12.2 verwijder 1 element op basis van de index in de SortedList: .RemoveAt De methode .RemoveAt verwijdert het element op de positie/met de index in het argument.Als het opgeven indexnummer niet bestaat genereert VBA een foutmelding. Verwijder het 5e element (met indexnummer 4) With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa5", "aa6")
End With.Add it
NextMsgBox .Count .RemoveAt 4 MsgBox .Count 12.3 verwijder 1 element op basis van de inhoud De SortedList heeft hiervoor geen eigen methode.Door op basis van de inhoud naar de bijbehorende index of de sleutel te zoeken kun je met .Remove of .RemoveAt het gewenste element verwijderen. Verwijder op index With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa8", "aa3", "aa12", "aa6")
End With.Add it, .Count * 5
NextMsgBox .Count For j = 0 To .Count - 1 If .getbyIndex(j) = 25 Then
Next.RemoveAt j
End IfExit For MsgBox .Count With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa8", "aa3", "aa12", "aa6")
.
End WithAdd it, .Count * 5
NextMsgBox .Count For j = 0 To .Count - 1 If .getbyIndex(j) = 25 Then
Next.Remove .getkey(j)
End IfExit For MsgBox .Count 12.4 verwijder alle elementen: .Clear De methode .Clear verwijdert alle elementen uit de Sorted.With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa8", "aa12", "aa6")
End With.Add it, .count*3
Next.Clear MsgBox .Count 13. maak een kopie van de SortedList: .Clone Voor een SortedList bestaat een aparte methode om een onafhankelijke kopie te maken: .Clone.Wijzigingen in die kopie hebben geen effekt op de oorspronkelijke SortedList. Omdat de kopie ook weer een SortedList is, dus een object, is de instructie 'Set' noodzakelijk bij de toewijzing aan een variabele. With CreateObject("System.Collections.SortedList")
For Each it In Array("aa1", "aa2", "aa3", "aa8", "aa12", "aa6")
End With.Add it, it
Nextset c_00=.Clone msgbox c_00.Count c_00.item(2)="~" MsgBox .Item("aa2") & vbTab & c_00.Item("aa2")) |