Vous êtes sur la page 1sur 11

Charger la source d'une liste déroulante en VBA

Dans cette formation Visual Basic Access, nous souhaitons préparer une application
qui permettra d'évaluer les candidats avec des questionnaires à choix multiples. Ici
nous nous contenterons de développer le formulaire d'accueil qui permettra à
l'utilisateur de choisir, par le biais d'une liste déroulante, le questionnaire sur lequel il
souhaite être évalué.

Ces questionnaires dépendent des noms des tables Access dans lesquelles ils ont été
bâtis et archivés. Au chargement du formulaire, un code VBA Access doit donc
parcourir toutes les tables de la base de données, afin de prélever leur nom et de les
charger dans une liste déroulante de choix. Au clic de l'utilisateur sur l'un des
questionnaires ainsi proposés, le QCM doit débuter par le biais d'un autre formulaire,
chargé dynamiquement des questions et choix de la table correspondante.

Présentation de la base de données des QCM


Pour aller à l'essentiel, nous allons débuter les travaux avec une base de
données existante contenant déjà les questionnaires et les deux formulaires de
l'application.
 Télécharger la base de données charger-liste-vba.accdb en cliquant sur son lien,
 L'ouvrir dans Access et cliquer sur le bouton Activer le contenu, si nécessaire,
 Double cliquer sur le formulaire Listes depuis le volet gauche des objets Access,
Il s'agit du formulaire qui doit permettre à l'utilisateur de choisir un questionnaire,
comme celui illustré par la capture ci-dessus. Mais ce dernier n'est pas encore
fonctionnel puisqu'au clic sur la liste déroulante, aucun choix n'est proposé.

C'est tout l'enjeu du code que nous devons développer. Il s'agit certes de charger le
contenu d'une liste déroulante par le code Visual Basic Access. Mais il ne s'agit pas
de n'importe quel contenu, puisque nous devons être capables de récupérer les
informations de tables et plus précisément, leur nom.

La capture suivante, illustre les tables qui composent la base de données et archivent
les questionnaires. Il s'agit certes de QCM anciens mais qui feront très bien l'affaire
pour développer l'application Access.

Accès aux données en VBA Access


Comme nous l'avions appris dans la formation VBA Access pour accéder aux données,
avant de développer le code, nous aurons besoin d'ajouter une référence à la librairie
permettant la connexion aux données de la base. Le contrôle Microsoft ActiveX
DataObject (ADO ou DAO) permettra alors d'instancier n'importe quel objet de base
de données. Nous pourrons ainsi accéder aux propriétés et méthodes nécessaires
pour notamment, parcourir les tables de la base et récupérer leur nom. Mais avant
cela, nous devons créer la procédure événementielle qui permettra de déclencher
le code à l'ouverture du formulaire.
 Cliquer avec le bouton droit sur le formulaire Listes depuis le volet des objets Access,
 Dans le menu contextuel, choisir Mode Création,
Le formulaire s'affiche au centre de l'écran, en mode conception, avec tous les
contrôles qui le composent. Le formulaire lui-même est le contrôle actif par défaut.
Nous allons donc en profiter pour le paramétrer avec sa feuille de propriétés.
 Si elle n'est pas visible, cliquer sur le bouton Feuille de propriétés du ruban Création,
 Activer l'onglet Evénement de cette feuille de propriétés,
 Cliquer sur le petit bouton de son événement Sur chargement,
 Dans la boîte de dialogue qui suit, choisir Générateur de code et valider par Ok,
Nous basculons ainsi dans l'éditeur de code Visual Basic Access, entre les bornes de
la procédure événementielle Form_Load(). Load est l'événement qui se déclenche au
chargement du formulaire. En d'autres termes, tout code saisi entre ces bornes, se
déclenchera en même temps que le formulaire se charge puis s'ouvre. C'est donc ici
que nous devons développer les lignes de programmation permettant de charger
la liste déroulante, des noms de tables composant la base de données. Mais avant
cela, nous devons ajouter la référence nécessaire au pilotage des objets de base de
données.
 Cliquer sur le menu Outils en haut de l'éditeur de code,
 Dans la liste, choisir Références,
 Dans la boîte de dialogue qui suit, cocher la case Microsoft ActiveX Data Objects 6.1
Library,
 Puis valider par Ok,

Le numéro de cette librairie 6.1 peut dépendre de la version Office installée sur votre
poste.

Variables Objets pour accéder aux données Access


Comme toujours, nous devons commencer l'implémentation du code VBA par
la déclaration des variables nécessaires. Et parmi elles, figurent les variables
objets qui permettront d'instancier les classes ADO afin d'hériter de leurs propriétés
et méthodes. Dès lors nous serons en mesure d'accéder aux propriétés des objets
Access et notamment des tables.
 Entre les bornes de la procédure, saisir les déclarations VBA suivantes :
Dim la_base As Database
Dim chaque_table As TableDef
Dim tabval(20)
Dim i As Integer, j As Integer
Dim nouvelle_table As TableDef : Dim nouveau_champ As Field : Dim
nouvel_enregistrement As Recordset
Dim nom_table As String, nom_champ As String

Tout d'abord, grâce à la référence à la librairie Microsoft ActiveX Data Objects, nous


pouvons déclarer un objet en tant que base de données (Dim la_base As Database).
Nous l'utiliserons pour pointer sur la base de données en cours. Dès lors, nous
pourrons manipuler ses éléments, comme ses tables. Nous déclarons ensuite un
objet qui pourra accéder à la définition stockée des tables (Dim chaque_table As
TableDef). Une boucle les parcourant toutes, permettra alors d'en extraire les noms
respectifs. Puis nous déclarons un tableau de valeurs (Dim tabval(20)), limité
arbitrairement à 20 éléments pour stocker temporairement les informations
prélevées des noms de tables. Les variables entières i et j seront utilisées pour
réaliser des boucles de traitements. Les variables objets nouvelle_table,
nouveau_champ et nouvel_enregistrement seront exploitées pour créer une table
temporaire dans laquelle seront stockées les informations prélevées sur les tables de
la base de données. Cette table temporaire servira alors de source de données pour
la liste déroulante proposant les noms des QCM. Enfin, les variables nom_table et
nom_champ déclarées comme des chaînes de caractères (String) permettront de
piloter cette table.

Après la déclaration, suit l'initialisation et l'affectation des variables.


 A la suite du code VBA, ajouter les affectations suivantes :
i=0
nom_table = 'Liste_tables'
nom_champ = 'Questionnaire'
Set la_base = Application.CurrentDb

La variable i servira de compteur pour insérer chacun des noms de table prélevés,
dans le tableau de valeur précédemment déclaré. Nous l'initialisons donc à zéro, soit
sur l'indice du premier élément à insérer. Les variables nom_table et
nom_champ stockent respectivement le nom de la table temporaire et de son champ
dans lequel seront ajoutés les titres des questionnaires. Enfin, nous initialisons
la variable objet la_base grâce au mot clé Set sur la base de données en cours. C'est
la méthode CurrentDb de l'objet VBA Access Application qui permet de pointer sur
la base de données courante.

Nous devons désormais parcourir toutes les tables de la base de données. Pour ce
faire nous devons exploiter la variable objet chaque_table afin de parcourir et
d'accéder à la définition de chacune d'elle. Et pour parcourir chacun de ces objets,
nous devons utiliser une boucle For Each.
 En conséquence, ajouter les bornes de la boucle For Each comme suit :
For Each chaque_table In la_base.TableDefs

Next

Une boucle For Each se borne avec le mot clé Next. Les éléments parcourus se
situent à droite du mot clé In dans la syntaxe de la boucle. La propriété
TableDefs d'un objet base de données est une collection qui permet d'accéder à
toutes les tables qu'elle contient. L'élément à gauche du mot clé In doit être du
même type que le groupe parcouru. C'est pourquoi nous avions déclaré l'objet
chaque_table comme un TableDef.

Les tables système ne sont pas visibles par l'utilisateur mais sont accessibles par le
code. Il faut donc les exclure du traitement. Nous devons réaliser un test sur le nom
de chacune des tables dans la boucle, grâce à une instruction conditionnelle If pour
vérifier la condition. Le nom des tables système commence toujours par les trois
lettres Msy.
 Dans la boucle, ajouter le test pour exclure les tables système du traitement :
If UCase( Left( chaque_table.Name, 3)) <> 'MSY' And Left( chaque_table.Name, 1) <>
'~' And chaque_table.Name <> 'Liste_tables' Then

End If

Grâce à la propriété Name de l'objet TableDef, nous récupérons le nom de la table


en cours de lecture dans la boucle. Nous n'en prélevons que les trois premières
lettres grâce à la fonction VBA Left et son second paramètre (3). Nous convertissons
ces trois caractères prélevés en majuscules pour éviter les problèmes de casse dans la
comparaison. Nous cherchons à savoir s'ils sont bien différents des trois lettres (MSY)
du préfixe des tables système. Dans la foulée, nous vérifions un autre critère (AND)
pour nous assurer que le nom de la table ne commence pas par le symbole ~. Ce cas
se produit lorsque des tables temporaires sont supprimées. Enfin nous excluons du
filtre la table temporaire potentielle que nous utiliserons pour enregistrer les
informations (chaque_table.Name <> 'Liste_tables').

Si ces trois conditions sont vérifiées, nous savons que les tables restantes
correspondent bien aux questionnaires dont nous souhaitons prélever les noms. Pour
nous en assurer, nous allons réaliser un test grâce à la fonction MsgBox qui permet
d'afficher un message à l'écran.
 Dans les bornes de l'instruction If de la boucle For Each, ajouter la ligne de code
suivante :
MsgBox chaque_table.Name
 Enregistrer les modifications (CTRL + S),
 Basculer sur le formulaire Access (ALT + F11),
 Exécuter ce dernier (F5),

Le formulaire apparaît et affiche effectivement le premier nom de table présent dans


la base de données. Il faut cliquer jusqu'à atteindre le dernier nom pour que
l'exécution du code se termine. Cet essai a permis de confirmer que nous parvenions
bien à accéder aux informations des tables de la base de données.
 Afficher de nouveau le formulaire en mode Création,
 Basculer dans l'éditeur de code Visual Basic Access (ALT + F11),
 Supprimer la ligne précédente du MsgBox,
 A la place, ajouter les instructions de code suivantes :
i=i+1
tabval(i) = chaque_table.Name

Ainsi, nous stockons chacun des noms prélevés (chaque_table.Name) dans une ligne
du tableau de valeur (tabval(i) = chaque_table.Name) après avoir incrémenté l'indice
qui permet de désigner la position (i = i + 1).

Avant de pouvoir stocker ces informations dans la table temporaire, nous devons
commencer par la supprimer, si elle a été générée par une précédente ouverture du
formulaire. Comme elle est exclue du traitement par le critère de l'instruction
conditionnelle If, nous devons ajouter cette nouvelle ligne de code après le End If,
mais toujours dans la boucle.
 Après le End If mais avant le Next qui clôture la boucle, ajouter la ligne suivante :
If chaque_table.Name = nom_table Then
la_base.TableDefs.Delete nom_table
L'instruction If permet de vérifier si le nom de la table est bien celui de la table
prévue pour stocker tous les noms de questionnaires (nom_table). Si c'est le cas,
la méthode Delete de la propriété TableDefs de l'objet de base de données
la_base permet de supprimer cette table, en lui passant en paramètre, son nom
mémorisé par la variable.

Créer et paramétrer une table en VBA Access


