Boucles imbriquées

Bonjour le forum,

Aujourd'hui j'ai tapé un petit code qui est censé me permettre de remplir des cellules ligne par ligne en fonction d'autres valeurs et calculs, le tout avec des boucles imbriquées. L'application est de déterminer la marche d'un système de transport. Accélération, vitesse maximale, position et décélération sont à prendre en compte.

L'idée est la suivante :

  • Dans une première boucle, je demande de décélérer jusqu'à trouver la position à laquelle il arrivera à la prochaine Vmax. Je compare cette position à la position réelle de la prochaine Vmax. Si cette position est inférieure, alors je passe aux étapes suivantes, qui permettent d'affecter une accélération au système en fonction d'autres données.
  • La boucle principale permet de rééditer cette opération jusqu'à ce que la position maximale soit atteinte.

L'idée, c'est de remplir les cellules de chaque ligne en fonction de toutes ces données. Les cellules sont celles initialisées, et les variable b et c correspondent aux numéros de ligne.

Le problème que j'ai c'est que ça ne fonctionne pas, ça ne remplit pas mes cellules, et ça ne passe pas aux lignes suivantes.

Pour couronner le tout, ça remplit une valeur négative sur la deuxième ligne de mon tableau, une valeur qui décroît sans cesse, jusqu'à épuisement de la capacité de calcul.

Qu'est-ce qui pourrait manquer ?

En vous remerciant pour votre attention et pour votre aide je l'espère, je vous souhaite à toutes et à tous un bon jeudi.

Rod'

Voici le code en question :

Option Explicit

Sub Marchetypesensaller_Bouton1_Cliquer()

'Outil et onglets utilisés
Dim OUT As Workbook

Dim VMR As Worksheet
Dim MTA As Worksheet
Dim MTR As Worksheet
Dim ACC As Worksheet

'Toutes les données utiles à la marche-type
Dim Pki As Single 'Pk courant, utilisé également pour les tests
Dim Pko As Single 'Pk à l'instant T
'Dim T As Single 'Variable temporelle
Dim Vo As Single 'Vitesse à l'instant T
Dim Vi As Single 'Vitesse à l'instant T créée pour les tests
Dim a As Single 'Accélération
Dim a1 As Single 'Accélération pallier
Dim amax As Single 'Accélération maximale
Dim Vmax As Single 'Vitesse maximale due à l'infrastructure
Dim VmaxMR As Single 'Vitesse maximale du matériel roulant
Dim V1 As Single 'Vitesse pallier du matériel roulant pour calculer l'accélération
Dim pVmax As Single 'prochaine Vmax infra
Dim PkpVmax As Single 'position de la prochaine Vmax infra
Dim d As Single 'Décélération maximale du matériel roulant
Dim Pkmax As Single

'Pas et cellule variable
Dim k As Single 'Pas de temps
Dim b As Integer 'Cellule
Dim c As Integer 'Cellule suivant

'Initialisation des onglets utilisés
Set OUT = ThisWorkbook
Set VMR = OUT.Worksheets("Validation matériel roulant")
Set MTA = OUT.Worksheets("Marche type sens aller")
Set MTR = OUT.Worksheets("Marche type sens retour")
Set ACC = OUT.Worksheets("ACCUEIL")

Pko = ACC.Cells("16", "G")
Pki = Pko
Pkmax = ACC.Cells("18", "G")

b = 9
c = b + 1
'T = 0

pVmax = MTA.Cells(b, "H")
PkpVmax = MTA.Cells(b, "I")

Vo = MTA.Cells(b, "C")
Vi = Vo
k = MTA.Cells("3", "K")
d = VMR.Cells("7", "B")
amax = VMR.Cells("4", "B")
a = amax
V1 = VMR.Cells("5", "B")
VmaxMR = VMR.Cells("6", "B")
Vmax = MTA.Cells(b, "G")

Do

    Do While Vo > pVmax

'Test prochaine position en fonction de prochaine Vmax en cas de décélération
   Vi = Vo
    Vi = Vi + k * d
    Pki = Pko
    Pki = Pki + k * Vi

    Exit Do

    Loop

   If Pki >= PkpVmax Then 'Si la position courante ne se trouve plus avant la prochaine Vmax, alors enclencher décélération

    Vo = Vo + k * d
    Pko = Pko + k * Vo

   ' Cells(b, "A").Value = T
   Cells(b, "E").Value = d
    Cells(c, "C").Value = Vo
    Cells(c, "D").Value = Vo * 3.6
    Cells(c, "B").Value = Pko

  '  T = T + k

   Else

   If Pki < PkpVmax Then 'Si la positions courante est en amont de la prochaine Vmax, alors accélérer sous conditions

       If Vo = Vmax Then
       a = 0
       Pko = Pko + k * Vo

     '   Cells(b, "A").Value = T
       Cells(b, "E").Value = 0
        Cells(c, "C").Value = Vo
        Cells(c, "D").Value = Vo * 3.6
        Cells(c, "B").Value = Pko

    '    T = T + k

       Else
       If Vo < V1 Then

       a = amax
       Vo = Vo + k * a
       Pko = Pko + k + Vo

    '    Cells(b, "A").Value = T
       Cells(b, "E").Value = a
        Cells(c, "C").Value = Vo
        Cells(c, "D").Value = Vo * 3.6
        Cells(c, "B").Value = Pko

