Création de classe

   

Accueil

 

Module de classe
Avantages de la programmation objet
Module de classe Liste
Module de classe Base de données
Module de classe Tableau
Module de classe DictionnaireMac pour Excel Mac
Module de classe Dictionnaire avec Tri
Simulation de ArrayList et SortedList
Module de classe Arbre

 

Modules de classe

On peut ajouter aux classes d'objets Excel ses propres classes.
Un objet est l'association de données et de fonctions.

Sur l'exemple, nous avons crée une classe Rectangle dans un module de classe:
-Rectangle est une classe (virtuel)
-'a' est un objet de la classe Rectangle (on instancie la classe Rectangle)

Sub essai
  Set a = New Rectangle                 ' Nouvel objet 'a' classe Rectangle
  a.hauteur = 20                            ' Propriété hauteur
  a.largeur = 30
  MsgBox a.surface                        ' Propriété surface 
  MsgBox a.perimetre                     ' Propriété périmètre
End sub

Classe Rectangle

Avantages de la programmation objet (POO)

-On initialise l'objet 'a' avec des valeurs (hauteur et largeur sur l'exemple). Celles ci sont mémorisées dans l'objet.
-Lorsque que l'on appelle une fonction (propriété) de l'objet (surface ou périmètre), il n'est plus nécessaire de lui passer des paramètres comme on le fait sans programmation objet.
-
La classe gère elle même certains paramètres qui deviennent donc transparents au programmeur d'application.

D'une façon générale, les objets ont :
-des propriétés (valeurs) que l'on peut récupérer ou modifier.
-des méthodes qui agissent sur l'objet.

Création d’une classe

- Insertion/Module de classe
- Nommer le module de Classe Rectangle (Le nom du module représente le nom de la classe)

Private xhauteur As Double
Private xlargeur As Double

Public Property Let hauteur(phauteur)
  xhauteur = phauteur
End Property

Public Property Let largeur(plargeur)
  xlargeur = plargeur
End Property

Public Property Get hauteur()
  hauteur = xhauteur
End Property

Public Property Get largeur()
  largeur = xlargeur
End Property

Public Property Get surface()
  surface = xlargeur * xhauteur
End Property

Public Property Get perimetre()
  perimetre = (xlargeur + xhauteur) * 2
End Property

Classe Liste

La classe Liste gère des listes de couples clé+item.
Elle permet d'ajouter, supprimer et trier ces couples.

ClasseListe      

Clé   

Item

Balu

Balu@hotmail.com

Dupont

Dupont@hotmail.com

Durand

Durand@hotmail.com

Martin

Martin@hotmail.com


Méthodes et propriétés de la classe Liste

obj.Ajout clé,item

Ajoute une clé et la valeur associée

obj.Item(clé)

Donne l'item de la clé

obj.Count(clé)

Donne le nombre de clés

obj.Existe(clé)

Renvoi Vrai si la clé existe

obj.Sup(clé)

Suprime la clé

obj.ListeCles

Renvoie un tableau vertical des clés

obj.ListeItems

Renvoie un tableau vertical des items

obj.Cle(indice)

Donne la clé pour un indice (1,2,3,...)

obj.Tri

Tri les clés

Sub essaiClasseListe()
  Set MaListe = New Liste ' instanciation de la classe Liste
  MaListe.Ajout "Dupont", "Dupont@hotmail.com"       ' ajout élément à l'objet a
  MaListe.Ajout "Martin", "Martin@hotmail.com"
  MaListe.Ajout "Durand", "Durand@hotmail.com"
  MaListe.Ajout "Balu", "Balu@hotmail.com"
  cle = "Durand"
  MsgBox "Email de " & cle & ": " & MaListe.item(cle)    ' affiche email de Durand
  MaListe.Tri                                                              ' tri objet Maliste
  Set plg = Range("a2").Resize(MaListe.count)
  Range("a2").Resize(MaListe.count) = MaListe.ListeCles
  Range("b2").Resize(MaListe.count) = MaListe.ListeItems
  MaListe.Sup "Dupont" ' suppression de Dupont
  MaListe.Ajout "Zoe", "Zoe@hotmail.com"
  Range("d2").Resize(MaListe.count) = MaListe.ListeCles
  Range("e2").Resize(MaListe.count) = MaListe.ListeItems
  indice = 2
  MsgBox "Clé " & indice & ":" & MaListe.cle(indice)
  MsgBox "Item " & indice & ":" & MaListe.ItemInd(indice)
  i = 2
  For Each c In MaListe.ListeCles
     Cells(i, "g") = c
     i = i + 1
  Next c
