[VBA] Collections de classes et collections d’objets

Dernière mise à jour le 2 novembre 2009 à 17:30 par marlalapocket
Publié par lermite222
Cette démo emploi, comme le titre l’indique, des collections différentes.
Elle ne comporte que deux séries de cinq contrôles mais peut en gérer beaucoup plus avec le même nombre de lignes de code.



Introduction


Elles permettent de gérer des séries de contrôles uniquement avec leurs index, que ce soit pour les événements des contrôles ou pour leurs propriétés. Pour ceux qui connaissent VB6, exactement comme les contrôles indexés.
Les collections de classes pour gérer les événements.
Les collections d’objet pour gérer les propriétés.
Les événements sont directement renvoyer dans l'Userform où les contrôles peuvent alors êtres traités directement par leur index.
La propriété contrôle.TAG est utilisée pour indiquer l’index du contrôle.

Les contrôles sur une feuille de calcul


Les collections peuvent aussi êtres employées pour des contrôles situés sur des feuilles Excel, mais ils ne disposent pas de la propriété contrôle.TAG, il est possible de remédier à cet inconvénient en utilisant la propriété contrôle. Name.
Ajouter en fin du nom du contrôle, par exemple pour index 1 >> 01, qu’importe le nom, il y aurait donc, en supposant que ce soit un TextBox nommé TxtNom deviendrait TxtNom01, TxtPrenom deviendrait TxtPrenom02, etc. Jusque 99. Si plus de 99 contrôles de la même série ajouter une 3ième valeur en commençant par 001.. Jusque 999 et tester les 3 dernier caractères du nom.
Et pour déterminer l’index (quand il est question de Tag dans les démo), employer Val(Right(Groupe.name, 2)). (ou 3 pour aller jusqu’à 999)
Attention, quelques variantes pour initialiser les contrôles dans une feuille, Voir cette astuce pour initialiser les contrôles dans une feuille

L'Userform


La démo ci-dessous marque les contrôles survolés en modifiant leurs propriétés.
Il fallait bien que je trouve un support pour mettre ces collections en pratique.

Ajouter la référence « Microsoft Forms X.X Object Library » si elle n’est pas présente.
Dans un Userform nommé « UF_DemoCC »
LA FORME
Coller 5 boutons (qu’importe le nom) avec Tag=1, =2, =3, =4, =5
Coller un 6ième bouton, Tag = 11, Caption = Quitter la démo
Coller 5 Labels, idem pour les tag de 1 à 5

Le code de l'UserForm


Option Explicit
'------------------------------------
'Déclaration des collections
Dim CollectBouton As Collection
Dim CollectLabel As Collection
Dim ClLabel
Dim ClBouton
'------------------------------------
'Déclaration pour les instances de classe
Dim mBouton As CL_DemoCC
Dim mLabel As CL_DemoCC
'------------------------------------
Dim MemIndex As Integer

Private Sub UserForm_Initialize()
Dim Ctl As Control
'--------------------------------------------------------
'Crée les collection de classe
    Set CollectBouton = New Collection
    Set CollectLabel = New Collection
'--------------------------------------------------------
'Crée les collections d'objet
    Set ClBouton = New Collection
    Set ClLabel = New Collection
'--------------------------------------------------------
    
    For Each Ctl In Me.Controls
        'verifie s'il s'agit d'un bouton
        If TypeOf Ctl Is MSForms.CommandButton Then
            'Ajoute dans la collection des classes boutons
            Set mBouton = New CL_DemoCC
            Set mBouton.GroupBoutons = Ctl
            CollectBouton.Add mBouton
            'Ajoute dans la collection des Objets boutons
            ClBouton.Add Ctl
        ElseIf TypeOf Ctl Is MSForms.Label Then
            'Ajoute dans la collection des classes labels
            Set mLabel = New CL_DemoCC
            Set mLabel.GroupLabels = Ctl
            CollectLabel.Add mLabel
            'Ajoute dans la collection des Objets labels
            ClLabel.Add Ctl
        End If
    Next Ctl
End Sub