'   T = T + k

        Else
        If Vo < VmaxMR Then
        a = (amax / (VmaxMR - Vo)) * (VmaxMR - Vi)
        Vo = Vo + k * a
        Pko = Pko + k * Vo

    '    Cells(b, "A").Value = T
       Cells(b, "E").Value = a
        Cells(c, "C").Value = Vo
        Cells(c, "D").Value = Vo * 3.6
        Cells(c, "B").Value = Pko

  ' T = T + k

        End If
        End If
        End If
        End If
        End If

   Loop While Pko < Pkmax

End Sub
 

Bonjour,

à aucun moment les valeurs de "b" et "c" ne sont incrémentées...

Donc à chaque boucles se sont toujours les mêmes cellules qui sont modifiées...

A la fin de la boucle, avant le LOOP il faut faire (je pense) un :

b=c

c=b+1

@ bientôt

LouReeD

Bonjour !

Hum, effectivement ça marche mieux...en tous cas ça passe d'une ligne à l'autre.

En revanche, lorsque mon programme arrive à la ligne 38, il y a un message d'erreur disant "dépassement de capacité"...comment y remédier ?

Merci pour ton aide.

Rod'

Re

en fait vous mettez :

Dim b As Integer 'Cellule
Dim c As Integer 'Cellule suivant

Integer = valeur max positive (numéro de lignes de feuille excel) 32000 !

Ce qui veut dire qu'à un moment le c=b+1 dépasse les 32000 !

Hors vous me dites que c'est à partir de la ligne 38 que l'erreur apparaît... Donc j'en déduis qu'à partir de la ligne 38 le code n'inscrit plus de valeur mais que la boucle continue de tourner... donc c'est votre condition de sortie de boucle qui ne fonctionne pas...

N'ayant pas la "vue" sur le code, je ne peux vous en dire plus.

Ce que vous pouvez faire c'est de dérouler le code en mode "pas à pas"

Sous VBA vous placez le curseur de saisie de code au niveau du SUB...

puis avec la touche [F8] vous le dérouler ligne par ligne, ensuite lors du déroulement, à tout moment vous pouvez placer le curseur de la souris sur les variables, et les valeurs de celles-ci s'affichent dans une info bulle, comme cela après 38 tour de boucle vous comprendrez pourquoi la condition de sortie ne fonctionne pas.

@ bientôt

LouReeD

Re,

Merci pour la réponse !

Oui je vois ! Si je mets un "Double" à la place de "Integer", est-ce que ça peut mieux fonctionner ?

En fait, je remarque que le code s'arrête dès lors que la condition Vo >= Vmax est vérifiée, et c'est là que tout s'arrête. Je me dis alors que ça peut tout-à-fait venir de là, mais je ne vois pas dans quelle mesure, le code me paraît pourtant cohérent...à moins que ça ne le bloque dans la boucle Vo > pVmax ? Peut-être...

Au passage, j'ai aussi la condition "If Vo < VmaxMR" qui est un "Else" de "If Vo < V1", or même quand Vo > V1, il continue à effectuer les actions dans ce if et pas dans les autres...c'est étrange !

J'aimerais beaucoup pouvoir joindre un fichier, mais celui-ci prend quand même 20 Mo, et il paraît insécable car tous les onglets sont en relations les uns des autres. :/

Encore merci pour votre écoute ! Et pour votre aide !

Rod'

Rebonjour, et bonjour le forum,

J'ai modifié mon code pour avoir quelque chose qui fera, j'en suis quasi-sûr, exactement ce que je souhaite.

Mais voilà, toujours pareil : au bout de la 23e ligne, il fait planter Excel, fini au revoir. Je n'arrive vraiment pas à comprendre pourquoi.

Sub Bouton2_Cliquer()

'Outil et onglets utilisés
Dim OUT As Workbook

Dim VMR As Worksheet
Dim MTA As Worksheet
Dim MTR As Worksheet
Dim ACC As Worksheet
Dim AVM As Worksheet

'Toutes les données utiles à la marche-type

Dim Pk As Single 'Pk à l'instant T
Dim Pkt As Single 'Pk test
Dim Pkw As Single 'Pk test 2
Dim Pkmax As Single