End Sub

Module de classe Liste

Option Compare Text
Private table()
Private xn

Private Sub class_initialize()
  xn = 0
End Sub

Sub Ajout(cle, item)
  xn = xn + 1
  ReDim Preserve table(1 To 2, 1 To xn)
  table(1, xn) = cle
  table(2, xn) = item
End Sub

Sub Sup(cle)
  p = 0
  For i = 1 To xn
    If table(1, i) = cle Then
       p = i
    End If
  Next i
  If p > 0 Then
    For i = p To xn - 1
     table(1, i) = table(1, i + 1)
     table(2, i) = table(2, i + 1)
   Next i
   xn = xn - 1
   ReDim Preserve table(1 To 2, 1 To xn)
  End If
End Sub

Property Get count()
  count = xn
End Property

Property Get Existe(cle)
   témoin = False
   For i = 1 To xn
     If table(1, i) = cle Then témoin = True
   Next i
   Existe = témoin
End Property

Property Get item(cle)
  temp = False
  i = 1
  témoin = False
  Do While i < xn And Not témoin
    If table(1, i) = cle Then
      temp = table(2, i)
      témoin = True
    End If
    i = i + 1
  Loop
  item = temp
End Property

Property Get cle(indice)
  If indice <= xn Then cle = table(1, indice) Else cle = ""
End Property

Property Get ItemInd(indice)
  If indice <= xn Then ItemInd = table(2, indice) Else ItemInd = ""
End Property

Property Get ListeCles()
  Dim temp()
  ReDim temp(1 To xn)
  For i = 1 To xn
    temp(i) = table(1, i)
  Next i
  ListeCles = Application.Transpose(temp)
End Property

Property Get ListeItems()
  Dim temp()
  ReDim temp(1 To xn)
  For i = 1 To xn
    temp(i) = table(2, i)
  Next i
  ListeItems = Application.Transpose(temp)
End Property

Public Sub Tri()
  Call Quick(table, 1, xn)
End Sub

Private Sub Quick(a, gauc, droi) ' Quick sort
  ref = a(1, (gauc + droi) \ 2)
  g = gauc: d = droi
  Do
    Do While a(1, g) < ref: g = g + 1: Loop
    Do While ref < a(1, d): d = d - 1: Loop
    If g <= d Then
      temp = a(1, g): a(1, g) = a(1, d): a(1, d) = temp
      temp = a(2, g): a(2, g) = a(2, d): a(2, d) = temp
      g = g + 1: d = d - 1
    End If
  Loop While g <= d
  If g < droi Then Call Quick(a, g, droi)
  If gauc < d Then Call Quick(a, gauc, d)
End Sub

Classe Base de données

La classe BD gère des enregistrements.
Elle permet d'ajouter, supprimer et trier des enregistrements.
C'est l'équivalent de SortedList avec plusieurs champs.
Construite avec l'objet Dictionary, elle permet d'accéder directement (rapidement) à un engistrement par une clé. Elle peut remplacer avantageusement des tableaux de taille importante. Les ajouts et suppressions sont plus faciles à gérer que dans un tableau classique.

ClasseBD Dictionary
ClasseBD Collection   

Nom

Age

Ville

Balu

33

Versailles

Dupont

30

Paris

Durand

35

Issy

Martin

34

Montigny

Méthodes et propriétés de la classe BD

obj.Ajout enreg()

Ajoute un enregistrement (tableau 1D)

obj.AjoutChamp champ

Ajoute un champ

obj.ListeEnreg(clé)

Donne l'enregistrement de la clé

obj.Count()

Donne le nombre de clés

obj.Existe(clé)

Renvoi Vrai si la clé existe

obj.Sup(clé)

Suprime la clé

obj.ListeCles

Renvoie un tableau vertical des clés

obj.ListeBD

Renvoie un tableau avec le contenu de la BD

obj.Item(clé,colonne)

Donne l'item de la colonne spécifiée

obj.Tri

Tri les clés

obj.TriCol(tableau,colonne,"A ou D")

Tri par colonne A/D