Public Sub BoutonMouseMove(ByVal Index As Integer, Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'Evite de réinitialiser si l'index n'a pas changé.
'6 c'est pour le bouton QUITTE qui n'a pas de label associé.
    If MemIndex = Index Or Index = 6 Then Exit Sub
    Remet
'Marque les contrôles survolé par le pointeur de souris
    ClLabel(Index).SpecialEffect = 1
    ClLabel(Index).ForeColor = &HFFFF&
    ClBouton(Index).BackStyle = 0
    ClBouton(Index).ForeColor = &H8080FF
    MemIndex = Index
End Sub

'Réinitialise les contrôles sélectionnés en mode d’origine
Sub Remet()
    If MemIndex = 0 Then Exit Sub
    ClLabel(MemIndex).SpecialEffect = 0
    ClLabel(MemIndex).ForeColor = &HFFFF00
    ClBouton(MemIndex).BackStyle = 1
    ClBouton(MemIndex).ForeColor = &HFFFF&
End Sub

Sub BoutonClick(ByVal Index As Integer)
    If Index = 6 Then 'Bouton QUITTE LA DEMO
        Unload Me
    Else
        Transfer(1) = ClBouton(Index).Name
        Transfer(2) = ClBouton(Index).Caption
        Transfer(3) = Index
        Transfer(4) = ClLabel(Index).Name
        Transfer(5) = ClLabel(Index).Caption
        Transfer(6) = "Bouton"
‘Eventuellement un UF d’affichage joint dans la démo mais pas dans cet exemple
       ‘ Affiche.Show
    End If
End Sub
Sub LabelClick(ByVal Index As Integer)
    Transfer(1) = ClLabel(Index).Name
    Transfer(2) = ClLabel(Index).Caption
    Transfer(3) = Index
    Transfer(4) = ClBouton(Index).Name
    Transfer(5) = ClBouton(Index).Caption
    Transfer(6) = "Label"
‘Eventuellement un UF d’affichage joint dans la démo mais pas dans cet exemple
   ‘ Affiche.Show
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Remet
    MemIndex = 0
End Sub

Le module de classe


Dans un Module de classe nommé « CL_DemoCC »

Le code


Option Explicit
Public WithEvents GroupBoutons As MSForms.CommandButton
Public WithEvents GroupLabels As MSForms.Label

Private Sub GroupBoutons_Click()
    Call UF_DemoCC.BoutonClick(GroupBoutons.Tag)
End Sub

Private Sub GroupBoutons_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
 'Pour exemple
 '   Call UF_DemoCC.BoutonMouseDown(GroupLabels.Tag, Button, Shift, X, Y)
End Sub

Private Sub GroupBoutons_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Call UF_DemoCC.BoutonMouseMove(GroupBoutons.Tag, Button, Shift, X, Y)
End Sub
Private Sub GroupLabels_Click()
    Call UF_DemoCC.LabelClick(GroupLabels.Tag)
End Sub

Private Sub GroupLabels_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

End Sub

Private Sub GroupLabels_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Call UF_DemoCC.BoutonMouseMove(GroupLabels.Tag, Button, Shift, X, Y)
End Sub End Sub

Private Sub GroupLabels_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
‘Ne sert pas, juste comme exemple.

End Sub

Private Sub GroupLabels_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Call UF_DemoCC.GroupMouseMove(GroupLabels.Tag, Button, Shift, X, Y)
End Sub

Le module public


Dans un module général.
Option Explicit
Public Transfer(6)

Téléchargement


Vous pouvez télécharger les deux démos.

Démo 1


Utilisation de deux collections de Classe pour les événements des contrôles.
Utilisation de deux collections d'objets pour les propriétés des contrôles.
Remarque importante :
Les index dans les collections d'objet ne sont pas déterminés par le .Tag mais
par leur ORDRE DE CREATION sur la forme.
Vous devez donc en tenir compte quand vous faite le design de la forme.
Pour des contrôles gérer par une clé voir la deuxième démo.
sur Cijoint.fr

Démo 2


Pour cette démo j'ai utilisé la propriété Key, il n'est donc pas nécessaire de tenir compte de l'ordre de création des contrôles.
Un inconvéniant : Key DOIT être en string,
Il faut donc transcrire les index en string, heureusement, VB fait ça pour nous
sauf en cas de calcul, par exemple si index est en string Index + 5 va bien être calculé mais
le résultat sera un nombre, il faut donc mettre Cstr(Index + 5)
Pour démontrer cette possibilité j'ai mis les labels ET les boutons dans la même collection en ajustant les .Tag de 1 à 10
1 à 5 pour les boutons et de 6 à 10 pour les labels, de cette façon il est bien démontrer que ce sont les clés qui sont prise en compte.
Cette façon de procéder est plus souple, elle ne tient pas compte de l'ordre de création des contrôles.
sur Cjoint.fr
Meilleures réponses pour « Collections de classes et collections d’objets » dans :
VBA et les collections d'objets. Voir VBA et les collections d'objets Quand plusieurs (beaucoup de) contrôles sont mis sur une feuille ou un Userform il est parfois fastidieux d'écrire du code dans chaque évènement des contrôles. Ce Tuto vous permet de traiter vos contrôles comme...
Le mot-clé static ou les attributs et méthodes de classe en POO Voir(NOTE: Cet article explique la signification du mot-clé static au sein d'une classe. La signification de "static" en C n'a par exemple rien à voir.) Vous êtes débutant en programmation orientée objet. En Java, en C++...ou que sais-je encore,...
Classe et instance d'objet VoirLa notion de classe On appelle classe la structure d'un objet, c'est-à-dire la déclaration de l'ensemble des entités qui composeront un objet. Un objet est donc « issu » d'une classe, c'est le produit qui sort d'un moule. En réalité on dit qu'un...
PHP - Les classes VoirLa notion de classe Php3 intègre un soupçon de caractéristiques empruntées aux langages orientés objet, c'est-à-dire la possibilité d'utiliser des objets, entités regroupant des données et des fonctions au sein d'une structure et rendant la...
Les classes Java VoirLa notion d'objet Le langage Java intègre fortement le concept objet, il s'agit donc d'un langage orienté objet (LOO). Le terme langage orienté objet est plus qu'une simple appellation de plus pour désigner un type de langage, il...