Nous pouvons désormais récréer cette table vierge. Nous lui associerons un seul
champ qui permettra d'ajouter pour chaque enregistrement, le nom de chaque
questionnaire, représenté par le nom de chaque table parcourue. Ce traitement ne
doit être réalisé qu'une seule fois. Le code doit donc être écrit en dehors de la boucle.
C'est la raison pour laquelle nous avons mémorisé temporairement ces noms dans le
tableau de valeurs tabval. Pour créer cette table, nous devons exploiter les variables
objets déclarées en début de code.
 A la suite du code, après la boucle, soit après le mot clé Next, ajouter les instructions
suivantes :
Set nouvelle_table = la_base.CreateTableDef(nom_table)
Set nouveau_champ = nouvelle_table.CreateField(nom_champ, dbText, 25)
nouvelle_table.Fields.Append nouveau_champ
la_base.TableDefs.Append nouvelle_table

Set nouvelle_table = Nothing


Set nouveau_champ = Nothing

Le mot clé Set est utilisé une fois de plus pour initialiser et instancier les objets de
base de données qui avaient été déclarés à cet effet. Ainsi la méthode
CreateTableDef de l'objet base de données permet de créer une table du nom passé
en paramètre. Mais ce n'est pas suffisant, une table doit avoir au moins un champ
typé. Et la création du champ comme celle de la table doivent être confirmées par
des méthodes VBA précises. C'est pourquoi nous exploitons la méthode
CreateField de l'objet fraîchement instancié afin de créer le champ nécessaire passé
en paramètre (nom_champ), avec son type (dbText) et sa longueur (25).

C'est alors que la méthode Append de la propriété Fields de l'objet de création de


table, permet de confirmer la création du champ représenté par l'objet passé en
paramètre, donc avec toutes ses propriétés. Cette même méthode, cette fois de
la propriété TableDefs de l'objet de base de données, permet de confirmer la
création de la table, avec l'objet passé en paramètre, donc avec toutes ses propriétés.

Enfin, comme nous l'avions appris dans la formation VBA pour archiver les données
de base Access, le mot clé Nothing permet de décharger ces objets, qui ne sont plus
exploités. Enfin, maintenant que la table est créée, nous devons y accéder par le
code, pour ajouter les enregistrements, dont les informations sont contenues dans le
tableau de valeur.

Nous allons tester que ces lignes de code ont bien permis de créer la table à la volée.
 Enregistrer les modifications (CTRL + S),
 Basculer sur le formulaire Access (ALT + F11) et exécuter ce dernier (F5),
A notre grande surprise, une erreur est générée. Il s'agit d'une incompatibilité de
type. Aussi étonnant que cela puisse paraître, c'est la référence à la
librairie Microsoft ActiveX Data Objects qui pose conflit. Nous devons la désactiver et
adapter les déclarations des variables objets afin d'accéder seulement aux classes
nécessaires, afin que tout conflit soit levé.
 Cliquer sur le bouton Réinitialiser en haut de l'éditeur de code pour stopper
l'exécution,
 Dérouler le menu Outils et cliquer sur Références dans la liste,
 Décocher la case Microsoft ActiveX Data Objects 6.1 Library,
 Ajouter le préfixe DAO dans la déclaration des variables d'objets de base de données :
Dim la_base As DAO.Database
Dim chaque_table As DAO.TableDef
Dim tabval(20)
Dim i As Integer, j As Integer
Dim nouvelle_table As  DAO.TableDef : Dim nouveau_champ As DAO.Field : Dim
nouvel_enregistrement As  DAO.Recordset
Dim nom_table As String, nom_champ As String
 Enregistrer les modifications (CTRL + S),
 Basculer sur le formulaire Access (ALT + F11) et exécuter ce dernier (F5),

Comme vous le constatez, la nouvelle table apparaît bien dans le volet de gauche


des objets de la base de données Access. Bien sûr à ce stade, si vous double cliquez
sur son nom pour l'ouvrir, vous constatez qu'elle est vide. Nous n'avons pas encore
écrit le code VBA permettant de lui ajouter des enregistrements.

Ajouter des enregistrements à une table en VBA