obj.TriColMult(tableau,col1,col2,col3)

Tri par colonnes

obj.Stat2DCompte(tableau,col1,col2)

Stats 2D

obj.GetEnregsColCle(tableau,col,crit)

Sélection enregs pour un critère

Sub GestionBD()
  Set mabd = New BD
  a = [A2:C5]
  nchamp = UBound(a, 2) - LBound(a, 2) + 1
  Dim t(): ReDim t(1 To nchamp)
  For i = LBound(a) To UBound(a)     ' on alimente la BD
    For k = 1 To nchamp: t(k) = a(i, k): Next k
    mabd.Ajout t()
  Next i
  Range("a2").Resize(mabd.count, 3) = mabd.ListeBD    ' liste de la BD
  Range("a10").Resize(mabd.count, 3) = mabd.Tri     ' liste triée par noms
End Sub

Sub TriMult()
  Set mabd = New BD
  mabd.AjoutChamp ([A2:C5])
  Range("a17").Resize(mabd.count, mabd.NbChamp) = mabd.TriColMult(3, 2)
  Range("e17").Resize(mabd.count, mabd.NbChamp) = mabd.TriCol(2, "D")
  Range("a17").Resize(mabd.count, mabd.NbChamp) = mabd.TriCol(3, "A")
  Range("a17").Resize(mabd.count, mabd.NbChamp) = mabd.TriColMult(3, 1)
End Sub

Sub Stats()
  Set mabd = New BD
  mabd.AjoutChamp ([A2:C5])
  a = mabd.Stat2DCompte(2, 3)
  [A40].Resize(UBound(a), UBound(a, 2)) = a
End Sub

Sub Selection()
  Set mabd = New BD
  mabd.AjoutChamp ([A2:C5])
  a = mabd.GetEnregsColCle(3, "paris")
  [A44].Resize(UBound(a), UBound(a, 2)) = a
End Sub

Module de classe BD

Option Compare Text
Private Dict, nchamp

Private Sub class_initialize()
  Set Dict = CreateObject("Scripting.Dictionary")
  Dict.CompareMode = vbTextCompare
End Sub

Property Let NbChamp(NewChamp)
  If nchamp = 0 Then nchamp = NewChamp
End Property

Property Get NbChamp()
  NbChamp = nchamp
End Property

Sub Ajout(Enreg())
  Dict(Enreg(LBound(Enreg))) = Enreg()
  NbChamp = UBound(Enreg) - LBound(Enreg) + 1
End Sub

Sub AjoutChamp(Champ As Range)
  a = Champ
  Dim t(): ReDim t(LBound(a, 2) To UBound(a, 2))
  NbChamp = UBound(a, 2) - LBound(a, 2) + 1
  For i = LBound(a) To UBound(a) ' on alimente la BD
    For col = LBound(a, 2) To UBound(a, 2)
       t(col) = a(i, col)
    Next col
    Ajout t()
  Next i
End Sub

Property Get count()
  count = Dict.count
End Property

Property Get listeCles()
   listeCles = Application.Transpose(Dict.keys)
End Property

Property Get Existe(cle)
   Existe = Dict.Exists(cle)
End Property

Property Let Sup(cle)
  Dict.Remove (cle)
End Property

Property Get ListeEnreg(cle)
   temp = Dict(cle)
   ListeEnreg = temp
End Property

Function item(cle, col)
   temp = Dict(cle)
   item = temp(col)
End Function

Property Get ListeBD()
  Dim tbl()
  ReDim tbl(1 To Dict.count, 1 To nchamp)
  lig = 1
  For Each k In Dict.keys
    temp = Dict(k): decal = IIf(LBound(temp) = 0, 1, 0)
    For col = LBound(temp) To UBound(temp): tbl(lig, col + decal) = temp(col): Next col
   lig = lig + 1
  Next k
  ListeBD = tbl
End Property

Function Tri()
  temp = Dict.keys
  Call Quick(temp, LBound(temp), UBound(temp))
  Dim tbl()
  ReDim tbl(LBound(temp) To Dict.count - 1, 1 To nchamp)
  For lig = LBound(temp) To UBound(temp)
    tmp = Dict(temp(lig)): decal = IIf(LBound(tmp) = 0, 1, 0)
    For col = LBound(tmp) To UBound(tmp): tbl(lig, col + decal) = tmp(col): Next col
  Next lig
  Tri = tbl
