RSS

For Each...Next løkker i Excel VBA class collections

Class collections (klassesamlinger) er et formidabelt værktøj til struktureret programmering, når man har mange objekter af samme natur.

Det være sig bøger, kunder, varer, råmaterialer - hvad som helst der kan beskrives på nogenlunde samme måde med egenskaber, metoder og hændelser.

Det har jeg beskrevet på siden Klasser og class collections i Excel VBA, hvor du også kan downloade et regneark med et eksempel.

Det er slet ikke så langhåret, men kan tværtimod gøre programmering til en leg, fordi man ikke skal holde styr på en hulens masse variable.

Der er bare en lille hage: Man kan ikke uden videre gennemløbe sin class collection med den hurtige løkke, For Each...Next, som man kan med Excels egne collections.

Jeg skriver "ikke uden videre," for man kan nemlig godt, det kræver bare lidt snedig "snyd". Mere om dette om et øjeblik.

Gennemløb med Item og en tæller

Forestil dig en class collection, "clKunder", som er en collection af kunder, hvor hver kunde er i en klasse for sig, "clKunde".

Indtil for nylig gennemløb jeg mine egne class collections med en tæller og Item-metoden i stil med dette eksempel, hvor "bBetalt" er en property af datatypen Boolean:


With clKunder
   For lCount = 1 to .Count
      If .Item(lCount).bBetalt = False Then
         'Send straks rykker!
      End If
   Next
End With

Gennemløb med For Each...Next

Det irriterede mig, at jeg ikke kunne bruge den hurtige og enklere For Each...Next løkke, og løsningen fandt jeg på Internet. Fidusen er at eksportere sit klassemodul (her "clKunder"), indlæse filen i en teksteditor (fx Notepad), tilføje en linje med kode, og så importere modulet igen.

Pointen er, at den kodelinje, man tilføjer i Notepad, ikke kan tilføjes i VBA-editoren. Man kan godt, det virker bare ikke.

Når man har tilføjet linjen i Notepad og importeret klassemodulet igen, er linjen ikke synlig i VBA-editoren, men den virker!

Først tilføjede jeg følgende Public Function i klassemodulet:


Public Function NewEnum() As IUnknown
'Denne funktion muliggør gennemløb
'med For Each...Next, fordi følgende
'(usynlige) linje er tilføjet i
'Notepad:
'Attribute NewEnum.VB_UserMemID = -4
    Set NewEnum = clKunder.[_NewEnum]
End Function

Det er altså linjen:

Attribute NewEnum.VB_UserMemID = -4

man skal tilføje i Notepad og selvfølgelig uden apostrof foran.

Det er bare smart. Nu kan jeg gennemløbe mine class collections på denne måde:


Sub Eksempel()
Dim Client as clKunde

For Each Client in clKunder
   If Client.bBetalt = False Then
      'Send straks rykker!
   End If
Next

End Sub

Det synes måske ikke af så meget, men når man har store class collections og mange gennemløb, betyder det faktisk noget for hastigheden, og det giver enklere kode.

Relateret: