Se connecter avec
S'enregistrer | Connectez-vous

Simplification et systémisation fonction VBA

Dernière réponse : dans Programmation

Bonjour,
j'ai un petit problème de programmation avec VBA (pour Arena). Il s'agit d'une
fonction testant les possibilités de mettre des outils dans un buffer en temps
masqué (pour un magasin d'outil de machine).
Le but est de remplir un tableau nommé Buffer_use() avec des 0 et des 1, sachant
que les 1 correspondent à la possibilité de réaliser le placement en temps
masqué. Pour cela, j'ai créer une fonction qui compare le temps de déplacement
du bras pour mettre les outils dans le buffer avec le temps de coupe de
l'opération actuelle. Ces données sont respectivement dans des tableaux nommés
Temps_Deplac() et Temps_Op(). n_tools est le nombre d'opération dans la gamme.

La fonction que j'ai réalisé fonctionne pour un buffer ayant 4 positions (elle
peut donc placer jusqu'à 4 outils dans le buffer a la suite).
Néanmoins, le nombre de positions du buffer est variable. Pouvez-vous m'aider à
transformer cette fonction pour que cela soit prit en compte ? ( J'ai pensé à
faire une fonction récursive mais je ne m'en sors pas).

Voici la fonction telle qu'elle est actuellement :

  1. buffer_v = 0
  2. counter = 1
  3. Do Until counter = n_tools
  4. If counter + 1 <= n_tools Then
  5. If Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  6. Buffer_Use(counter + 1) = 1
  7. buffer_v = 1
  8. If counter + 2 <= n_tools Then
  9. If Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) <
  10. Temps_Op(counter) Then
  11. Buffer_Use(counter + 2) = 1
  12. buffer_v = 2
  13. If counter + 3 <= n_tools Then
  14. If Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2)
  15. + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  16. Buffer_Use(counter + 3) = 1
  17. buffer_v = 3
  18. If counter + 4 <= n_tools Then
  19. If Temps_Deplac(counter + 4) +
  20. Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter +
  21. 1) < Temps_Op(counter) Then
  22. Buffer_Use(counter + 4) = 1
  23. buffer_v = 4
  24. End If
  25. End If
  26. End If
  27. End If
  28. End If
  29. End If
  30. End If
  31. End If
  32. counter = counter + buffer_v + 1
  33. buffer_v = 0
  34. If counter >= n_tools Then GoTo Nextstep
  35.  
  36. Loop
  37. Nextstep:


Merci d'avance.
Schnapz.
Lassé par la pub ? Créez un compte

Meilleure solution

Expert Programmation

Citation :
Après est-ce que l'ensemble fait quelque chose de logique ... Ca c'est mon problème.
On est bien d'accord :o  ;) 

Euh..... à te lire tout à l'heure, je pensais que ce n'était pas du tout résolu. L'est-ce ?
(Si oui, clique sur le bouton "Élire meilleure réponse" de la moins mauvaise réponse ;)  )

Sinon, s'il ne te manque que la borne 4, tu devrais t'en sortir tout seul ;) 
Pour l'arrêt dès qu'on a dépassé, aussi. Mais je te donne une bonne (on peut toujours faire mieux) façon de faire :
  1. Dim tdc As Integer ' // Temps_Deplac_Cumulé
  2. Dim position As Integer
  3. Dim i As Integer
  4.  
  5. buffer_v = 0
  6. counter = 1
  7. Do Until counter > n_tools
  8. For position = 1 To 4 ' // A toi de voir
  9. If counter + position > n_tools Then Exit For
  10. tdc = 0
  11. For i = 0 To position - 1
  12. tdc = tdc + Temps_Deplac(counter + i)
  13. Next
  14. If counter + position <= n_tools And tdc < Temps_Op(counter) Then
  15. Buffer_Use(counter + position) = 1
  16. buffer_v = position
  17. End If
  18. Next
  19.  
  20. counter = counter + buffer_v + 1
  21. buffer_v = 0
  22. If counter >= n_tools Then Exit Do
  23. Loop


Je n'ai fais qu'ajouter la ligne 9. On sort de la boucle et on se retrouve donc à la ligne 20.

---------------------------