End Function

Private Sub Quick(a, gauc, droi) ' Quick sort
  ref = a((gauc + droi) \ 2)
  g = gauc: d = droi
  Do
    Do While a(g) < ref: g = g + 1: Loop
    Do While ref < a(d): d = d - 1: Loop
    If g <= d Then
      temp = a(g): a(g) = a(d): a(d) = temp
      g = g + 1: d = d - 1
    End If
  Loop While g <= d
  If g < droi Then Call Quick(a, g, droi)
  If gauc < d Then Call Quick(a, gauc, d)
End Sub

Private Sub class_terminate()
   Set Dict = Nothing
End Sub

Function TriCol(Optional colTri, Optional ordre)
  If IsMissing(colTri) Then colTri = "A"
  If IsMissing(ordre) Then ordre = 1
  tbl = ListeBD
  Select Case UCase(ordre)
     Case "A": Call QuickA(tbl, LBound(tbl), UBound(tbl), colTri)
     Case "D": Call QuickD(tbl, LBound(tbl), UBound(tbl), colTri)
     Case Else: Call QuickA(tbl, LBound(tbl), UBound(tbl), colTri)
  End Select
  TriCol = tbl
End Function

Module de classe Tableau

Cette classe Tableau:

-Tri un tableau déjà existant en ordre croissant/décroissant suivant la colonne spécifiée.
-Effectue des tris multi-critères.
-Donne des statistiques sur les tableaux (compte et somme suivant un critère)
-Sélectionne des lignes d'un tableau en fonction d'un critère.

Classe Tableau

obj.TriTab(tableau,col,"A ou D")

Tri par colonne A/D

obj.TriTabMult(tableau,col1,col2,col3)

Tri par colonnes

obj.Stat2DCompte(tableau,col1,col2)

Stats 2D compte

obj.Stat2DSomme(tableau,col1,col2)

Stats 2D somme

obj.GetLignesColCle(tableau,col,crit)

Sélection enregs pour un critère

Sub Tris()
  Tablo = [a2:D6].Value
  Set monTab = New Tableau             ' instanciation de la classe Tableau
  monTab.TriTab Tablo, 1              ' Tri col 1 
  [a2:D6] = Tablo
  monTab.TriTab Tablo, 2, "D"       ' Tri col 2 décroissant
  [F2:I6] = Tablo
  monTab.TriTabMult Tablo, 4, 1    ' Tri multi crit col 4, col 1
  [k2:N6] = Tablo
End Sub

Sub Stats()
  Tablo = [a3:D8].Value
  Set monTab = New Tableau
  b = monTab.Compte(Tablo, 3)       ' compte sur la colonne 3
  monTab.TriTab b, 2, "D"
  [k16].Resize(UBound(b), 2) = b
  b = monTab.Somme(Tablo, 3, 2)    ' somme sur colonne 2 en fonction du critère colonne 2
  monTab.TriTab b, 2, "D"
  [k23].Resize(UBound(b), 2) = b
  b = monTab.Stat2DCompte(Tablo, 1, 3) ' Stats 2D compte
  [k40].Resize(UBound(b), UBound(b, 2)) = b
  b = monTab.Stat2DSomme(Tablo, 1, 3, 2) ' Stats 2d somme
  [k50].Resize(UBound(b), UBound(b, 2)) = b
End Sub

Filtre un tableau avec 1 critère.

Sub SelectionLignesColCle()
  Tablo = [a3:D8].Value
  Set monTab = New Tableau
  a = monTab.GetLignesColCle(Tablo, 3, "paris") ' Sélection des lignes pour Paris
  [k30].Resize(UBound(a), UBound(a, 2)) = a
End Sub

Filtre un tableau avec 1 ou 2 critères. On choisi les colonnes résultat.

Sub FiltreArray()
  Dim montab As tableau
  Set montab = New tableau
  tablo = [a3:D8].Value
  b = montab.FiltreArray(tablo, 3, "Paris", Array(1, 2, 4))
  [k75].Resize(UBound(b) - LBound(b) + 1, UBound(b, 2)).Value2 = b
End Sub

Module de classe Tableau

Option Compare Text