'Dim T As String 'Variable temporelle
Dim V As Single 'Vitesse à l'instant T
Dim Vi As Single 'Vitesse à l'instant T créée pour les tests
Dim Vmax As Single 'Vitesse maximale due à l'infrastructure
'Dim VmaxMR As Single 'Vitesse maximale du matériel roulant
Dim V1 As Single 'Vitesse pallier du matériel roulant pour calculer l'accélération
Dim Vt As Single 'Vitesse test
Dim Vw As Single 'Vitesse test 2

Dim a As Single 'Accélération
Dim a1 As Single 'Accélération pallier
Dim amax As Single 'Accélération maximale
Dim dmax As Single 'Décélération maximale du matériel roulant

'Pas et cellule variable
Dim k As Single 'Pas de temps
Dim b As Integer 'Cellule
Dim c As Integer 'Cellule suivant

Dim i As Integer
Dim j As Integer
Dim m As Integer
Dim n As Integer

'Initialisation des onglets utilisés
Set OUT = ThisWorkbook
Set VMR = OUT.Worksheets("Validation matériel roulant")
Set MTA = OUT.Worksheets("Marche type sens aller")
Set MTR = OUT.Worksheets("Marche type sens retour")
Set ACC = OUT.Worksheets("ACCUEIL")
Set AVM = OUT.Worksheets("Aperçu Vmax")

k = MTA.Cells("3", "K").Value
Pk = ACC.Cells("16", "G").Value
Pkmax = ACC.Cells("18", "G").Value

amax = VMR.Cells("4", "B").Value
'VmaxMR = VMR.Cells("6", "B").Value
dmax = VMR.Cells("7", "B").Value

Pkw = Pk

V = 0
Vw = V
V1 = VMR.Cells("5", "B").Value

j = 5
i = 6
m = 9
n = 10
MTA.Cells(m, "C") = V
MTA.Cells(m, "B") = Pk

Do Until Pk >= Pkmax

Do While AVM.Cells(i, "H").Value <= Pk

    i = i + 1
    j = j + 1

Loop

Vmax = AVM.Cells(j, "I").Value / 3.6
Pkt = AVM.Cells(i, "H").Value
Vt = AVM.Cells(i, "I").Value / 3.6

Do Until Round(V, 0) <= Vt

Vw = Vw + k * d
Pkw = Pkw + k * Vw

Loop

If Pkw >= Pkt Then
a = dmax
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

Else
If V = Vmax Then
a = 0
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

Else
If V < V1 Then
a = amax
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

Else
a = (amax / (Vmax - V1)) * (Vmax - V)
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

End If
End If
End If

m = m + 1
n = n + 1

Loop

End Sub

Re,

tout ce qui touche les lignes sous excel doit être (au cas ou) en Long

Dim b as Long, etc...

@ bientôt

LouReeD

Re,

Hum, toujours pareil, dès lors qu'il passe au calcul de la ligne 25 il s'arrête et je suis obligé de redémarrer Excel. :/