Observe toutefois la ligne 7, j'ai mis une inégalité. NE JAMAIS METTRE D'EGALITE.
Ben pourquoi ? Imagine pour une raison ou une autre, que ton code, dans un cas extrême ou par effet de bord, fasse déborder (tiens, c'est la même racine que effet de bord, justement) ta borne..... Hop, boucle infinie, bug, etc.

Les programmeurs en C l'ont bien compris :
  1. for (i=1; i<=4; i++)
La condition est toujours une inégalité.

http://xxxxxxxxxxxxxxxxxxxx pour une meilleure visualisation du code.


______________________________
Modérateur : NON !
Pour une meilleure visualisation du code, merci de lire le règlement et de l'appliquer.

:jap: 
Expert Programmation

Une fonction récursive est effectivement une bonne idée sur le principe. Mais je ne connais pas VBA, au point où je ne sais même pas si ce langage accepte les fonctions récursives...
Expert Programmation

Je regarde un peu ton code et je me fais les réflexions suivantes.
Il faut virer le GoTo, c'est comme ça. C'est non négociable.
Ensuite, deux If qui se suivent, c'est une clause de trop.
Enfin, une boucle Until avec deux bornes connues, ça me paraît louche. (à voir)

Ça donne :
  1. buffer_v = 0
  2. counter = 1
  3. Do Until counter = n_tools
  4. If counter + 1 <= n_tools And Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  5. Buffer_Use(counter + 1) = 1
  6. buffer_v = 1
  7. If counter + 2 <= n_tools And Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  8. Buffer_Use(counter + 2) = 1
  9. buffer_v = 2
  10. If counter + 3 <= n_tools And Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  11. Buffer_Use(counter + 3) = 1
  12. buffer_v = 3
  13. If counter + 4 <= n_tools And Temps_Deplac(counter + 4) + Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  14. Buffer_Use(counter + 4) = 1
  15. buffer_v = 4
  16. End If
  17. End If
  18. End If
  19. End If
  20. counter = counter + buffer_v + 1
  21. buffer_v = 0
  22. If counter >= n_tools Then Exit Do
  23. Loop


Comme je préfère y voir mieux, je sors les tests imbriqués. Ça manquera d'efficacité, mais ce sera plus visible :
  1. buffer_v = 0
  2. counter = 1
  3. Do Until counter = n_tools
  4. If counter + 1 <= n_tools And Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  5. Buffer_Use(counter + 1) = 1
  6. buffer_v = 1
  7. End If
  8. If counter + 2 <= n_tools And Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  9. Buffer_Use(counter + 2) = 1
  10. buffer_v = 2
  11. End If
  12. If counter + 3 <= n_tools And Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  13. Buffer_Use(counter + 3) = 1
  14. buffer_v = 3
  15. End If
  16. If counter + 4 <= n_tools And Temps_Deplac(counter + 4) + Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
  17. Buffer_Use(counter + 4) = 1
  18. buffer_v = 4
  19. End If
  20. counter = counter + buffer_v + 1
  21. buffer_v = 0
  22. If counter >= n_tools Then Exit Do
  23. Loop

Bon, du premier coup d'oeil, j'ai envie de mettre une boucle pour cumuler les Temps_Deplac. COmme les quatre blocs se reseemblent, je les assemble ( :fille:  ). Ça donne :
  1. Dim tdc As Integer ' // Temps_Deplac_Cumulé
  2.  
  3. Dim position As Integer
  4. Dim i As Integer
  5.  
  6. buffer_v = 0
  7. counter = 1
  8. Do Until counter = n_tools
  9. For position = 1 To 4
  10. tdc = 0
  11. For i = 0 To position - 1
  12. tdc = tdc + Temps_Deplac(counter + i)
  13. Next
  14. If counter + position <= n_tools And tdc < Temps_Op(counter) Then
  15. Buffer_Use(counter + position) = 1
  16. buffer_v = position
  17. End If
  18. Next
  19.  
  20. counter = counter + buffer_v + 1
  21. buffer_v = 0
  22. If counter >= n_tools Then Exit Do
  23. Loop


Qu'en penses-tu ?
Te poses-tu toujours la question des 4 positions ?

Merci pour cette réponse très constructive :) 
Je viens de tester avec ton code. Cela marche jusqu'à ce que Temps_Deplac(counter + i) sorte du tableau. Il faut donc que je rajoute une condition pour pas que counter+i dépasse n_tools (et non pas seulement n_tools).
Sinon j'ai l'impression que ton code fais la somme de 4 cases automatiquement puis compare si le temps est inférieur. Or le but serait de comparer le premier élément, puis le premier + le deuxième, puis on rajoute le troisième, etc jusqu'à ce que la somme soit supérieure.
Est-ce ce qui est réalisé ? Car je ne sais pas trop l'effet du Next en ligne 13.
Expert Programmation

Oui, il faut sans doute vérifier les bornes mieux que je ne le faisais.
M'enfin, il y a deux boucles For imbriquées. Donc la première itère de 1 à 4, l'autre dépend de la première. Regarde bien les lignes 11 à 13.

En fait, je dois ne pas bien comprendre la problématique. Je me fie trop à ton code.

Essaie d'expliquer un peu mieux ton problème, sans te (nous) perdre avec trop de détails.
Mieux, c'est-à-dire au sens "mathématique".

Alors le problème vu simplement :
Parcourir un tableau (Temps_Deplac) dans l'ordre en additionnant les valeurs des cases jusqu'à ce que la somme soit le plus proche mais toujours inférieure à une case d'un autre tableau (Temps_op). Lorsque que l'on atteint cette limite, on repars dans chaque tableau à la case suivante de la dernière utilisée. En même temps on remplit un autre tableau (Buffer_Use) avec des 1 pour chaque élément du tableau Temps_Deplac qui a été utilisé dans la somme.


En rajoutant la condition pour éviter de sortir du tableau, et en ayant remplacé le 4 par une variable d'entrée, il me semble que ça marche :)  :sol: 
Après est-ce que l'ensemble fait quelque chose de logique ... Ca c'est mon problème.

Merci zeb tu m'as bien aidé sur ce coup-là. Mais peut-être que j'aurai d'autres problèmes sous peu donc je dis pas au revoir si vite ;) 

Mon programme a l'air stable avec cette solution, je la conserve donc jusqu'à nouvel ordre. Le problème est résolu puisque je sais comment faire en sorte de changer le 4. Il me fallait surtout savoir comment assembler les conditions comme tu l'as fait. Merci beaucoup ! J'ai même corrigé les histoires d'inégalités ;) 

Lassé par la pub ? Créez un compte