Sub TriTab(Tbl, Optional colTri, Optional ordre)
  If IsMissing(colTri) Then colTri = 1
  If IsMissing(ordre) Then ordre = 1
  Dim clé(): ReDim clé(LBound(Tbl) To UBound(Tbl))
  Dim idx() As Long: ReDim idx(LBound(Tbl) To UBound(Tbl))
  Dim b(): ReDim b(LBound(Tbl) To UBound(Tbl), LBound(Tbl, 2) To UBound(Tbl, 2))
  For i = LBound(Tbl) To UBound(Tbl)
     clé(i) = Tbl(i, colTri)
     idx(i) = i
  Next i
  Select Case UCase(ordre)
    Case "A": Call QuickI(clé(), idx(), LBound(clé), UBound(clé))
    Case "D": Call QuickIDesc(clé(), idx(), LBound(clé), UBound(clé))
    Case Else: Call QuickI(clé(), idx(), LBound(clé), UBound(clé))
  End Select
  For lig = LBound(clé) To UBound(clé)
     For col = LBound(Tbl, 2) To UBound(Tbl, 2): b(lig, col) = Tbl(idx(lig), col): Next col
  Next lig
  For lig = LBound(clé) To UBound(clé)
      For col = LBound(Tbl, 2) To UBound(Tbl, 2): Tbl(lig, col) = b(lig, col): Next col
  Next lig
End Sub

Sub TriTabMult(tbl, Optional ColTri1, Optional Coltri2)
  If IsMissing(ColTri1) Then ColTri1 = 1
  If IsMissing(Coltri2) Then Coltri2 = 2
  Dim clé() As String: ReDim clé(LBound(tbl) To UBound(tbl))
  Dim idx() As Long: ReDim idx(LBound(tbl) To UBound(tbl))
  Dim b(): ReDim b(LBound(tbl) To UBound(tbl), LBound(tbl, 2) To UBound(tbl, 2))
  If IsNumeric(tbl(1, ColTri1)) Or IsDate(tbl(1, ColTri1)) Then tri1 = "num"
  If IsNumeric(tbl(1, Coltri2)) Or IsDate(tbl(1, Coltri2)) Then tri2 = "num"
  For i = LBound(tbl) To UBound(tbl)
     If tri1 = "num" Then col1 = Format(tbl(i, ColTri1), "0000000") Else col1 = tbl(i, ColTri1)
     If tri2 = "num" Then col2 = Format(tbl(i, Coltri2), "0000000") Else col2 = tbl(i, Coltri2)
     clé(i) = col1 & "_" & col2
   idx(i) = i
  Next i
  Call QuickI(clé(), idx(), LBound(clé), UBound(clé))
  For lig = LBound(clé) To UBound(clé)
     For col = LBound(tbl, 2) To UBound(tbl, 2): b(lig, col) = tbl(idx(lig), col): Next col
  Next lig
  For lig = LBound(clé) To UBound(clé)
     For col = LBound(tbl, 2) To UBound(tbl, 2): tbl(lig, col) = b(lig, col): Next col
  Next lig
End Sub

Sub QuickI(clé(), index() As Long, gauc, droi) ' Quick sort
  ref = clé((gauc + droi) \ 2)
  g = gauc: d = droi
  Do
    Do While clé(g) < ref: g = g + 1: Loop
    Do While ref < clé(d): d = d - 1: Loop
      If g <= d Then
         temp = clé(g): clé(g) = clé(d): clé(d) = temp
         temp = index(g): index(g) = index(d): index(d) = temp
         g = g + 1: d = d - 1
      End If
    Loop While g <= d
    If g < droi Then Call QuickI(clé, index, g, droi)
    If gauc < d Then Call QuickI(clé, index, gauc, d)
End Sub

Simulation de l'objet Dictionary pour Excel Mac

Pour simuler l'objet Dictionary sur Excel Mac, on crée un module de classe DictionnaireMac.

ClasseDictionnaireMacCollection
ClasseDictionnaireMacTableau

Méthodes et propriétés

Dico.Ajout clé,item

Ajoute une clé et la valeur associée

Dico.Existe(clé)

Teste l'existence d'une clé

Dico.Item(clé)

Donne l'item de la clé

Dico.Count(clé)

Donne le nombre de clés

Dico.Sup clé

Suprime la clé

Dico.ListeCles

Renvoie un tableau vertical des clés

Dico.ListeItems

Renvoie un tableau vertical des items

