Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Double boucle Do donne une vilaine boucle infinie


Sujet :

Macros et VBA Excel

  1. #1
    Nouveau membre du Club
    Double boucle Do donne une vilaine boucle infinie
    Bonsoir à tous,

    Voici un code fonctionnel bien qu'esthétiquement douteux, à mon sens.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    Sub g()
    Dim i, x, k, b As Integer
    Dim o, p As String
    Do
        x = Int((10 * Rnd) + 1)
        If x = b Then
            Call g
        Else
            For i = 1 To 10
            o = InputBox("combien font " & x & "x" & i & "?")
            If Val(o) = x * i Then
                MsgBox ("bravo nestor")
            Else
                MsgBox ("raté nestor, la bonne réponse était : " & x * i)
                k = k + 1
            End If
            Next i
                MsgBox ("votre nombre total d'erreurs est de : " & k)
                p = InputBox("souhaitez-vous jouer à nouveau ? (y/n)")
                x = b
        End If
    Loop While p = "y"
    End Sub


    L'horrible Call g n'est présent que pour une seule raison :

    Je n'ai pas réussi à intégrer une autre boucle Do dans ma boucle Do générale afin de vérifier que l'on n'avait pas la même table à jouer deux fois de suite (x≠b). Mon code commençait tel que : Do [incrément] Do et j'ai fait face à des boucles infinies qui m'ont fait la grâce, tout du moins la première, de retaper l'intégralité de mon code, heureusement saisi in extremis par screenshot.

    Notez que si j'utilise une boucle Do c'est parce que je ne vois pas comment faire autrement avec des If.

    Question 1 : comment remplacer le très peu orthodoxe Call g sans trop toucher à mon code ?

    En fait, je ne sais comment faire quelque chose tel que :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ...
    Next i
    MsgBox ("votre nombre total d'erreurs est de : " & k)
    p = InputBox("souhaitez-vous jouer à nouveau ? (y/n)")
    if y then
    	LOOP RETOURNE AU DEBUT DU PROGRAMME
    else
    	exit sub


    Question 2 : comment faire une boucle de type If tel que je le souhaitais initialement ?

  2. #2
    Rédacteur

    Bonjour,
    Difficile de t'aider pour l'imbrication de deux Do sans savoir ce que tu testes.
    En ce qui concerne le MsgBox, je ne vois pas pourquoi tu utilises à la suite un InputBox et un MsgBox, il suffit d'utiliser le MsgBox comme une fonction et pas comme une méthode

    Je te conseille la lecture de ce tutoriel VBA EXCEL La MsgBox décortiquée
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Quelques contributions : USERFORM - Créer, Consulter, Modifier et Supprimer des enregistrements à l'aide d'un formulaire - Géolocalisation d'une adresse avec Excel et Google sans VBA

  3. #3
    Nouveau membre du Club
    Lu.

    Voici le screenshot de ma boucle infinie.



    Que j'ai modifié en le code publié dans la message précédent.

    L'objectif est simplement de faire une micro-bouclette en début de grande boucle afin de tester que x, qui est donc la variable aléatoire de la table de multiplication à réviser, n'est pas de la même valeur deux fois de suite. D'où l'idée de mon x=b un peu plus loin dans la grande boucle.

    //

    Monsieur est amateur de Boileau. Monsieur a toutes mes salutations.

  4. #4
    Membre expert
    Bonjour,

    ta boucle infinie est là
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        Do
            x = Int(10 * Rnd + 1)
        Loop Until x = b


    ton "b" est vide et ton "x" jamais donc .... tu lui dis : boucle jusqu'a ce que x = b ... ben il boucle !!!!
    Ils ne savaient pas que c'était impossible ... du coup ils l'ont fait (Mark Twain)

    n'oubliez pas de si les messages vous aide ou sont pertinents et de mettre quand cela est !

  5. #5
    Expert confirmé
    Bonjour,

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        Do
            x = Int(10 * Rnd + 1)
        Loop Until x = b


    Je ne comprends l'intérêt de ce code, pourquoi donné à X une valeur aléatoire si au final tu veux qu'il soit égal à b
    J'aimerais bien aller vivre en Théorie, car en Théorie tout se passe bien.

  6. #6
    Membre extrêmement actif
    Bonjour

    cette ligne :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    x = b

    affecte à x la valeur de b et pas à b la valeur de x ...
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  7. #7
    Membre expert
    Bon quelques notions s'imposent
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    Dim i, x, k, b As Integer
    Dim o, p As String
    Ceci déclare i,x,k,o en VARIANT !! il faut faire
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    Dim i As Integer, x As Integer, k As Integer, b As Integer
    Dim o As String, p As String

    perso moi je les mets les uns en dessous des autres pour pouvoir mettre des commentaires derrière avec " ' "

    il est plus facile de déboguer une variable qui a un nom parlant plutôt qu'une lettre seule.
    par exemple : nom la variable de cumul des erreurs Cum_Err plutôt que k

    moi j'utiliserai une variable genre Cpt_Tab qui compterait le nombre de table révisées et 3variables Tab1, Tab2, Tab3 qui stockerait les tables révisées

    sinon au vu des valeurs de tes variables tu ne va pas dépassé 100 donc tu peux tout déclarer en Byte au lieu d'intéger
    Ils ne savaient pas que c'était impossible ... du coup ils l'ont fait (Mark Twain)

    n'oubliez pas de si les messages vous aide ou sont pertinents et de mettre quand cela est !

  8. #8
    Responsable
    Office & Excel

    Salut.

    Voici un code fonctionnel. Tu peux l'analyser en le lançant en pas à pas (F8). Tu pourras ainsi voir comment il fonctionne. J'ai supposé que le but de l'exercice était d'utiliser les boucles, je n'ai donc pas sécurisé la saisie de la réponse et estimé qu'elle était "dans les clous" (numérique et comprise entre -32767 et 32768).


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Sub Multi()
      Dim i As Integer, x As Integer, y As Integer
      Dim Result As Integer
     
      Do
        Do
          x = Int((10 * Rnd) + 1)
        Loop While x = y
        y = x
        For i = 1 To 10
          Result = InputBox("Combien font " & i & " x " & x & "? (0 pour stopper)", "Table de multliplication")
          If Result = x * i Then
            MsgBox "Correct"
          Else
            MsgBox "Faux"
          End If
        Next
      Loop While MsgBox("Voulez-vous continuer?", vbYesNo + vbQuestion, "Table de multiplication") = vbYes
    End Sub
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  9. #9
    Membre expert
    Bonjour à tous,

    Ben Pierre tu as testé ton code ?????

    As-tu lu mon permier post (N°4) Ce n'est pas en changeant la variable B en y que la boucle ne sera pas infinie.

    Et ta variable Y sert à ....... ????

    je me suis permis de te faire un exemple aussi

    pour cela j'ai utilisé une variable de type tableau pour récupérer tes table de multiplication et vérifier qu'elle ne revient pas

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    Sub Multipli_3()
      Dim i As Byte                 ' Variable d'indice pour passer de 1 à 10
      Dim Tab_Alea As Byte          ' Variable récupérant la Table Aléatoirement
      Dim Rep_cont  As Byte         ' variable pour récupérer la réponse si on continu ou pas
      Dim Cum_Err As Byte           ' Variable de cumul des erreurs
      Dim Cpt_Tab As Byte           ' Variable du nombre de Tables
     
      Dim Tab_Mutipli(1 To 3) As Byte   ' Variable tableau pour récupérer les 3 tables maxi
     
      Dim Result As Integer         ' Variable de récupération du résultat
     
        i = 1
        Cum_Err = 0
        Cpt_Tab = 1
     
        'chargement de la variable tableau
        Do
            Tab_Alea = Int((10 * Rnd) + 1)
            'Chargement premier élément
            If Cpt_Tab = 1 Then
                Tab_Mutipli(1) = Tab_Alea
                Cpt_Tab = Cpt_Tab + 1
            End If
            'Chargement deuxième élément + vérif non présent dans élémént 1
            If Cpt_Tab = 2 Then
                If Tab_Mutipli(1) <> Tab_Alea Then
                    Tab_Mutipli(2) = Tab_Alea
                    Cpt_Tab = Cpt_Tab + 1
                End If
            End If
            'Chargement deuxième élément + vérif non présent dans élémént 1 et 2
            If Cpt_Tab = 3 Then
                If Tab_Mutipli(1) <> Tab_Alea And Tab_Mutipli(2) <> Tab_Alea Then
                    Tab_Mutipli(3) = Tab_Alea
                    Cpt_Tab = Cpt_Tab + 1
                End If
            End If
        Loop While Cpt_Tab < 4
        Cpt_Tab = 1
     
     
        Do While Cpt_Tab <= 3
            For i = 1 To 10
                Result = InputBox("Combien font " & i & " x " & Tab_Mutipli(Cpt_Tab) & " ?", "Table de multliplication")
                If Result = Tab_Mutipli(Cpt_Tab) * i Then
                    MsgBox "Correct"
                Else
                    MsgBox "Faux"
                    Cum_Err = Cum_Err + 1
                End If
            Next
            Cpt_Tab = Cpt_Tab + 1
            Rep_cont = MsgBox("Voulez-vous continuer?", vbYesNo + vbQuestion, "Table de multiplication")
            If Rep_cont = vbNo Then
                Exit Do
            End If
        Loop
        MsgBox ("votre nombre total d'erreurs est de : " & Cum_Err)
    End Sub


    tu nous dit si cela te va
    Ils ne savaient pas que c'était impossible ... du coup ils l'ont fait (Mark Twain)

    n'oubliez pas de si les messages vous aide ou sont pertinents et de mettre quand cela est !

  10. #10
    Responsable
    Office & Excel

    Citation Envoyé par Igloobel Voir le message
    [...]
    Ben Pierre tu as testé ton code ?????[...]
    Oui, j'ai testé mon code, et il est fonctionnel les rares fois où je ne le teste pas, je le précise. Et toi, l'as-tu testé ? Teste-le en pas à pas et tu verras qu'il n'y a aucune Boucle infinie, sauf bien sûr à considérer que X serait tout le temps la même valeur à chaque calcul, ce qui n'a pas beaucoup de chance d'arriver

    A quoi sert y? Ben, teste mon code et tu verras à quoi sert y=> à tester qu'on n'a pas deux fois de suite la même table.

    Oui, j'ai vu le message 4
    Citation Envoyé par Igloobel Voir le message
    [...]
    ta boucle infinie est là
    Tu y relèves un Loop Until dans le code de Mathieu, alors que moi je parle de Loop While. Ce n'est pas la même chose. De plus, comme le fait remarquer unparia, ce n'est pas x = b qu'il faut écrire comme trouvé dans le code initial, mais b = x, comme je l'ai écrit dans le mien. Il y a donc dans mon code bien plus que changer b en y. Mais évidemment, pour se rendre compte de cela, il eu été préférable de le tester ^^

    Citation Envoyé par Matthieu_12 Voir le message
    [...]
    Je n'ai pas réussi à intégrer une autre boucle Do dans ma boucle Do générale afin de vérifier que l'on n'avait pas la même table à jouer deux fois de suite (x&#8800;b)[...]
    La demande initiale est claire, me semble-t-il, et ne dit pas qu'on ne peut pas avoir 2 fois la même table, elle dit qu'on ne peut pas avoir la même table deux fois de suite. Je ne comprends donc pas très bien pourquoi tu utilises un tableau pour voir si une table est sortie ou pas, et pourquoi tu reformules l'énoncé à ta sauce, en déterminant un nombre maxi de tables alors qu'il n'en est pas question dans l'énoncé, pas plus qu'il n'est question de garder les résultats. Mathieu va immanquablement s'y perdre et ce fil, d'une banale simplicité, va encore déborder.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  11. #11
    Membre expert
    MEA CULPA

    MEA MAXIMA CULPA

    Effectivevement c'est pas la même boucle (Ce que j'avais cru à tort. Je me repends, je me repends, je me repends, je me repends, …)

    et le coup du Y ... subtil


    Ne m'en veux pas
    Ils ne savaient pas que c'était impossible ... du coup ils l'ont fait (Mark Twain)

    n'oubliez pas de si les messages vous aide ou sont pertinents et de mettre quand cela est !

  12. #12
    Responsable
    Office & Excel

    Mea culpa aussi, Igloobel, puisque l'énoncé n'est pas clair (voir le message 3, dans lequel l'énoncé en vert ne correspond ni à l'énoncé du #1, ni à l'énoncé du bas du #3... Un peu sérieux svp dans la rédaction de la demande, Mathieu!)

    Pour choisir trois tables différentes, il faudra effectivement un tableau qui mémorisera les tables choisies. Voici un code qui fait cela. Je n'ai pas mémorisé les résultats (ce n'est a priori pas encore demandé, mais cela fait trois boucles, forcément qui s'imbriquent dans une quatrième... On est loin de l'énoncé de départ et du titre de la discussion

    Du coup, mon code s'approche de celui d'Igloobel, la mémorisation des résultats en moins

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Sub Multi()
      Dim i As Integer, x As Integer, y As Integer, z As Integer
      Dim Result As Integer
      Dim Tables(0 To 2)
      Dim Found As Boolean
     
      For y = 0 To 2
        Do
          x = Int((10 * Rnd()) + 1)
          Found = False
          For z = 0 To y
            Found = Found Or x = Tables(z)
          Next
        Loop While Found
        Tables(y) = x
        For i = 1 To 2
          Result = InputBox("Combien font " & i & " x " & x & "? (0 pour stopper)", "Table de multliplication")
          If Result = x * i Then
            MsgBox "Correct"
          Else
            MsgBox "Faux"
          End If
        Next
      Next
    End Sub
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

###raw>template_hook.ano_emploi###