Création et utilisation de classes personnalisées en VB 6.0 et VBA (partie 1)
Date de publication : 15/04/2008
Par
Pierre Fauconnier (Mon site sur www.developpez.com)
Grâce aux classes personnalisées, créez vos propres objets, maintenez facilement votre code, réutilisez rapidement votre code
dans de nouvelles applications
I. Introduction
I-A. Pourquoi utiliser des classes personnalisées
I-B. Objectifs
I-C. Notions abordées dans la partie 1
I-D. Notions abordées dans la partie 2
I-E. Notions abordées dans la partie 3
I-F. Prérequis
II. Notions d'objet
II-A. Les objets de la vie courante
II-B. Les objets informatiques
II-B-1. Quelques objets informatiques
II-B-2. L'explorateur d'objets en VB et VBA
III. Utilisation de variables simples, puis d'un "pseudo-objet", le type personnalisé
III-A. Manipulation des données d'un contact sans utilisation d'un type personnalisé
III-A-1. Limites de l'utilisation de variables simples
III-B. Qu'est-ce qu'une variable de type personnalisé et quand créer un type personnalisé?
III-C. Création d'un type personnalisé
III-D. Utilisation de mon type personnalisé
III-E. Différences entre l'utilisation de variables et l'utilisation d'un type personnalisé
III-F. Limites de l'utilisation d'un type personnalisé
IV. Une classe pour gérer des contacts
IV-A. Notion de classe,notion d'objet, notion d'encapsulation
IV-A-1. Notion de classe
IV-A-2. Notion d'objet
IV-A-3. Notion d'encapsulation
IV-B. Création de notre première classe
IV-B-1. Module de classe
IV-B-1-a. Ajout d'un module de classe en VB 6.0
IV-B-1-b. Ajout d'un module de classe en VBA
IV-B-2. Création de propriétés simples pour notre classe
IV-B-3. Utilisation de notre classe au sein d'un code
IV-B-4. Conclusions
IV-C. Création de vraies propriétés
IV-C-1. Notions de propriétés en lecture/écriture, en lecture seule et en écriture seule
IV-C-2. Propriétés en lecture/écriture
IV-C-3. Propriétés en lecture seule
IV-C-4. Propriétés en écriture seule
IV-C-5. Propriétés en lecture/écriture qui basculent en lecture seule
IV-C-6. Utilisation de Property Get et Property Let
IV-C-6-a. La propriété "Nom" en lecture-écriture
IV-C-6-a-i. Fonctionnement du code
IV-C-6-a-ii. Contrôle de la saisie du nom en vue de sa modification
IV-C-6-a-iii. Adaptation du code: Transformation des variables en propriétés
IV-C-6-a-iv. La propriété "Age" en lecture seule
IV-C-6-a-v. Un petit mot sur l'explorateur d'objets
IV-C-6-a-vi. Conclusions
IV-D. Déclenchement d'erreurs au sein de notre classe
IV-D-1. Génération d'une erreur au sein de la classe
IV-E. Mettre des évènements à disposition du code appelant
IV-E-1. Exemples d'évènements mis à disposition par des classes d'objets
IV-E-2. Création d'un évènement pour notre classe personnalisée
IV-E-2-a. Création et gestion d'un évènement sans paramètre
IV-E-2-a-i. Création de l'évènement
IV-E-2-a-ii. Gestion de l'évènement dans le code appelant
IV-E-2-b. Création d'un évènement qui passe un paramètre au code appelant
IV-E-2-b-i. Exemples d'évènements avec paramètre(s)
IV-E-2-b-ii. Création de l'évènement au sein de la classe
IV-E-2-b-iii. Utilisation de l'évènement et de son paramètre dans le code appelant
IV-E-2-c. Modification du déroulement du code dans la classe grâce à un paramètre "décisionnel"
IV-E-2-c-i. Création d'un paramètre décisionnel
IV-E-2-c-ii. Gestion de l'évènement dans le code appelant
V. Conclusions
VI. Remerciements
I. Introduction
I-A. Pourquoi utiliser des classes personnalisées
On est souvent confronté, lors de l'utilisation de VB ou de VBA, au problème de "réinventer la roue"
à chaque nouveau travail que l'on développe.
Si je prends l'exemple d'applications liées à la gestion d'une entreprise, nombre de nos classeurs Excel,
de nos bases de données Access, voire de nos applications VB, gèrent les données de contacts.
L'utilisation de classes personnalisées va permettre un gain de temps appréciable en favorisant
la réutilisation et la maintenance du code. De plus, les classes personnalisées permettent la mise
à disposition d'objets complexes à des programmeurs qui pourront "se borner" à utiliser les
propriétés et méthodes qu'une classe personnalisée met à leur disposition.
I-B. Objectifs
Ce tutoriel en trois parties a pour ambition de vous expliquer le fonctionnement des
classes personnalisées en VB 6.0 ou en VBA, de vous démontrer que la mise au point de
classes performantes n'est pas un travail impossible, et de vous prouver que les classes
personnalisées permettent la mise à disposition d'autres programmeurs d'un code qui les
soulage de la "réinvention de la roue".
I-C. Notions abordées dans la partie 1
Dans cette partie, nous allons manipuler principalement les concepts liés aux propriétés
d'un objet.
Pour cela, nous allons créer ce que l'on appelle une "classe métier", c'est-à-dire une
classe qui reproduit en informatique un objet manipulé
Notions abordées dans la partie 1
- Qu'est-ce qu'un objet informatique
- Qu'est-ce qu'une propriété
- Propriété en lecture seule, en écriture seule, en lecture écriture
- Encapsulation
- Génération des erreurs dans une classe et gestion par le code appelant
- Génération des évènements et gestion par le code appelant
I-D. Notions abordées dans la partie 2
Dans un deuxième temps, nous utiliserons notre classe "métier" vue en partie 1 en la liant à
différentes sources de données au travers d'une nouvelle classe d'accès aux données.
Notions abordées dans la partie 2
- Création d'un objet personnalisé au travers d'une classe d'accès aux données
- Liaison d'un objet personnalisé à une source pour la lecture des données
- Liaison d'un objet personnalisé à une source pour la modification des données du fichier source
- Portabilité du jeu des classes
- Utilisation de données d'une base Access dans un fichier Excel grâce aux classes personnalisées
I-E. Notions abordées dans la partie 3
La troisième partie nous permettra d'aborder une classe liant propriétés, fonctions et méthodes.
I-F. Prérequis
L'utilisation et la compréhension de ce cours requiert une bonne
connaissance de base en VB ou VBA.
Vous devez notamment savoir déclarer et utiliser des variables et
comprendre la notion de portée d'utilisation d'une variable.
Vous devez savoir déclarer et utiliser des fonctions personnalisées
et des procédures requérant l'emploi de paramètres.
Il est également préférable que l'environnement de développement de VB ou VBE
(Visual Basic Editor) vous soit familier, notamment les
possibilités de débogage du code.
II. Notions d'objet
II-A. Les objets de la vie courante
Dans la vie courante, nous utilisons quotidiennement des objets.
Nous les définissons par un ensemble de caractéristiques et,
généralement, nous pouvons agir avec ces objets.
Ainsi, si je regarde une boite à chaussures, je peux la définir.
Elle est noire, elle fait 40x18x12cm, ...
Je peux l'ouvrir, la fermer, la remplir, la vider,...
Ma voiture possède quatre roues, un volant, un moteur de telle
cylindrée.
Je peux la faire avancer, la stopper, ...
Dans ces exemples, nous discernons que nos objets possèdent des
caractéristiques qui leurs sont propres, et que nous pouvons
définir des actions réalisables sur ou avec ces objets.
II-B. Les objets informatiques
Un objet informatique est similaire à un objet de la vie
courante, et nous en utilisons quotidiennement dans nos
codes VBA.
Ces objets possèdent des caractéristiques qui leur sont propres
et nous pouvons agir sur ou avec ces objets.
Les caractéristiques d'un objet informatique sont appelées les
propriétés de l'objet.
Les actions que nous pouvons réaliser sur ou grâce à ces
objets sont appelées des méthodes.
Lorsque nous souhaitons utiliser un objet, nous devons donc
connaître les propriétés de l'objet mises à notre disposition,
et nous devons connaître aussi les méthodes utilisables sur cet
objet.
II-B-1. Quelques objets informatiques
En VB6, nous utilisons tout le temps des objets. Tous les contrôles que nous
plaçons sur un formulaire (qui est lui-même un objet) sont des objets.
En VBA pour Excel, nous manipulons les objets Range (plage de cellules), Worksheet
(feuille de calcul), Workbook (classeur), ...
En VBA pour Word, nous manipulerons les objets Word, Document, ...
En VBA pour Access, nous manipulerons les objets Form, Database, Recordset
En VB6 ou VBA, nous référençons parfois des bibliothèques d'objets externes, pour
manipuler des objets particuliers.
Par exemple, l'utilisation de la bibliothèque Microsoft Scripting Runtime
permet de manipuler des objets Fichier, dossier, ... non utilisables par défaut
dans VB6 ou VBA.
II-B-2. L'explorateur d'objets en VB et VBA
L'explorateur d'objets permet... d'explorer les objets, c'est-à-dire
d'en afficher les propriétés, méthodes et évènements.
En VB 6.0 comme en VBA, l'affichage de l'explorateur d'objets
est possible via le menu Affichage/Explorateur d'objets ou par
le raccourci F2.
Lorsque l'explorateur d'objets est affiché, on peut alors choisir
d'afficher les objets de toutes les bibliothèques disponibles du projet, ou
de restreindre la liste des obets à une bibliothèque particulière.
On peut alors choisir l'objet pour lequel on souhaite afficher
les propriétés, méthodes et évènements.
L'objet Form de la bibliothèque VB
L'objet Workbook de la bibliothèque Excel
III. Utilisation de variables simples, puis d'un "pseudo-objet", le type personnalisé
Lorsque l'on doit utiliser un "objet" informatique, on a trois possiblités.
La première consiste à créer autant de variables que de propriétés.
La seconde utilise un type personnalisé.
La troisième, enfin, passe par l'utilisation d'une classe personnalisée.
Avant d'aborder la création d'une classe personnalisée, je vais brièvement exposer
les deux premières méthodes, ne serait-ce que pour démontrer la puissance d'une classe
par rapport aux variables simples et aux types personnalisés.
Pour ceux qui connaissent l'histoire des trois petits cochons, on peut imaginer
la première solution comme étant la maison de paille, le type personnalisé étant la
maison de bois, la classe personnalisée comme la maison de briques...
III-A. Manipulation des données d'un contact sans utilisation d'un type personnalisé
Si je souhaite manipuler les données d'un contact,
je dois déclarer autant de variables que j'ai de données (champs)
pour mon contact, puis leur attribuer les données de mon contact,
et enfin les utiliser, par exemple au sein d'une procédure qui
affiche un message à l'écran.
Sub UtiliserContact ()
Dim ContactNom As String
Dim ContactPrenom As String
Dim ContactAdresse As String
Dim ContactCP As String
Dim ContactLocalite As String
Dim ContactDateNaissance As Date
ContactNom = " Fauconnier "
ContactPrenom = " Pierre "
ContactAdresse = " 20, Jevoumont "
ContactCP = " 4910 "
ContactLocalite = " Theux "
ContactDateNaissance = DateSerial (1966 , 12 , 26 )
AfficherMessageContact ContactNom, ContactPrenom, ContactAdresse, _
ContactCP, ContactLocalite, ContactDateNaissance
End Sub
Sub AfficherMessageContact (Nom As String , Prenom As String , Adresse As String , _
CP As String , Localite As String , DateNaissance As Date )
MsgBox " Bonjour " & Prenom & " " & Nom & " . " & vbCrLf & _
" Vous habitez " & Adresse & " à " & CP & " " & Localite & " . " & vbCrLf & _
" Vous êtes né le " & Format (DateNaissance, " dddd dd mmmm yyyy " ), vbOKOnly , " Salutations "
End Sub
|
Ce qui me donnera le résultat suivant à l'écran.
III-A-1. Limites de l'utilisation de variables simples
Les limites du code présenté ci-dessus sont évidentes.
Chaque fois que je souhaite utiliser les données d'un
autre contact, je dois réinitialiser mes variables, avec le
risque d'en oublier, et donc de mélanger les données de mes contacts.
De plus, passer les variables à une procédure ou une fonction
qui doit les utiliser n'est déjà pas pratique avec six
variables...
. . .
AfficherMessageContact ContactNom, ContactPrenom, ContactAdresse, _
ContactCP, ContactLocalite, ContactDateNaissance
. . .
|
Sub AfficherMessageContact (Nom As String , Prenom As String , Adresse As String , _
. . .
End Sub
|
Imaginez ce que cela donnerait avec un objet défini par vingt
ou trente champs...
Enfin, si je veux utiliser simultanément les données de
plusieurs contacts, je vais devoir créer autant de variables
ContactNom1, ContactNom2, ... que j'ai de contacts
à gérer simultanément. Mission impossible!!
III-B. Qu'est-ce qu'une variable de type personnalisé et quand créer un type personnalisé?
Une variable de type personnalisé est un groupe de plusieurs
variables simples dont le type personnalisé concrétise la structure.
Un type personnalisé sera créé lorsqu'il s'avérera nécessaire de
manipuler plusieurs variables comme si elles représentaient une
entité.
L'utilisation de variables de type personnalisé répondra partiellement
aux objections émises plus haut quant à l'utilisation de
variables simples.
III-C. Création d'un type personnalisé
Créer un type personnalisé de variable, c'est définir la structure
de la variable, préciser quelles sont les variables simples qui
seront groupées.
Les variables utilisées plus haut dans le cours constituent la
structure de mon type personnalisé.
Je vais les réutiliser en les modifiant légèrement et créer, ou plutôt
définir mon type personnalisé avec le code suivant:
Public Type tpContact
Nom As String
Prenom As String
Adresse As String
CP As String
Localite As String
DateNaissance As Date
End Type
|
|
Remarquez qu'ici, j'ai supprimé le préfixe Contact
pour mes variables, puisqu'elles sont définies à l'intérieur
de mon type personnalisé.
|
|
Ce code se place toujours en tête de module standard. Il ne peut jamais être
utilisé dans le corps d'une procédure ou d'une fonction.
|
III-D. Utilisation de mon type personnalisé
Je peux maintenant utiliser ce type personnalisé dans mon code
Sub UtiliserContact ()
Dim Contact As tpContact
With Contact
. Nom = " Fauconnier "
. Prenom = " Pierre "
. Adresse = " 20, Jevoumont "
. CP = " 4910 "
. Localite = " Theux "
. DateNaissance = DateSerial (1966 , 12 , 26 )
End With
AfficherMessageContact Contact
End Sub
Sub AfficherMessageContact (ByRef Contact As tpContact)
With Contact
MsgBox " Bonjour " & . Prenom & " " & . Nom & " . " & vbCrLf & _
" Vous habitez " & . Adresse & " à " & . CP & " " & . Localite & " . " & vbCrLf & _
" Vous êtes né le " & Format (. DateNaissance , " dddd dd mmmm yyyy " ), vbOKOnly , " Salutations "
End With
End Sub
|
Ce qui me donne le même résultat que tout à l'heure.
III-E. Différences entre l'utilisation de variables et l'utilisation d'un type personnalisé
Après avoir créé mon type personnalisé, j'utilise une variable de ce
type au travers de mon code, en étant certain d'emporter avec moi
la structure complète de ma variable.
De plus, l'écriture et la lecture du code sont plus simples, notamment
lorsque je dois passer ma variable en argument d'une fonction ou d'une
procédure.
. . .
AfficherMessageContact Contact
End Sub
Sub AfficherMessageContact (Contact As tpContact)
. . .
|
est plus simple à écrire et à lire que
. . .
AfficherMessageContact ContactNom, ContactPrenom, ContactAdresse, _
ContactCP, ContactLocalite, ContactDateNaissance
End Sub
Sub AfficherMessageContact (Nom As String , Prenom As String , Adresse As String , _
CP As String , Localite As String , DateNaissance As Date )
. . .
|
Enfin, la maintenance de mon code est simplifiée lorsque la
structure de ma variable change.
En effet, si je dois ajouter un "champ" à mon type personnalisé,
les modifications se limitent à l'affectation du nouveau champ et à
la récupération de sa valeur. Les passages et récupérations d'un
paramètre contact ne changent pas.
III-F. Limites de l'utilisation d'un type personnalisé
L'utilisation d'un type personnalisé ne permet pas le traitement
des données à l'intérieur de sa structure.
La vérification et le traitement des données sont délégués au code
appelant, ce qui limite considérablement la portabilité du type.
En effet, dans l'exemple de l'utilisation de ma variable Contact,
je dois déléguer au code appelant la vérification de date de naissance.
Nulle part dans la structure Type... End Type, je n'ai la possibilité
d'effectuer des actions relatives à la saisie d'informations.
De plus, la gestion des erreurs est également déléguée au code
appelant.
Enfin, je ne peux gérer aucun évènement relatif à un type personnalisé.
IV. Une classe pour gérer des contacts
L'utilisation d'une classe personnalisée va balayer ces restrictions
et me donner la possibilité de mettre à disposition du code utilisateur
de ma classe des propriétés, méthodes, erreurs et évènements.
Dans la suite du cours, nous allons avancer petit à petit dans la
création d'une classe permettant de gérer des contacts.
La classe que nous allons créer dans un premier temps ne sera vraiment
pas professionnelle, mais nous améliorerons le code petit à petit pour
intégrer calmement les notions essentielles à la création de classes
sûres et portables.
IV-A. Notion de classe,notion d'objet, notion d'encapsulation
IV-A-1. Notion de classe
La classe représente la structure d'un objet. En cela, elle
est comparable aux lignes de définition Type... End Type.
IV-A-2. Notion d'objet
Un objet est une variable dont le type s'appuie sur une classe. Que ce soit en VB ou en VBA,
cette classe peut être personnalisée ou mise à disposition par l'application.
VB 6.0 comme VBA permettent d'utiliser des références externes. Dans VB 6.0, le menu
Projet/Références... permet d'ajouter une référence. Dans VBA, c'est via
le menu Outils/Références... que vous avez la possibilité d'ajouter une référence externe.
|
Ainsi, en Excel, Dim MaFeuille As Worksheet créera
un objet appelé MaFeuille qui s'appuiera sur la classe qui
définit les objets de type WorkSheet, c'est-à-dire les feuilles
de calcul.
|
IV-A-3. Notion d'encapsulation
Nous devrons toujours veiller, lorsque nous construisons une
classe, à ce qu'elle soit "encapsulée".
Cela veut dire qu'à aucun moment, notre classe ne doit avoir
besoin de données externes pour fonctionner. Dans les faits, cela veut dire que notre classe ne peut
jamais faire appel à une variable extérieure à la portée du module
de classe.
De même, une classe ne devrait jamais donner la main à l'utilisateur
via par exemple un msgbox ou un inputbox. Il faudra donc développer à l'intérieur
du module de classe des événements et des gestions d'erreurs qui
rendront la main au code appelant.
Ces notions seront vues dans la suite du cours.
IV-B. Création de notre première classe
La classe que nous allons créer va nous permettre de manipuler un
objet contact.
IV-B-1. Module de classe
IV-B-1-a. Ajout d'un module de classe en VB 6.0
En VB 6.0, nous créerons une classe personnalisée en ajoutant un module
de classe via le menu Projet/Ajouter un module de classe
Nous choisissons alors d'ajouter le module de classe parmi les différents icônes proposés.
Le nouveau module de classe apparaît dans l'arborescence de notre projet, sous le noeud
Modules de classe
La première chose que nous allons faire, c'est renommer le module,
car c'est lui qui déterminera le nom de notre classe.
Ce nom sera donc choisi avec soin, en évitant notamment les noms
réservés par VB 6.0.
IV-B-1-b. Ajout d'un module de classe en VBA
En VBA, nous créerons une classe personnalisée par l'ajout
d'un module de classe au sein de notre projet.
|
Les illustrations proviennent d'un VBA pour EXCEL, mais vous
pouvez les transposer sans problème sur Word, PowerPoint, Access,
Outlook, ...
|
Pour ajouter un module de classe, utilisons le menu
Insertion/Module de classe.
Nous pouvons aussi utiliser le bouton d'outil d'ajout de module.
Un nouveau module apparaît dans l'arborescence du projet,
dans le noeud Modules de classe.
La première chose que nous allons faire, c'est renommer le module,
car c'est lui qui déterminera le nom de notre classe.
Ce nom sera donc choisi avec soin, en évitant notamment les noms
déjà utilisés par VBA.
IV-B-2. Création de propriétés simples pour notre classe
|
Ce que nous allons voir maintenant est à proscrire en
utilisation professionnelle de classes personnalisées.
La seule raison de leur mention ici est de permettre une
prise en main "pas à pas" des notions nécessaires à la
réalisation d'une classe performante.
|
Pour ajouter des propriétés simples à notre classe, il nous
suffit de déclarer des variables publiques au sein de notre
module de classe.
Pour cela, nous pouvons reprendre la structure de notre
type personnalisé.
Le code est le suivant:
Public Nom As String
Public Prenom As String
Public Adresse As String
Public CP As String
Public Localite As String
Public DateNaissance As Date
Public Sexe As String
|
Ces variables publiques, parce que déclarées au sein d'un module de classe,
sont des propriétés en lecture/écriture
pour les objets qui s'appuieront sur notre classe.
|
Le terme variable publique est utilisé ici abusivement. La déclaration
de variables via Public ... dans un module de classe
ne crée pas des variables publiques utilisables partout dans le projet, mais
bien des propriétés publiques mises à disposition du code appelant par la
classe dont l'objet est issu.
A l'extérieur du module de classe, ces propriétés devront être préfixées
du nom de l'objet issu de la classe personnalisée.
|
IV-B-3. Utilisation de notre classe au sein d'un code
Pour utiliser un objet de type cContact au sein d'un
code, nous utiliserons la même technique que pour notre
type personnalisé.
En reprenant le code utilisé plus haut, nous avons deux
modifications à réaliser pour utiliser notre classe plutôt
que notre type personnalisé.
Voici le code:
Sub UtiliserContact ()
Dim Contact As New cContact
With Contact
. Nom = " Fauconnier "
. Prenom = " Pierre "
. Adresse = " 20, Jevoumont "
. CP = " 4910 "
. Localite = " Theux "
. DateNaissance = DateSerial (1966 , 12 , 26 )
. Sexe = " masculin "
End With
AfficherMessageContact Contact
End Sub
Sub AfficherMessageContact (Contact As cContact)
With Contact
MsgBox " Bonjour " & . Prenom & " " & . Nom & " . " & vbCrLf & _
" Vous habitez " & . Adresse & " à " & . CP & " " & . Localite & " . " & vbCrLf & _
" Vous êtes né le " & Format (. DateNaissance , " dddd dd mmmm yyyy " ) & " . " , vbOKOnly , " Salutations "
End With
End Sub
|
La saisie semi-automatique permet, ici aussi, d'utiliser
la liste des objets disponibles en fonction de la saisie.
Et voici les modifications à réaliser:
Le résultat est toujours le même, à savoir l'affichage
d'un message de bienvenue.
|
Attention! Bien que nous ayons déclaré nos variables publiques, il
n'est pas possible de les utiliser telles quelles ailleurs que dans
notre module de classe.
Ainsi, le code Debug.Print DateNaissance à l'extérieur de
notre code provoquera une erreur de compilation.
|
IV-B-4. Conclusions
Nous venons de voir comment créer notre première classe.
Il n'y a pas de quoi fouetter un chat. Nous ne savons pas mieux
contrôler les données avec ce code qu'avec l'utilisation d'un
type personnalisé.
Néanmoins, nous avons vu comment créer un module de classe, lui
affecter un nom qui sera celui de la classe que nous créons, et nous
avons ajouté des variables "publiques" qui sont des propriétés en
lecture/écriture disponibles pour les objets de notre classe.
IV-C. Création de vraies propriétés
Déclarer des variables publiques au sein d'un module de classe
est certes rapide, mais peu intéressant.
Pour pouvoir manipuler, contrôler et travailler avec les propriétés
d'un objet, nous allons déclarer des ... propriétés.
IV-C-1. Notions de propriétés en lecture/écriture, en lecture seule et en écriture seule
IV-C-2. Propriétés en lecture/écriture
Une propriété en lecture/écriture est une propriété qui peut être lue ET modifiée.
Exemple: La propriété DateNaissance doit être en lecture pour pouvoir la récupérer
et en écriture pour pouvoir la définir pour un contact particulier.
IV-C-3. Propriétés en lecture seule
Une propriété en lecture seule ne peut être ni définie, ni
modifiée.
Exemple: si je dote ma classe d'une propriété Age, elle sera
en lecture seule car elle dépendra de la propriété DateNaissance,
qui sera, elle, en lecture/écriture.
IV-C-4. Propriétés en écriture seule
Une propriété pourrait être en écriture seule, et donc définissable mais
non lisible.
Je ne vois pas d'exemple concret pour ce cas.
IV-C-5. Propriétés en lecture/écriture qui basculent en lecture seule
Certaines propriétés doivent être définies une fois, puis être
verrouillées pour ne plus pouvoir être modifiées.
Elles sont dès lors en lecture/écriture mais le code les fera
basculer en lecture seule pour éviter leur modification.
Exemple: Une propriété ID qui doit être définie mais qui ne
peut par la suite être modifiée. C'est le cas des clés primaires, pour
ceux qui connaissent.
Nous verrons ce cas particulier dans la suite du cours.
IV-C-6. Utilisation de Property Get et Property Let
Property Get et Property Let permettent la création
de propriétés au sein de la classe.
Property Get permet la lecture d'une propriété,
Property Let permet l'écriture d'une propriété.
IV-C-6-a. La propriété "Nom" en lecture-écriture
La création d'une propriété passe pas deux étapes;
la définition d'une variable privée, et la création des blocs
Property Get et Property Let.
Modifions le code de notre classe en modifiant la ligne
pour définir une variable privée
Remarquez que ma variable a changé de nom, par l'ajout d'un
préfixe "m" précisant la limite de sa portée au module.
Cette variable ne sera donc pas manipulable par le code
appelant qui utilisera notre objet.
La définition du nom de notre contact s'effectuera via le code
Property Get Nom () As String
Nom = mNom
End Property
Property Let Nom (Nom As String )
mNom = Nom
End Property
|
|
Notons que ces modifications n'ajoutent actuellement rien à notre
classe par rapport à l'utilisation d'une variable déclarée
avec Public. Patience...
Notez aussi que les propriétés ne sont pas déclarées Public,
car elles le sont d'office. C'est leur raison d'être!
Notons cependant que des propriétés peuvent être déclarées Private
pour n'être utilisables qu'à l'intérieur du module de classe.
|
IV-C-6-a-i. Fonctionnement du code
Pour nous aider à comprendre comment le code fonctionne
avec les propriétés d'une classe, nous allons démarrer
le code appelant vu plus haut avec la méthode "pas à pas",
en mettant un point d'arrêt sur la ligne With Contact de
la procédure UtiliserConctact
Puis nous démarrons le code. L'exécution s'arrête sur
With contact. Nous sommes dans le module standard
qui contient la procédure UtiliserContact.
Nous pressons sur F8 pour passer à la ligne suivante,
puis encore sur F8. Le contrôle du code passe dans le
module de classe pour s'arrêter sur Property Let.
L'infobulle nous montre que le paramètre Nom possède la
valeur "Fauconnier" passée par le module standard.
Nous connaissons déjà le fonctionnement des paramètres, puisqu'il
est identique dans une propriété à celui d'une procédure ou d'une
fonction dans VBA. Rien de nouveau sous le soleil de ce côté-là.
Pressons F8. Le code repasse dans le module standard,
et pressons F8 jusqu'à nous arrêter sur la ligne End Property.
L'infobulle nous montre que la valeur du paramètre a été
passée à la variable privée mNom.
Pressons F8 plusieurs fois pour arriver sur la ligne
MsgBox... de la procédure AfficherMessageContact
Puis pressons F8, pour constater que le code repasse
dans le module de classe, et s'arrête sur la ligne
Property Get Nom(). Le code va récupérer
la valeur de la variable mNom
Pour la passer au paramètre Nom
Ce qui permettra l'affichage du nom au sein du MsgBox.
On comprend donc maintenant le fonctionnement et le parcours du
code au sein des propriétés de la classe. Mais à quoi cela sert-il?
IV-C-6-a-ii. Contrôle de la saisie du nom en vue de sa modification
L'intérêt de passer par Property Let pour définir
le nom de notre contact, c'est que nous pouvons ajouter du code
au sein de la propriété, ce qui était impossible avec une variable
de type personnalisé ou une variable publique de notre module de classe.
Imaginons que nous voulons que les noms de nos contacts soient
systématiquement en majuscules. Grâce à Property Let, nous
n'aurons aucune difficulté à satisfaire à cette exigence.
Modifions le code comme suit:
Property Let Nom (Nom As String )
mNom = UCase (Nom)
End Property
|
En plaçant un point d'arrêt sur
End Property de cette
propriété,
Nous verrons, grâce à l'infobulle, que mNom contient le nom
en majuscules.
A la lecture de la propriété, le paramètre Nom recevra
la valeur de mNom pour afficher, cette fois, un
message différent de ceux vus précédemment.
IV-C-6-a-iii. Adaptation du code: Transformation des variables en propriétés
Maintenant que nous avons compris l'intérêt d'utiliser des propriétés
plutôt que des variables, nous pouvons modifier le code en
transformant toutes les variables en propriétés.
Toutes ces propriétés sont en lecture/écriture.
Option Explicit
Private mNom As String
Private mPrenom As String
Private mAdresse As String
Private mCP As String
Private mLocalite As String
Private mDateNaissance As Date
Private mSexe As String
Property Get Nom () As String
Nom = mNom
End Property
Property Let Nom (Nom As String )
mNom = UCase (Nom)
End Property
Property Get Prenom () As String
Prenom = mPrenom
End Property
Property Let Prenom (Prenom As String )
mPrenom = UCase (Prenom)
End Property
Property Get Adresse () As String
Adresse = mAdresse
End Property
Property Let Adresse (Adresse As String )
mAdresse = UCase (Adresse)
End Property
Property Get CP () As String
CP = mCP
End Property
Property Let CP (CP As String )
mCP = UCase (CP)
End Property
Property Get Localite () As String
Localite = mLocalite
End Property
Property Let Localite (Localite As String )
mLocalite = UCase (Localite)
End Property
Property Get DateNaissance () As Date
DateNaissance = mDateNaissance
End Property
Property Let DateNaissance (DateNaissance As Date )
mDateNaissance = DateNaissance
End Property
Property Get Sexe () As String
Sexe = mSexe
End Property
Property Let Sexe (Sexe As String )
mSexe = UCase (Sexe)
End Property
|
|
Remarquez qu'il faut une similitude de type entre une propriété
en lecture et la même propriété en écriture.
Ainsi, si la propriété en lecture est typée String,
la propriété en écriture doit recevoir un paramètre typé String.
|
IV-C-6-a-iv. La propriété "Age" en lecture seule
Après avoir vu comment ajouter du code dans un Property Let,
nous allons aborder une propriété en lecture seule avec du code
pour calculer la valeur de la propriété.
Pour éviter que le programmeur du code appelant doive créer une
fonction qui calcule l'âge du contact par rapport à la date de
naissance, nous allons créer une propriété Age au sein de notre
classe. Le code appelant devra alors seulement lire la propriété
Age de l'objet contact, sans se soucier de l'algorithme
utilisé.
Voici le code permettant de calculer l'âge révolu du contact.
Property Get Age () As Integer
Age = Int ((Date - mDateNaissance) / 365 )
End Property
|
|
Il existe une multitude de façons de calculer l'âge, avec ou sans
la fonction DateDiff. Ce cours ayant pour objectif
l'apprentissage des classes personnalisées et non les
algorithmes de calcul d'âge, le lecteur acceptera ma façon de
calculer et la considérera pour ce qu'elle est, à savoir
l'illustration d'une création de propriété en lecture seule.
|
Ainsi, le code suivant, placé dans un module standard,
permettra de connaître l'âge d'un contact en fonction de sa
date de naissance.
Sub CreerContactAge ()
Dim Contact As New cContact
Contact. Prenom = " Pierre "
Contact. DateNaissance = DateSerial (1966 , 12 , 26 )
MsgBox Contact. Prenom & " a " & Contact. Age & " ans "
End Sub
|
Ce qui affichera le message suivant
|
Dans ce cas précis, mDateNaissance étant une date, le fait
de ne pas spécifier la date de naissance pose simplement un
problème de calcul, et le résultat est erroné.
Il n'y a pas d'erreur amenant à un débogage ou un plantage, mais
il faudra être vigilant et envisager tous les cas possibles.
Nous verrons très bientôt comment gérer ce type de situation.
|
IV-C-6-a-v. Un petit mot sur l'explorateur d'objets
J'ai abordé plus haut dans le cours l'explorateur d'objets.
Cet explorateur permet également de parcourir les objets que
nous créons.
Si je demande à l'explorateur d'objets de m'afficher les propriétés
de ma classe cContacts, j'obtiendrai l'affichage suivant:
En sélectionnant une valeur dans la liste, j'obtiens les spécifications
de cette propriété ou méthode
IV-C-6-a-vi. Conclusions
Nous venons d'approcher la puissance des propriétés de notre classe,
car seule notre imagination va nous bloquer.
Si, par exemple, vous devez souvent calculer des emprunts, les taux de
remboursement, ..., vous pouvez vous définir une classe
cEmprunts et créer des méthodes et des propriétés
pour cette classe.
Vous mettez alors à disposition du code, voire d'autres programmeurs,
une classe qui peut être utilisée, même par quelqu'un qui ne connaît
aucune formule de calcul...
Dans la suite du cours, nous allons enrichir notre classe avec des
créations d'erreurs et des déclenchements d'évènements.
Nous donnerons également au code appelant les moyens de contrôler
l'exécution du code à l'intérieur de la classe. Mais, ... Patience!
IV-D. Déclenchement d'erreurs au sein de notre classe
Lorsque nous avons créé la propriété Age, nous avons remarqué
que l'âge pouvait être erroné si la date de naissance n'était pas spécifiée.
Nous pourrions aussi avoir des surprises désagréables si nous créons un
contact pour une personne qui n'est pas encore née, en introduisant une date
ultérieure à la date système. Gênant...
Nous allons donc contrôler, dans Property Let DateNaissance, que la
date passée en paramètre est valide.
Cela se fera très facilement avec le code suivant
Property Let DateNaissance (DateNaissance As Date )
If DateNaissance < = Date Then
mDateNaissance = DateNaissance
Else
. . .
End If
End Property
|
Jusque là, ce n'est pas trop compliqué. Mais par quoi faut-il
remplacer les ... ? Par ceci ?
Property Let DateNaissance (DateNaissance As Date )
If DateNaissance < = Date Then
mDateNaissance = DateNaissance
Else
MsgBox " Date non valide " , vbOKOnly + vbExclamation , " Erreur de saisie "
End If
End Property
|
En effet, si je passe comme date de naissance une date ultérieure à la
date du jour, j'ai un beau message d'erreur.
Mais, ce faisant, j'enfreins la règle d'encapsulation vue plus haut, car
ma classe passe outre le code appelant pour s'adresser directement
à l'utilisateur derrière son écran, sans donner la possibilité au code
appelant de reprendre la main.
|
Une classe doit TOUJOURS, en cas d'erreur, rendre la main au code
appelant et JAMAIS à l'utilisateur.
C'est au code appelant qu'il revient de gérer l'erreur survenue dans
la classe.
|
Nous allons donc devoir créer du code au sein de la classe pour rendre
la main au code appelant et lui déléguer la responsabilité de traiter l'erreur.
|
La classe a la responsabilité de signaler l'erreur, le code appelant a la
responsabilité de le gérer.
|
IV-D-1. Génération d'une erreur au sein de la classe
Pour informer le code appelant d'une erreur, dans le cas présent une
erreur de saisie, nous allons générer une erreur avec
Err.Raise Number, [Source], [Description],...
Property Let DateNaissance (DateNaissance As Date )
If DateNaissance < = Date Then
mDateNaissance = DateNaissance
Else
Err . Raise Number:= vbObjectError + 1 , Description:= " Date non valide "
End If
End Property
|
Pour générer l'erreur, nous avons besoin d'un numéro d'erreur, et
optionnellement d'une source et d'une description de l'erreur. Nous
pouvons également définir des paramètres utiles lors de l'utilisation
de fichier d'aide, mais je n'en parlerai pas ici.
Certaines plages de numéros d'erreur étant réservées par Windows et VBA,
Nous utiliserons la constante vbobjecterror en lui ajoutant des unités, et
il faudra, pour le support technique, tenir des fiches à jour avec le
numéro de l'erreur et les lignes de code concernées, pour faciliter la
maintenance de code.
En plus de ce numéro d'erreur, nous utiliserons le paramètre
Description qui explicitera l'erreur rencontrée.
Si, après cette modification de la propriété, nous relançons le
code, nous avons un message d'erreur, mais au niveau du code appelant
et plus au niveau de l'utilisateur "final".
On comprend donc clairement ici que la main est rendue au code appelant. A lui
la responsabilité de la gestion de l'erreur, par exemple avec le code
suivant
On Error GoTo Erreurs
Contact. Prenom = " Pierre "
Contact. DateNaissance = DateSerial (2008 , 12 , 26 )
MsgBox Contact. Prenom & " a " & Contact. Age & " ans "
Erreurs :
Select Case Err
Case - 2147221503
MsgBox " La date saisie n'est pas valide et ne sera pas enregistrée " , vbOKOnly + vbExclamation , " Erreur de saisie "
Resume Next
End Select
|
C'est donc bien le code appelant qui reprend la main et qui décide de la
façon de traiter l'erreur.
IV-E. Mettre des évènements à disposition du code appelant
VB 6.0 et VBA permettent de créer des évènements liés à une classe personnalisée. Ces
évènements sont levés lors de certaines manipulations à l'intérieur de la classe et
passent la main au code appelant qui peut choisir de les gérer ou pas
IV-E-1. Exemples d'évènements mis à disposition par des classes d'objets
Nous connaissons tous la gestion des évènements pour des objets couramment utilisés
lors d'une programmation en VB 6.0 ou en VBA.
Voici par exemple la gestion de l'évènement de chargement d'un "form" en VB 6.0
... et voici l'illustration de la gestion de l'évènement "SelectionChange" d'une
feuille de calcul Excel, recevant en paramètre la cellule active de la plage sélectionnée.
|
Les évènements qu'il est possible de gérer dépendent évidemment de l'objet que l'on
manipule. Ainsi, dans une classe personnalisée, il n'y a par défaut aucun évènement à la disposition
du code qui exploite un objet issu de cette classe. C'est au concepteur de la classe qu'il
revient de créer les évènements qu'il souhaite mettre à disposition du code utilisateur.
|
IV-E-2. Création d'un évènement pour notre classe personnalisée
|
La mise à disposition d'évènements pour des objets d'une classe personnalisée n'impose pas
la gestion de ces évènements par le code appelant. Dans Excel, lorsque vous manipulez des
feuilles de calcul, vous n'êtes pas tenus de gérer les évènements mis à votre disposition. Il en
est de même pour les évènements de vos classes personnalisées, qui ne seront peut-être jamais
gérés par le code appelant. C'est ce qui différencie les évènements des erreurs,
qui sont, quant à elles, levées systématiquement, qu'elles soient gérées ou non par le code appelant.
|
IV-E-2-a. Création et gestion d'un évènement sans paramètre
Imaginons que nous souhaitons que le code appelant puisse gérer le fait que l'anniversaire
du contact surviendra dans les 10 jours, et que nous souhaitons déclencher
l'évènement lors de la saisie de sa date de naissance.
IV-E-2-a-i. Création de l'évènement
Tout d'abord, il faut déclarer l'évènement. Celui-ci se déclare avant la première
méthode, la première propriété ou la première fonction, tout en haut du module. Créons
un évènement appelé AnniversaireDans10Jours. Le code utilisé est simple
Public Event AnniversaireDans10jours ()
|
Lorsque cela est fait, il nous reste à déclencher l'évènement lorsque la condition
est remplie. Pour cela, nous allons modifier le code de
property let DateNaissance, de façon à tester la date d'anniversaire
Property Let DateNaissance (DateNaissance As Date )
Dim DateAnniversaire As Date
mDateNaissance = DateNaissance
DateAnniversaire = DateSerial (Year (Date ), Month (DateNaissance), Day (DateNaissance))
If DateAnniversaire >= Date And DateAnniversaire < = Date + 10 Then RaiseEvent AnniversaireDans10jours
End Property
|
Avec la saisie semi-automatique, la liste des évènements disponibles pour l'objet
apparaît après la saisie de RaiseEvent
Nous venons donc de créer un évènement pour les objets de notre classe. Si
cet évènement est géré par le code appelant, ce dernier pourra, par exemple,
avertir l'utilisateur que le contact qu'il est en train de gérer a son
anniversaire dans les dix prochains jours.
IV-E-2-a-ii. Gestion de l'évènement dans le code appelant
Pour pouvoir gérer l'évènement de l'objet issu de notre classe cContact,
nous devons déclarer à VB 6.0 ou VBA que nous voulons gérer les évènements
pour cet objet. Pour cela, il suffit de déclarer notre objet de la façon suivante,
en utilisant Dim ou Public en fonction de la portée d'utilisation voulue
pour notre objet.
Dim WithEvents oContact As cContact
|
|
Tant en VB 6.0 qu'en VBA, les modules standard ne permettent pas de
gérer des évènements pour des objets, qu'ils soient personnalisés ou non. Il
n'est donc pas possible de déclarer des objets avec la clause
WithEvents au sein d'un module standard. La ligne est directement
refusée et mise en rouge.
|
|
Pour info, la déclaration avec WithEvents d'un objet qui ne possède
pas d'évènements ne déclenche pas d'erreur lors de la saisie du code, mais
déclenche une erreur à l'exécution. Il n'est donc possible d'utiliser
WithEvents que pour des objets pour lesquels il existe des
évènements gérables.
|
Pour illustrer cela, nous allons utiliser un formulaire avec un bouton
Dans un formulaire de notre projet (formulaire pour VB 6.0 ou userform pour VBA),
déclarons un objet de type cContact en tête de module.
Option Explicit
Dim WithEvents oContact As cContact
|
En déclarant notre objet de cette manière, nous pouvons gérer le(s)
évènement(s) qui lui sont attachés. En effet, dans la fenêtre du code, nous
disposons de l'objet dans la liste déroulante de gauche,
VB 6.0: Objet dans la liste des objets disposant d'évènements
VBA: Objet dans la liste des objets disposant d'évènements
et de la liste de
ses évènements dans la liste déroulante de droite.
VB 6.0: Liste des évènements pour l'objet sélectionné dans la liste déroulante de gauche
VBA: Liste des évènements pour l'objet sélectionné dans la liste déroulante de gauche
Lorsque l'objet a été déclaré ce cette manière, je peux gérer l'évènement souhaité
Private Sub oContact_AnniversaireDans10jours ()
MsgBox " L'anniversaire de " & oContact. Prenom & " a lieu dans les 10 prochains jours "
End Sub
|
Si, sur le formulaire (VB 6.0) ou le userform (VBA), nous plaçons un bouton
nommé btnContact, nous pouvons gérer notre contact via un clic sur ce
bouton, avec le code suivant
Private Sub btnContact_Click ()
Set oContact = New cContact
With oContact
. Prenom = " Manon "
. DateNaissance = DateSerial (1992 , 12 , 3 )
End With
End Sub
|
En démarrant le code, nous aurons le message suivant
|
Pour que l'exemple fonctionne, il faut évidemment que la date de naissance
utilisée soit calculée pour que l'anniversaire tombe dans les 10 prochains jours
par rapport à la date système de vote pc.
|
Si nous suivons l'exécution du code pas à pas, nous pouvons comprendre comment
la levée de l'évènement fonctionne. Pour cela, plaçons un point d'arrêt sur la
ligne de code qui attribue la date de naissance.
Démarrons le code. L'exécution s'arrête sur la ligne qui attribue la date
de naissance.
Avec F8, avançons pas à pas. L'exécution saute dans le module de classe, et
nous pressons F8 jusqu'à la ligne qui teste la date de naissance
La date de naissance est testée. Si la condition est remplie, l'évènement est
généré
L'exécution saute dans le code appelant pour générer l'évènement, et nous
constatons que l'affichage du message va avoir lieu
Après affichage du message et clic sur le bouton Ok, on passe à la fin
de la gestion de l'évènement dans le code appelant
Puis on retourne dans le code de la classe pour terminer le code lié à la
propriété DateNaissance en écriture
Et on repasse dans le code appelant pour continuer l'exécution du code
Comme vous le voyez ici, la mise en place d'un évènement au sein d'une classe est
finalement assez simple et s'effectue en deux temps: Déclarer un évènement au niveau
du module, puis générer l'évènement dans le code, à l'endroit opportun. Il ne reste plus
qu'à choisir de gérer ou non l'évènement dans le code appelant.
IV-E-2-b. Création d'un évènement qui passe un paramètre au code appelant
IV-E-2-b-i. Exemples d'évènements avec paramètre(s)
Certains évènements passent au code appelant un ou plusieurs paramètres. C'est le cas
de l'évènement Unload d'un form en VB 6.0, qui passe un paramètre
ou encore de l'évènement BeforeDoubleClick d'une feuille de calcul Excel, qui
passe quant à lui deux évènements au code appelant.
Ces paramètres peuvent alors être gérés ou utilisés par le code appelant.
IV-E-2-b-ii. Création de l'évènement au sein de la classe
Il est possible de passer un paramètre au code appelant. Ainsi,
on pourrait vouloir passer la date de naissance au code appelant
lorsque le contact a son anniversaire dans les 10 jours.
Pour cela, on doit modifier la déclaration de l'évènement.
Il faut aussi modifier également le code qui génère l'évènement, car
il doit correspondre à la syntaxe de la déclaration de l'évènement.
Bien entendu, le code qui gère l'évènement doit lui aussi correspondre
à la syntaxe de l'évènement paramétré.
Le code appelant est bien entendu libre d'utiliser ou pas le
paramètre passé lors de la levée de l'évènement. Ici, le paramètre
est utilisé dans un messagebox
IV-E-2-b-iii. Utilisation de l'évènement et de son paramètre dans le code appelant
IV-E-2-c. Modification du déroulement du code dans la classe grâce à un paramètre "décisionnel"
IV-E-2-c-i. Création d'un paramètre décisionnel
Un paramètre décisionnel est un paramètre dont la modification par le
code appelant va modifier l'exécution du code au sein de la classe. L'exemple
typique de paramètre "décisionnel" est le paramètre Cancel utilisé par
nombre de codes évènementiels.
Imaginons que nous voulions contrôler la modification de la propriété sexe
de notre contact. On se rend compte rapidement que, sauf à devoir changer le contenu
de la garderobe du contact, il peut être utile de mettre
à disposition du code appelant un évènement lorsque celui-ci modifie la
propriété Sexe du contact.
Nous allons déclarer l'évènement dans la classe en utilisant le code suivant
Public Event ModificationGenre(ByRef Cancel As Boolean)
|
Remarquez que le paramètre Cancel est passé ByRef.
Il nous faut modifier la propriété Sexe en écriture,
dans la classe cContact
Property Let Sexe(Sexe As String)
' Propriété en écriture
Dim Cancel As Boolean
If mSexe <> "" Then RaiseEvent ModificationGenre(Cancel) ' Teste si le genre a déjà été attribué
If Not Cancel Then mSexe = UCase(Sexe) ' Si Cancel = FALSE, on n'annule pas la modification...et donc on modifie!
End Property
|
Le code modifié testera si le genre a déjà été défini. Si oui, l'évènement
est généré, à charge pour le code appelant de définir la suite des opérations.
IV-E-2-c-ii. Gestion de l'évènement dans le code appelant
Dans le code appelant (code du form ou du userform), on va gérer l'évènement,
puisque nous avons maintenant un deuxième évènement dans la liste de droite.
Private Sub oContact_ModificationGenre(Cancel As Boolean)
Dim Reponse As VbMsgBoxResult
Reponse = MsgBox("Etes-vous certain de vouloir modifier le genre du contact?", vbYesNo + vbQuestion, "Gestion du contact")
If Reponse <> vbYes Then Cancel = True
End Sub
|
|
Remarquez que la ligne de déclaration de la procédure évènementielle reprend
la structure de la déclaration de l'évènement dans le module de classe, et donc
passe le(s) paramètre(s) définis dans cette déclaration.
|
A nouveau, utilisons l'exécution pas à pas pour bien comprendre ce qui se
passe. Pour cela, nous allons utiliser le code appelant suivant, dans la
procédure évènementielle Click du bouton btnContact
Private Sub btnContact_Click ()
Set oContact = New cContact
With oContact
. Prenom = " Manon "
. Sexe = " F "
End With
oContact. Sexe = " M "
MsgBox oContact. Prenom & " : sexe " & UCase (oContact. Sexe )
End Sub
|
Plaçons un point d'arrêt sur la ligne qui affecte le genre du contact
Démarrons l'exécution du code, qui s'arrête sur la ligne qui définit
pour la première fois le genre du contact
Le code passe dans le module de classe, teste si mSexe est une
chaine vide.
Comme c'est le cas, l'évènement n'est pas généré, et le code
passe à la ligne suivante, sur laquelle on va tester la variable locale
Cancel, définie à False par défaut
Cancel est différent de True, donc la variable mSexe reçoit
la valeur passée par le code appelant.
Et le code continue, et repasse dans le code appelant
pour, cette fois, modifier le genre du contact, puisque nous venons
de l'attribuer à la ligne précédente.
Le code appelant veut modifier la propriété Sexe du contact, le code
repasse donc dans le module de classe sur la propriété Sexe en écriture
et teste si mSexe est une chaine vide. Ce n'est plus le cas, puisque la
valeur "F" a déjà été attribuée
Donc, l'évènement est généré avec Cancel = False (valeur par défaut).
Le code repasse au code appelant puisqu'une procédure évènementielle
a été rédigée. Cette procédure évènementielle reçoit bien le paramètre
Cancel avec la valeur False
Si nous répondons NON à la question posée, la valeur de Cancel
est modifiée
La procédure évènementielle se termine, et le code repasse dans le
module de classe pour continuer son exécution. On voit ici que la
valeur de Cancel a été modifiée, grâce au mot-cle ByRef utilisé
lors de la déclaration de l'évènement en début du module de classe.
Comme Cancel vaut True, mSexe n'est pas modifié.
La modification de Cancel par le code appelant a donc bien modifié
l'exécution du code à l'intérieur de la classe.
Si nous avions répondu Oui à la question posée par le code appelant,
la valeur de Cancel n'aurait pas été modifiée, et donc mSexe aurait
reçu la nouvelle valeur, ce qui aurait pour conséquence que notre contact féminin
serait devenu un homme...
|
On comprend donc mieux ici, gràce à cet exemple, comment
fonctionne le paramètre Cancel présent dans de
nombreuses procédures évènementielles que nous rencontrons
avec les objets que nous utilisons dans nos applications.
|
V. Conclusions
Cette partie du tutoriel nous a permis de comprendre ce qu'était un objet personnalisé. Nous
avons abordé les notions de propriété, génération d'erreurs et
génération d'évènements
Nous voici arrivés au terme de la première partie de ce que je souhaite vous expliquer
sur le fonctionnement des classes personnalisées.
Dans une seconde partie, nous envisagerons l'utilisation de cette classe "métier"
au travers d'une classe qui liera notre contact à une source de données. Nous verrons que
peu de choses seront à modifier dans cette nouvelle classe pour lier nos données
à un classeur Excel ou à une base de données Access.
VI. Remerciements
Copyright © 2008 .
Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.