Dico.Cle(indice)

Donne la clé pour un indice (1,2,3,...)

Dico.Tri

Tri les clés

Exemple 1: Sur cet exemple, nous obtenons une liste sans doublons.

Sur l'exemple, nous créons un dictionnaire avec les noms comme clés et les villes comme items.
Les doublons de Nom1 seront éliminés.

Noms Villes
Nom1 Ville1
Nom2 Ville2
Nom3 Ville3
Nom4 Ville4
Nom1 Ville1
Nom1 Ville1
Nom7 Ville7

Code

Sub ListeSansDoublonsCollection()
  Set d1 = New DictionnaireMac
  Set plage1 = Range("A2", [a65000].End(xlUp))
  For Each c In plage1
      If c <> "" Then d1.ajout c.Value, c.Offset(, 1).Value
  Next c
  '-------- transfert dans le tableur
  Range("d2").Resize(d1.count) = d1.listeCles
  Range("e2").Resize(d1.count) = d1.listeItems
  [P2].Resize(d1.count, 2) = d1.Tri
End Sub

Module de classe DictionnaireMac

L'option Key de la classe Collection permet d'interdire les doublons à la création et d'accéder à un item par une clé mais elle ne permet pas d'accéder à l'ensemble des clés. Pour accéder à l'ensemble des clés, nous utilisons une deuxième collection (CollecCle).
L'objet Collec stocke les items et l'objet CollecCle les clés

Cette classe simule la classe Dictionary en lui ajoutant un Tri.
Elle peut remplacer SortedList. Elle permet par exemple:
- d'obtenir des listes triées sans doublon,
- d'effectuer des tris multi-critères de tableaux à 2 dimensions,...

Option Compare Text
Private xn
Private Collec As New Collection
Private CollecCle As New Collection

Sub ajout(cle, item)
  On Error Resume Next
  Collec.Add item:=item, Key:=cle
  CollecCle.Add item:=cle, Key:=cle
  If Err = 0 Then xn = xn + 1
End Sub

Property Get count()
  count = xn
End Property

Property Get listeItems()
  Dim temp()
  ReDim temp(1 To xn)
  For i = 1 To xn
    temp(i) = Collec(i)
  Next i
  listeItems = Application.Transpose(temp)
End Property

Property Get listeCles()
  Dim temp()
  ReDim temp(1 To xn)
  For i = 1 To xn
    temp(i) = CollecCle(i)
  Next i
  listeCles = Application.Transpose(temp)
End Property

Property Get item(cle)
  item = Collec(cle)
End Property

Property Get Existe(cle)
  On Error Resume Next
  retour = Collec(cle)
  Existe = (Err = 0)
End Property

Property Get cle(indice)
  If indice <= xn Then cle = CollecCle(indice) Else cle = ""
End Property

Property Get ItemInd(indice)
  If indice <= xn Then ItemInd = Collec(indice) Else ItemInd = ""
End Property

Sub Sup(cle)
  p = 0
  For i = 1 To xn
     If CollecCle(i) = cle Then p = i
  Next i
  If p > 0 Then
    CollecCle.Remove p
    Collec.Remove p
    xn = xn - 1
  End If
End Sub

Function Tri()
  Dim temp()
  ReDim temp(1 To xn, 1 To 2)
  For i = 1 To xn
    temp(i, 1) = CollecCle(i)
    temp(i, 2) = Collec(i)
  Next i
  Call Quick(temp, LBound(temp), UBound(temp))
  Tri = temp
End Function

Private Sub Quick(a, gauc, droi) ' Quick sort
  ref = a((gauc + droi) \ 2, 1)
  g = gauc: d = droi
  Do
    Do While a(g, 1) < ref: g = g + 1: Loop
    Do While ref < a(d, 1): d = d - 1: Loop
    If g <= d Then
      temp = a(g, 1): a(g, 1) = a(d, 1): a(d, 1) = temp
      temp = a(g, 2): a(g, 2) = a(d, 2): a(d, 2) = temp
      g = g + 1: d = d - 1
    End If
  Loop While g <= d
  If g < droi Then Call Quick(a, g, droi)
  If gauc < d Then Call Quick(a, gauc, d)
End Sub

Classe Dictionnaire