Ca a peut-être un lien avec l'une de mes deux boucles :

  • Sur un autre onglet Excel (l'onglet AVM), il y a deux colonnes : une avec des positions (Pk), et une autre avec des Vmax. Il va chercher le prochain Pk affecté à une Vmax supérieur au Pk de cet instant.
  • Dans l'autre boule, il prend cette Vmax, et teste une décélération jusqu'à celle-ci. On récupère le Pk correspondant, et on compare au Pk réel de la prochaine Vmax.
  • Selon que ce Pk soit inférieur ou non, on accélère et on décélère. On calcule les vitesses, les Pk, et on reboucle tant que le Pkmax n'est pas atteint.

A priori mon code semble cohérent avec ce que je veux faire...c'est frustrant !


10exemple.xlsm (647.90 Ko)

Voici un fichier avec je pense tout ce qu'il faut pour les calculs.

après un test il arrive en "boucle infinie" ce qui fait qu'Excel ne répond plus !

Du coup on arrête tout !

Mais j'ai du mal à suivre le code indenté comme il est...

Alors j'avoue sécher...

@ bientôt

LouReeD

Bonjour !

J'espère que le week-end a été bon !

J'ai finalement trouvé la solution à mon problème ! En effet j'avais une boucle infinie qui n'était pas belle ! :p

Voici la solution :

Sub FreqOK()
'
' FreqOK Macro
'

'
    ActiveSheet.Calculate
End Sub
Sub AperçuVmax_Bouton6_Cliquer()

Dim TW As Workbook
Dim TS As Worksheet
Dim ACC As Worksheet

Dim i As Integer
Dim p As Integer
Dim q As Integer
Dim Pkmax As Double

Set TW = ThisWorkbook
Set TS = TW.Worksheets("Aperçu Vmax")
Set ACC = TW.Worksheets("ACCUEIL")
Pkmax = ACC.Range("G18").Value

p = 5
q = 6
i = 6

Do Until Cells(i, "B") >= Pkmax

    If Cells(q, "F") = Cells(p, "F") Then

    Else

    Cells(i, "H").Value = Cells(q, "B").Value
    Cells(i, "I").Value = Cells(q, "F").Value

    i = i + 1

    End If

    q = q + 1
    p = p + 1

Loop

End Sub
Sub Bouton2_Cliquer()

'Outil et onglets utilisés
Dim OUT As Workbook

Dim VMR As Worksheet
Dim MTA As Worksheet
Dim MTR As Worksheet
Dim ACC As Worksheet
Dim AVM As Worksheet

'Toutes les données utiles à la marche-type

Dim Pk As Single 'Pk à l'instant T
Dim Pkt As Single 'Pk test
Dim Pkw As Single 'Pk test 2
Dim Pkmax As Single

'Dim T As String 'Variable temporelle
Dim V As Single 'Vitesse à l'instant T
Dim Vi As Single 'Vitesse à l'instant T créée pour les tests
Dim Vmax As Single 'Vitesse maximale due à l'infrastructure
'Dim VmaxMR As Single 'Vitesse maximale du matériel roulant
Dim V1 As Single 'Vitesse pallier du matériel roulant pour calculer l'accélération
Dim Vt As Single 'Vitesse test
Dim Vw As Single 'Vitesse test 2

Dim a As Single 'Accélération
Dim a1 As Single 'Accélération pallier
Dim amax As Single 'Accélération maximale
Dim dmax As Single 'Décélération maximale du matériel roulant

'Pas et cellule variable
Dim k As Single 'Pas de temps
Dim b As Long 'Cellule
Dim c As Long 'Cellule suivant

Dim i As Long
Dim j As Long
Dim m As Long
Dim n As Long

'Initialisation des onglets utilisés
Set OUT = ThisWorkbook
Set VMR = OUT.Worksheets("Validation matériel roulant")
Set MTA = OUT.Worksheets("Marche type sens aller")
Set MTR = OUT.Worksheets("Marche type sens retour")
Set ACC = OUT.Worksheets("ACCUEIL")
Set AVM = OUT.Worksheets("Aperçu Vmax")

k = MTA.Cells("3", "K").Value
Pk = ACC.Cells("16", "G").Value
Pkmax = ACC.Cells("18", "G").Value

amax = VMR.Cells("4", "B").Value
'VmaxMR = VMR.Cells("6", "B").Value
dmax = VMR.Cells("7", "B").Value

Pkw = Pk

V = 0
Vw = V
V1 = VMR.Cells("5", "B").Value

j = 5
i = 6
m = 9
n = 10
MTA.Cells(m, "C") = V
MTA.Cells(m, "B") = Pk

Do Until Pk >= Pkmax

Do While AVM.Cells(i, "H").Value <= Pk

    i = i + 1
    j = j + 1

Loop

Vmax = AVM.Cells(j, "I").Value / 3.6
Pkt = AVM.Cells(i, "H").Value
Vt = AVM.Cells(i, "I").Value / 3.6

Do Until Vw <= Vt

Pkw = Pkw + k * Vw
Vw = Vw + k * dmax

Loop

If Pkw >= Pkt Then

Do Until V <= Vt

a = dmax
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk
m = m + 1
n = n + 1

Loop

Else
If V >= Vmax Then
a = 0
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
If V = 0 Then
MTA.Cells(n, "C").Value = 0
Else
MTA.Cells(n, "C").Value = V
End If
MTA.Cells(n, "B").Value = Pk

Else

'If V = Vt Then
'a = 0
'V = V + k * a
'Pk = Pk + k * V
'MTA.Cells(m, "E").Value = a
'MTA.Cells(n, "C").Value = V
'MTA.Cells(n, "B").Value = Pk

'Else
If V < V1 Then
a = amax
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

Else
a = (amax / (Vmax - V1)) * (Vmax - V)
V = V + k * a
Pk = Pk + k * V
MTA.Cells(m, "E").Value = a
MTA.Cells(n, "C").Value = V
MTA.Cells(n, "B").Value = Pk

End If
End If
End If
'End If

Pkw = Pk
Vw = V

m = m + 1
n = n + 1

Loop

End Sub

J'ai juste un dernier petit point : comment effectuer une instruction uniquement lorsqu'on va sortir de la boucle ? C'est le dernier petit point dont j'ai besoin.

Bonjour,

en l'inscrivant après le "LOOP"

En fait quand vous sortez de la boucle, le code reprend à la suite de celle-ci, c'est à dire après le Loop et avant le End Sub.

@ bientôt

LouReeD

Bonjour,

Ouep c'est évident en plus quand on y pense !

Bref, merci beaucoup pour cette aide précieuse !

Bonne journée, peut-être à plus tard !

Rod'

Rechercher des sujets similaires à "boucles imbriquees"