Les boucles While / Until : répéter une opération tant qu’une condition est remplie (ou jusqu’à ce qu’elle soit remplie) [#17 FORMATION EXCEL VBA COMPLETE]
Continuons la découverte des boucles au sein de VBA avec les boucles While et Until sous leurs différentes formes !
Téléchargement
Vous pouvez obtenir le fichier d'exemple de cet article et découvrir la méthode d'apprentissage de VBA pas-à-pas en cliquant sur le lien suivant :
Tutoriel Vidéo
Vous trouverez très régulièrement de nouvelles vidéos sur la chaîne, alors pensez à vous abonner pour ne manquer aucune astuce et devenir rapidement un pro d’Excel (cliquez-ici) !
1. Présentation
Il existe encore un autre type de boucle que nous pouvons utiliser lors du développement de nos applications en VBA, il s’agit de la boucle While ainsi que de son inverse : Until.
Celles-ci permettent de répéter une opération tant qu’une condition est remplie (pour la boucle While), ou à l’inverse tant qu’une opération n’est PAS remplie (cette fois-ci avec la boucle Until).
Nous préférerons utiliser ce type de boucle lorsque nous ne connaissons pas le nombre de répétitions que nous souhaitons mettre en place (au contraire de la boucle For pour laquelle nous spécifions dès sa création les bornes de départ et d’arrivée).
2. La classique boucle While… Wend
Il s’agit de la manière d’utiliser la boucle While la plus simple qu’il soit, nous déclarons celle-ci avec le mot-clé While, puis marquons la fin avec Wend (forme raccourcie de While End) :
Sub quizzAddition()
Dim a As Integer, b As Integer
a = 4
b = 2
While InputBox("Combien font " & a & " + " & b & " ?") <> a + b
MsgBox "Faux, veuillez recommencer !"
Wend
MsgBox " Bravo, vous avez gagné !"
End Sub
Ici nous instancions deux variables a et b auxquelles nous affectons des valeurs (respectivement 4 et 2).
Ensuite nous demandons à l’utilisateur de saisir un nombre :
Puis tant que le résultat n’est pas égal à la somme des valeurs de a et b, nous lui affichons une notification d’erreur.
Enfin, lorsque le résultat saisi est bien égal à 6, alors nous sortons directement de la boucle et affichons cette fois un message de félicitation.
Cette structure de boucle est effectivement rapide et simple à mettre en place, mais mieux utiliser les structures que nous verrons juste après, qui sont mieux gérées par VBA et proposent davantage de souplesse notamment par l’existence d’une possibilité de quitter prématurément la boucle.
3. La variante Do While… Loop
Il existe une variante à cette boucle, dont le résultat est exactement identique, il s’agit de la boule Do While… Loop :
Do While InputBox("Combien font " & a & " + " & b & " ?") <> a + b
MsgBox "Faux, veuillez recommencer !"
Loop
Le test conditionnel peut également être réalisé en fin de boucle :
Do
MsgBox "Faux, veuillez recommencer !"
Loop While InputBox("Combien font " & a & " + " & b & " ?") <> a + b
Dans ce cas, l’instruction va être réalisée une première fois avant que le test ne soit réalisé.
C’est la raison pour laquelle la notification d’erreur de calcul est affichée avant même que le joueur n’a eu l’occasion de renseigner le moindre résultat :
Il est possible de quitter prématurément une boucle Do While grâce à l’instruction Exit Do :
Do While InputBox("Combien font " & a & " + " & b & " ?") <> a + b
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Do
Loop
Lorsque nous utilisons cette instruction, le code reprend le fil de son déroulement à partir de la ligne qui suit la fin de la boucle (après la ligne Loop), c’est pourquoi la macro nous affiche quand même un message de félicitation !
L’astuce pour éviter cela est de quitter toute la procédure et non pas simplement la boucle.
Pour cela nous utiliserons plutôt Exit Sub :
Do While InputBox("Combien font " & a & " + " & b & " ?") <> a + b
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Sub
Loop
Attention : tout comme nous l’avons déjà abordé dans les chapitres précédents, il est possible de générer des bugs pouvant aboutir sur la génération d’une boucle infinie ! En effet étant donné que la boucle se répète tant qu’une condition est (ou pas) remplie, il faut être vigilent sur la construction des conditions :
Do While a <> b
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Do
Loop
Dans cet exemple, nous souhaitons recommencer le cheminement de la boucle tant que a est différent de b, ce qui sera évidemment toujours le cas (pour le moment les valeurs de a et de b ne changent jamais) !
Heureusement que nous y avons laissé une porte de sortie avec le Exit Do, qui nous évitera d’être face à une boucle infinie, synonyme de plantage (et donc de perte potentielle de données !)
4. L’inverse Do Until… Loop
À l’inverse de la boucle Do While que nous venons de voir, il existe également la boucle Do Until qui elle permet de répéter une partie de code tant qu’une condition n’est pas remplie !
Nous pouvons ainsi traduire cette boucle de la manière suivante : « Répéter l’opération JUSQU’À ce que … ».
Cette déclinaison de la boucle Do est donc encore plus adaptée à notre code :
Do Until InputBox("Combien font " & a & " + " & b & " ?") = a + b
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Sub
Loop
Bien évidemment, le test peut tout aussi bien être réalisé après avoir lancé la boucle une première fois en plaçant le test après l’instruction Loop :
Do
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Sub
Loop Until InputBox("Combien font " & a & " + " & b & " ?") = a + b
5. Imbrication de boucles Do While / Do Until
L’imbrication des boucles au sein d’autres boucles est également tout à fait possible.
Dans cet exemple, nous allons souhaiter affecter de nouvelles valeurs aux variables a et b, mais pour faciliter le calcul nous souhaitons que ces deux variables aient des valeurs strictement identiques.
Pour cela, nous encapsulons la génération de ces valeurs aléatoire dans une boucle Do… Loop Until :
Do Until InputBox("Combien font " & a & " + " & b & " ?") = a + b
If MsgBox("Faux ! Souhaitez-vous recommencer ?", vbYesNo) = vbNo Then Exit Sub
Do
Randomize
a = CInt(Rnd * 10)
b = CInt(Rnd * 10)
Loop Until a = b
Loop
Nous demandons ainsi que générer un nombre compris entre 1 et 9 pour chacune de ces deux valeurs, et nous répétons cette opération JUSQU’À ce que les valeurs soient identiques !
Réaliser le test après avoir lancé la boucle une première fois permet de s’assurer que de nouveaux nombres vont effectivement être calculés. En effet, si nous avions fait le choix d’effectuer le test sans générer au préalable de nouveau nombre, alors la condition serait effectivement toujours remplie à partir de la deuxième itération !