Cette classe encapsule la classe Dictionary en lui ajoutant un Tri.
Elle peut remplacer SortedList. Elle permet par exemple:
- d'obtenir des listes triées sans doublon ( 0,36s pour 10.000 items)
- d'effectuer des tris multi-critères de tableaux à 2 dimensions,...

Classe Dictionnaire Tri
Classe DictionarySorted David84

Sub ListeSansDoublonsDicoTrié()
  Set d1 = New Dictionnaire
  a = Range("A2:B" & [A65000].End(xlUp).Row)
  For i = 1 To UBound(a)
    d1.ajout a(i, 1), a(i, 2)
  Next i
  '--- résultat dans le tableur
  Range("d2").Resize(d1.Count, 2) = d1.Tri
  '-- résultat dans un tableau
  a = d1.Tri
End Sub

Module de classe Dictionnaire

Private Dict
Option Compare Text

Private Sub class_initialize()
  Set Dict = CreateObject("Scripting.Dictionary")
  Dict.CompareMode = vbTextCompare
End Sub

Sub ajout(cle, item)
  If Not Dict.Exists(cle) Then Dict(cle) = item
End Sub

Property Get Count()
  Count = Dict.Count
End Property

Property Get listeItems()
  listeItems = Application.Transpose(Dict.Items)
End Property

Property Get listeCles()
  listeCles = Application.Transpose(Dict.keys)
End Property

Property Get item(cle)
  item = Dict(cle)
End Property

Property Get Existe(cle)
  Existe = Dict.Exists(cle)
End Property

Sub Sup(cle)
  Dict.Remove cle
End Sub

Function Tri()
  Dim temp()
  ReDim temp(1 To Dict.Count, 1 To 2)
  i = 1
  For Each c In Dict.keys
    temp(i, 1) = c
    temp(i, 2) = Dict(c)
    i = i + 1
  Next c
  Call Quick(temp, LBound(temp), UBound(temp))
  Tri = temp
End Function

Private Sub Quick(a, gauc, droi) ' Quick sort
  ref = a((gauc + droi) \ 2, 1)
  g = gauc: d = droi
  Do
    Do While a(g, 1) < ref: g = g + 1: Loop
    Do While ref < a(d, 1): d = d - 1: Loop
    If g <= d Then
      temp = a(g, 1): a(g, 1) = a(d, 1): a(d, 1) = temp
      temp = a(g, 2): a(g, 2) = a(d, 2): a(d, 2) = temp
      g = g + 1: d = d - 1
    End If
  Loop While g <= d
  If g < droi Then Call Quick(a, g, droi)
  If gauc < d Then Call Quick(a, gauc, d)
End Sub

Private Sub class_terminate()
  Set Dict = Nothing
End Sub

Simulation de ArrayList et SortedList

Dans le fichier ci dessous, on trouvera un module de classe Aliste(tableau 1 dimension trié) qui remplace ArrayList (+rapide)

Classe AListe

Dans le fichier ci dessous, on trouvera un module de classe Sliste (tableau 2D trié) qui remplace SortedList (Il est 2 fois +rapide :0,28s pour 10.000 lignes).
En outre, il accepte les doublons. Si on veut supprimer ces derniers, on peut utiliser Dictionary qui est très rapide.
Cette classe peut être utilisée pour trier des tableaux multi-dimensionnel.

Classe SListe
Classe SortedListe Collection David 84

Module de classe Arborescence/Organigramme

Classe ArbreTableau
ArbreTableau
Classe ArbreDictionary

Sub DessineBrancheArbre()
  Set a = New Arbre
  a.Ajout = "aa,,Attribut1"
  a.Ajout = "bb,aa,Attribut2"
  a.Ajout = "cc,aa,Attribut3"
  a.Ajout = "dd,aa,Attribut4"
  a.Ajout = "ee,bb,Attribut5"
  a.Ajout = "ff,bb,Attribut6"
  a.Ajout = "gg,dd,Attribut7"
  a.Ajout = "hh,ee,Attribut8"
  a.Ajout = "ii,ee,Attribut9"
  a.Ajout = "jj,hh,Attribut10"
  a.Ajout = "kk,hh,Attribut11"
  a.DessineBrancheShapes = "aa,feuil1"
  a.DessineBrancheShapes = "bb,feuil2"
  Sheets("feuil1").Select
End Sub

