Pour partager cette vidéo sur les réseaux sociaux ou sur un site, voici son url :
Sujets que vous pourriez aussi aimer :
Jeu aléatoire d'enregistrements
Savoir générer un
jeu d'enregistrements aléatoires n'est pas du tout futile contrairement à ce que l'on pourrait croire. Dans le cas d'une
application d'évaluation par QCM , il est intéressant de pouvoir proposer un groupe de questions toujours différent. C'est ainsi qu'une
évaluation n'est jamais la même, y compris pour un même candidat, d'un test à un autre. Cette nouvelle
astuce VBA Access démontre comment choisir des questions au
hasard .
Dans l'exemple illustré par la capture, l'utilisateur choisit un
thème d'évaluation à l'aide d'une
liste déroulante . Chaque thème proposé correspond au nom d'une table. Et lorsque l'utilisateur clique sur le bouton Générer, ce sont dix questions qui sont extraites aléatoirement de la table ainsi désignée. A chaque nouveau clic, les questions changent complètement et bien sûr, aucun doublon n'est proposé dans un même jeu.
Base de données Access à télécharger
Pour la découverte de cette technique, nous suggérons d'appuyer l'étude sur une
base de données offrant ces
questionnaires . Bien qu'anciens, ils feront l'affaire.
Le
volet de navigation , sur la gauche de l'écran, présente les
sept tables des questionnaires et le
formulaire nommé
fQuestions .
Si vous double cliquez sur l'une ou l'autre table, vous remarquez qu'elles ont toutes la même architecture. Les questions sont toutes énumérées dans un
champ nommé
QUESTION .
Dans le volet de navigation, double cliquer sur le formulaire fQuestions ,
Dès lors, déployer la liste déroulante sur la gauche et choisir un thème,
Comme vous le constatez, ces thèmes sont issus des noms des tables.
Bien sûr et fort logiquement à ce stade, si vous cliquez sur le
bouton Générer , aucun jeu d'enregistrements aléatoires n'est encore produit.
Liste déroulante des noms de tables
Mais comme vous avez pu le constater, la liste est automatiquement chargée des
noms des tables , donc des intitulés des
questionnaires . Et tout cela se produit au
chargement du formulaire par un
code VBA offert.
A gauche du ruban Accueil , cliquer sur la flèche du bouton Affichage ,
Dans la liste des propositions, choisir le mode Création ,
Dès lors, cliquer sur le carré grisé en haut à gauche, à l'intersection des règles,
De cette manière, nous désignons le formulaire parent explicitement.
Activer l'onglet Evénement de sa feuille de propriétés ,
Vous remarquez la présence d'une
procédure événementielle attachée à son
événement Sur activation . Ce code se déclenche notamment à chaque
chargement du formulaire et il concerne la
liste déroulante .
Cliquer sur le petit bouton situé à l'extrémité droite de cet évenement,
De cette manière, nous basculons dans l'
éditeur VBA Access entre les bornes de la
procédure événementielle Form_Current :
Private Sub Form_Current()
Dim base As Database
Dim table As TableDef
Set base = CurrentDb()
For Each table In base.TableDefs
If Left(table.Name, 4) <> "MSys" Then
Questionnaire.AddItem table.Name
End If
Next table
base.Close
Set table = Nothing
Set base = Nothing
End Sub
Il s'agit d'un
code VBA Access que nous avons conçu à l'occasion de la précédente astuce. Il parcourt toutes les tables de la base de données pour charger leurs noms (Méthode AddItem) dans la liste déroulante.
Générer au clic
Désormais, nous devons créer la
procédure de code qui doit se déclencher
au clic sur le bouton pour générer des
questionnaires aléatoires .
Revenir sur le formulaire en conception,
Cliquer sur le bouton Générer pour le sélectionner,
Dans sa feuille de propriétés , cliquer sur le petit bouton associé à son événement Au clic ,
Nous revenons ainsi dans l'
éditeur VBA Access , mais cette fois entre les bornes de la
procédure generer_Click . Son code se déclenchera naturellement au clic sur ce bouton.
Private Sub generer_Click()
End Sub
Son code est naturellement vide pour l'instant. C'est forcément lui que nous devons implémenter pour générer ces
questionnaires aléatoires sur ordre.
Les objets de base de données
Ensuite et pour pouvoir accéder aux
enregistrements des tables , nous devons déclarer des
objets permettant de piloter cette
base de données . Il s'agit de
déclarations et affectations de variables que nous maîtrisons bien désormais.
Dans les bornes de la procédure, ajouter les déclarations suivantes :
...
Dim base As Database: Dim enr As Recordset
Dim nomTable As String: Dim compteur As Byte
Dim nbEnr As Integer: Dim numEnr As Integer
Dim mem As String
...
Nous déclarons un
objet de type Database pour piloter la
base de données en cours et un
objet de type Recordset pour manipuler les
enregistrements des tables de cette base. Les déclarations qui suivent sont plus classiques. Nous mémoriserons le
choix du questionnaire dans la
variable nomTable , typée comme un texte. La
variable compteur doit compter les enregistrements restitués pour limiter la sélection Ã
dix questions . Nous stockerons le
nombre total d'enregistrements de la
table dans la
variable nbEnr . Nous génèrerons les numéros à atteindre dans la
variable numEnr . Enfin, la
variable mem , typée comme un texte, est destinée à mémoriser tous les numéros d'enregistrements
générés aléatoirement pour ne pas les reproposer. Et nous verrons bientôt comment nous allons nous y prendre.
Vérifier le choix du questionnaire
Avant de poursuivre, nous devons nous assurer que l'utilisateur a bien choisi un
questionnaire , donc une
table . C'est seulement si la liste déroulante de choix porte une valeur que la suite du
traitement VBA peut être entreprise.
Après la déclaration des variables, ajouter les instructions VBA suivantes :
...
If (Questionnaire.Value <> "") Then
mem = "-": Randomize
compteur = 0: nomTable = Questionnaire.Value
Set base = CurrentDb()
Set enr = base.OpenRecordset(nomTable)
End If
...
L'
instruction conditionnelle permet de tester le contenu de la
liste déroulante nommée
Questionnaire . Si elle porte bien une valeur (<>""), alors (Then) nous engageons le traitement. Et pour cela, nous entamons l'
initialisation des variables . Nous inscrivons un tiret dans la
variable mem . Nous allons effectivement mémoriser les numéros générés, séparés par des tirets pour éviter toute confusion. En vue de la génération aléatoire à venir, nous appelons la
fonction VBA Randomize . Elle permet d'initialiser le processus sur l'horloge système afin d'assurer de vraies
générations au hasard . Nous prélevons ensuite le choix du questionnaire dans la
variable nomTable . Puis, nous nous occupons des
variables de BDD . Grâce à la
fonction CurrentDb , nous initialisons la
variable base qui de fait, hérite des
propriétés et méthodes pour piloter la
base de données en cours . Et pour preuve dans l'enchaînement, nous initialisons la
variable enr grâce à sa
méthode OpenRecordset ainsi héritée. En lui passant le
nom de la table choisie par l'utilisateur, elle fournit à la
variable enr , les
enregistrements à manipuler.
Compter les enregistrements de la table
Avant de chercher à manipuler les enregistrements, nous devons déjà nous assurer qu'ils existent. Et pour cela, nous pouvons exploiter la
propriété RecordCount d'un
objet de type Recorset . Nous aurons ainsi la borne supérieure absolument essentielle pour entreprendre une
génération aléatoire de numéros à tirer au sort.
A la suite, mais toujours dans le bloc du If, ajouter les instructions VBA suivantes :
...
Set base = CurrentDb()
Set enr = base.OpenRecordset(nomTable)
If enr.RecordCount <> 0 Then
nbEnr = enr.RecordCount
lesQuestions.Value = "<u><strong>10 questions aléatoires:</strong></u><br />"
End If
End If
...
Si la table choisie offre bien des enregistrements (enr.RecordCount <> 0), alors nous mémorisons ce nombre dans la
variable nbEnr . Puis, nous initialisons le titre de la zone de texte multiligne avec des attributs de mise en forme grâce à des balises Html.
Boucle de génération aléatoire
Maintenant que la borne supérieure est connue, nous devons engager le traitement dans une
boucle . Son rôle est de produire
dix numéros d'enregistrements au hasard et tous différents les uns des autres. C'est la
variable compteur qui doit servir de test. Tant que les dix nombres n'ont pas été produits, le traitement doit recommencer.
A la suite de cette seconde instruction conditionnelle, ajouter les lignes VBA suivantes :
...
Set enr = base.OpenRecordset(nomTable)
If enr.RecordCount <> 0 Then
nbEnr = enr.RecordCount
lesQuestions.Value = "<u><strong>10 questions aléatoires:</strong></u><br />"
While compteur < 10
With enr
End With
compteur = compteur + 1
Wend
End If
End If
...
Tant que les dix nombres ne sont pas générés (While compteur < 10), nous poursuivons le traitement. Celui-ci va bien sûr consister Ã
tirer au sort des
numéros d'enregistrements de la
table pour en restituer
aléatoirement les questions. Dans cette
boucle et à des fins d'optimisation de code, nous créons un
bloc With sur la
variable enr . En effet, nous allons appeler quelques
propriétés et méthodes de cet
objet . Autant les regrouper pour ne pas répéter à chaque occasion le nom de cet objet. Enfin, nous n'oublions pas d'
incrémenter la variable de boucle (compteur = compteur + 1).
Numéros aléatoires d'enregistrements
Nous atteignons désormais l'étape cruciale. C'est maintenant que nous devons
générer dix numéros aléatoires d'enregistrements , tous différents les uns des autres. Et pour cela, nous allons stocker chaque nombre produit dans la
variable mem . Ainsi à chaque nouvelle génération, nous vérifierons si le numéro produit n'est pas déjà inscrit dans cette variable.
Dans le bloc With , ajouter les instructions VBA suivantes :
...
With enr
refaire:
numEnr = Int((nbEnr) * Rnd) + 1
If (InStr(1, mem, "-" & numEnr & "-") <> 0) Then
GoTo refaire
Else
mem = mem & numEnr & "-"
End If
End With
...
Nous créons tout d'abord une
étiquette nommée
refaire . Elle fait figure de point de référence. Nous y renverrons le
code VBA tant que le numéro généré a déjà été proposé. C'est une sorte de
boucle , aux
bornes aléatoires , à l'intérieur même de la
boucle While . Nous générons ensuite le
numéro aléatoire entre le premier et le dernier enregistrement selon cette formule : Int((borneSup -borneInf + 1) * Rnd + borneInf). Grâce à la
fonction Instr , nous vérifions sa présence encadrée de tirets dans la
variable mem . Si cette fonction renvoie une position (<>0), cela signifie que le numéro a déjà été proposé. Nous renvoyons donc le code à l'étiquette (GoTo refaire) pour recommencer la génération. Dans le cas contraire (else), nous mémorisons ce numéro à la suite des autres et suffixé d'un tiret.
Déplacer le curseur sur l'enregistrement aléatoire
Désormais à chaque passage dans cette
boucle While et pour chaque nouveau numéro généré, nous devons nous déplacer sur l'enregistrement correspondant dans la table. C'est ainsi que nous pourrons prélever ses informations, en l'occurrence ici, il s'agit de ponctionner la question du
champ QUESTION .
A la suite du bloc With, ajouter les trois instructions VBA suivantes :
...
With enr
refaire:
numEnr = Int((nbEnr) * Rnd) + 1
If (InStr(1, mem, "-" & numEnr & "-") <> 0) Then
GoTo refaire
Else
mem = mem & numEnr & "-"
End If
.MoveFirst
.Move numEnr - 1
lesQuestions.Value = lesQuestions.Value & "<br />" & compteur + 1 & "/ Num : " & numEnr & " : " & .Fields("QUESTION")
End With
...
Nous plaçons tout d'abord le
pointeur de lecture sur le tout
premier enregistrement de la table grâce à la
méthode MoveFirst de l'
objet enr . C'est ainsi que nous pouvons entreprendre un
déplacement vers le bas jusqu'au numéro généré grâce à la
méthode Move de ce même objet. Nous enlevons une unité à ce score (-1) puisque le pointeur est déjà placé sur le premier enregistrement, donc déjà décompté. Ensuite, nous concaténons simplement les informations récoltées les unes en dessous des autres (<br />) dans la zone de texte multiligne (lesQuestions). Et c'est la
propriété Fields de l'
objet enr qui permet de pointer sur le champ par son nom.
Nous n'en avons pas tout à fait terminé. Comme vous le savez, les
objets de base de données , quand ils ne sont plus utilisés, doivent être fermés et détruits. C'est ainsi que nous libérons les ressources.
A la toute fin du code avant le End Sub, ajouter les quatre instructions VBA suivantes :
...
Wend
End If
End If
enr.Close
base.Close
Set base = Nothing
Set enr = Nothing
End Sub
...
Simplement, nous fermons la connexion aux enregistrements et à la base de données grâce à la
méthode Close des objets respectifs. Puis, nous les détruisons de la mémoire en les réinitialisant (Set) sur la
valeur Nothing .
Enregistrer les modifications (CTRL + S) et basculer sur le formulaire (ALT + Tab),
L'enregistrer à son tour et l'exécuter avec la touche F5 du clavier,
Choisir un questionnaire avec la liste déroulante et cliquer sur le bouton Générer ,
Comme vous pouvez l'apprécier à chaque clic, c'est un lot de dix nouvelles questions aléatoires qui est proposé.