Dans la formation permettant d'archiver les données en VBA Access, nous avions
appris à ajouter des enregistrements dans une table existante, par le code Visual
Basic Access. Nous allons répliquer ce code.
 Afficher le formulaire en mode création puis basculer dans l'éditeur de code (ALT +
F11),
 A la suite du code, ajouter les instructions suivantes :
Set nouvel_enregistrement = la_base.OpenRecordset(nom_table, dbOpenDynaset)
For j = 1 To i
nouvel_enregistrement.AddNew
nouvel_enregistrement.Fields(nom_champ) = tabval(j)
nouvel_enregistrement.Update
Next j

La méthode OpenRecordset d'un objet de base de données, permet d'accéder aux


enregistrements de la table dont le nom est désigné en premier paramètre
(nom_table). Le deuxième paramètre de la méthode, dbOpenDynaset indique le
mode d'accès à la table. Il s'agit ici d'un accès en mode modification. Il doit y avoir un
nouvel enregistrement pour chaque questionnaire à recenser. Donc nous
construisons une boucle capable de parcourir tous les noms mémorisés dans le
tableau de valeurs (For j = 1 To i). 1 est le premier élément tandis que le dernier est
référencé à la dernière valeur enregistrée par l'incrément de la variable i. Ensuite et
comme nous l'avions appris, la méthode AddNew d'un objet RecordSet permet
d'initialiser la création d'un enregistrement. Chronologiquement, suivent les
informations à renseigner pour les champs de l'enregistrement à créer
(nouvel_enregistrement.Fields(nom_champ) = tabval(j)). Puis la méthode
Update d'un objet RecordSet, permet de confirmer et valider la création de
l'enregistrement.

Nous n'avons plus besoin des objets de base de données. Afin de coder proprement
nous devons les décharger.
 Ajouter les lignes permettant de vider les variables objets de base de données de la
mémoire :
Set nouvel_enregistrement = Nothing
Set la_base = Nothing
 Enregistrer les modifications (CTRL + S),
 Basculer sur le formulaire Access (ALT + F11) et l'exécuter (F5),
 Double cliquer sur le nom de la table ListeTables depuis le volet des objets Access,

Comme vous le remarquez, un enregistrement a été créé par questionnaire,


correspondant chacun au nom de la table qui lui est associé. Mais malgré tout, la liste
déroulante du formulaire est toujours vide. En effet, nous avons bien rempli la table
des informations nécessaires mais nous ne l'avons pas encore désignée comme
source de données de la liste déroulante.
 Fermer la table et afficher le formulaire en mode création,
 Basculer dans l'éditeur de code Visual Basic,
Un contrôle de formulaire se pilote dans le code VBA par son nom d'objet. C'est lui
qui permet d'accéder aux propriétés et méthodes. Le nom défini pour la liste
déroulante à charger est Liste.
 A la suite du code, ajouter les deux instructions suivantes :
Liste.RowSourceType = 'Table/Requête'
Liste.RowSource = 'ListeTables'

Nous devons d'abord définir quelle est la nature de la source de données pour la liste
déroulante, comme si nous le faisions depuis la feuille de propriétés du formulaire.
C'est la propriété RowSourceType de l'objet zone de liste qui, affecté à la valeur
Table/Requête, permet d'indiquer que la source est une table. Alors, sa propriété
RowSource, affectée au nom de la table établit le lien.
 Enregistrer les modifications, basculer sur le formulaire et l'exécuter,
Le lien est cette fois établi. Le code permettant de charger le contenu d'une zone de
liste avec les noms de tables de la base de données, a fonctionné. Cependant, si vous
cliquez sur l'un des sujets, rien ne se produit pour l'instant. Nous n'avons pas encore
écrit le code permettant de transmettre les informations nécessaires au formulaire
question, afin qu'il charge la table correspondante du QCM. C'est l'objet de la
prochaine formation permettant de modifier des données d'un formulaire depuis un
formulaire externe. Ainsi petit à petit, nous allons monter l'application finale qui
permettra d'évaluer les candidats selon leur choix de questionnaire.
 

Vous aimerez peut-être aussi