Sub ArbreBD()
  Set a = New Arbre
  Set f = Sheets("bd")
  For i = 2 To f.[A65000].End(xlUp).Row
     a.Ajout = f.Cells(i, 1) & "," & f.Cells(i, 2) & "," & f.Cells(i, 3)
  Next i
  a.DessineBrancheShapes = "aa,feuil1"
  a.DessineBrancheShapes = "bb,feuil2"
End Sub

Module de classe

Private Tbl(1 To 100, 1 To 4)
Private n, branche, débutOrg, fbd, inth, intv, colonne

Public Property Let Ajout(FilsPèreAttribut)
   a = Split(FilsPèreAttribut, ",")
   clé = a(0): élem = a(1)
   n = n + 1
   Tbl(n, 1) = a(0): Tbl(n, 2) = élem: Tbl(n, 3) = a(2)
End Property

Public Property Let DessineBrancheShapes(pèreFeuille)
  a = Split(pèreFeuille, ",")
  Set fbd = Sheets(a(1))
  For Each s In fbd.Shapes
     If s.Type = 17 Or s.Type = 1 Then s.Delete
  Next s
  tmp = a(0)
  créeShape tmp, 1, Attribut(tmp)
  Set débutOrg = fbd.Range("c4")
  colonne = 0
  inth = 50
  intv = 40
  PosShape tmp, 1
End Property

Public Property Get affiche()
  tmp = ""
  For p = 1 To n
    If Tbl(p, 1) <> "" Then tmp = tmp & "Fils:" & Tbl(p, 1) & " - père:" & Tbl(p, 2) & vbLf
  Next p
  affiche = tmp
End Property

Public Property Get liste()
  tmp = ""
  For p = 1 To n
    If Tbl(p, 1) <> "" Then tmp = tmp & Tbl(p, 1) & "," & Tbl(p, 2) & "," & Tbl(p, 3) & ":"
  Next p
  liste = Left(tmp, Len(tmp) - 1)
End Property

Public Property Get Père(Fils)
  For i = 1 To n
    If Tbl(i, 1) = Fils Then Père = Tbl(i, 2)
  Next   i
End Property

Public Property Get Attribut(Fils)
  For i = 1 To n
    If Tbl(i, 1) = Fils Then Attribut = Tbl(i, 3)
  Next i
End Property

Sub créeShape(parent, niv, Attribut) ' procédure récursive
  hauteurshape = 30
  largeurshape = 50
  fbd.Shapes.AddTextbox(msoTextOrientationHorizontal, 10, 10, largeurshape, hauteurshape).Name = parent
  fbd.Shapes(parent).Line.ForeColor.SchemeColor = 22
  txt = parent & vbLf & Attribut
  With fbd.Shapes(parent)
   .TextFrame.Characters.Text = txt
   .TextFrame.Characters(Start:=1, Length:=1000).Font.Size = 8
   .TextFrame.Characters(Start:=1, Length:=Len(parent)).Font.Bold = True
   .Fill.ForeColor.RGB = RGB(255, 255, 255)
  End With
  For i = 1 To n
    If Tbl(i, 2) = parent Then créeShape Tbl(i, 1), niv + 1, Tbl(i, 3)
  Next i
End Sub

Sub PosShape(parent, niv) ' procédure récursive
  colonne = colonne + 1
  fbd.Shapes(parent).Left = débutOrg.Left + inth * colonne
  fbd.Shapes(parent).Top = débutOrg.Top + intv * (niv - 1)
  For i = 1 To n
    If Tbl(i, 1) = parent And niv > 1 Then
      shapePère = Tbl(i, 2)
      fbd.Shapes.AddConnector(msoConnectorElbow, 813.75, 258.75, 885.75, 330.75).Name = parent & "c"
      fbd.Shapes(parent & "c").Line.ForeColor.SchemeColor = 22
      fbd.Shapes(parent & "c").ConnectorFormat.BeginConnect fbd.Shapes(shapePère), 3
       fbd.Shapes(parent & "c").ConnectorFormat.EndConnect fbd.Shapes(parent), 1
    End If
    If Tbl(i, 2) = parent Then PosShape Tbl(i, 1), niv + 1
  Next i
End Sub

Exemples

jb-ObjetsClassesSynthèse
Calculette
SaisieObligatoireToutesZones
FormCheckBoxClasse
FormComboBoxClasse
FormTotalisation