Simplifier l'imbrication de boucles While

[Résolu]
Signaler
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007
-
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007
-
Hello everybody!

J'espere que vous allez bien et que vos meninges aussi !

Mon petit soucis est que lorsque je compile mon code, cela met 5minutes avant de s'afficher!
Mon chef n'est pas content, il veut que je descend sous la barre de la minute!
J'ai amélioré plusieur parties de mon code, mais la ou ca rame le plus, c'est les imbrications de boucles while.
Voici le bout de mon code que j'aimerais améliorer:

t = 2
lm = 1
While Worksheet(1).Cells(2, t) <> ""
x = 4
    While Worksheet(1).Cells(x, 1) <> ""
    s = 161
        While ((Worksheet(2).Cells(s, 1) <> "") And (lm = 1))               If ((CDate(Worksheet(2).Cells(s, 1)) CDate(Worksheet(1).Cells(2, t))) And (Worksheet(2).Cells(s, 2) "SC") And (Worksheet(2).Cells(s, 3) = Worksheet(1).Cells(x, 1))) Then
...
' je remplit le tableau qui se trouve dans la feuille Worksheet(1)
...
               end if
        s = s + 1
        Wend
    lm = 1
    x = x + 1
    Wend
t = t + 1
Wend

Explication de ce qui est fait:
J'ai une feuille Worksheet(2) dans laquelle j'ai des données (parcouru avec la variable s).
Une autre feuille Worksheet(1) contient un tableau avec les numero code (parcourru grace à x)  en verticale ( a la premiere colonne) et les dates de la periode d'etudes (parcouru par t) en horizontale ( ligne 2).
Pour chaque date de la periode d'etudes, pour chaque numero de code, on compare aux données qui se trouve sur la feuille Worksheet(2), et si ca correspond, on execute le code.

Le code est bon, il n'y a aucune faute.
Par contre, il n'est pas optimal, ca donne les bon resultats certes mais il faut attendre trop trop longtemps!
Dans la feuille Worksheet(2) il y a enormement de données ( plus de 1000), on a egalement beaucoup de numero de code ( plus de 20) et une periode d'etudes qui peut allé à plus de 100 dates.

J'aimerais savoir si il est possible de remplacer les boucles while, de maniere à obtenir une compilation plus rapide.

Si vous avez des éléments de réponses, ca serai cool!!!

Merci beaucoup à tous ceux qui se pencheront sur mon probleme ( et a tous ceux qui ont lu jusqu'ici!  )

Monaldinho.

 faites comme moi, éssayer d'éviter le coté obscur de la force

7 réponses

Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Modérateur
Dernière intervention
4 mars 2013
125
Déjà, une petite optimisation : faire les tests du plus rapide au plus lent, et non le contraire comme tu fais :If ((Worksheet(2).Cells(s, 2) "SC") And (Worksheet(2).Cells(s, 3)
Worksheet(1).Cells(x, 1)) And (CDate(Worksheet(2).Cells(s, 1)) = CDate(Worksheet(1).Cells(2, t))) ) Then

Rien qu'avec cà tu va y gagner quelques secondes !

Ensuite, tu fais :
While ((Worksheet(2).Cells(s, 1) <> "") And (lm = 1))
While Worksheet(1).Cells(x, 1) <> ""

Ca oblige VB à tester à chaque tour de boucle ! Il vaut mieux faire une première boucle qui va lire quelle est la case <> "" puis faire un simple test ! Exemple :

Dim nombreCellules As Integer
While Worksheet(1).Cells(x, 1) <> ""
    nombreCellules = nombreCellules + 1
Wend

Puis :
While x < nombreCellules

Ca te fera gagner quelques secondes voir quelques minutes là aussi !

Autre chose : tu parcoure tout tes éléments une multitude de fois en les lisant à chaque fois dans ton tableau ! Ca prend beaucoup de temps pour accèder à la données !

Il vaut mieux lire une fois pour toutes les données et les stocker dans un tableau : ca te fera gagner plusieurs minutes !
Messages postés
918
Date d'inscription
vendredi 3 août 2007
Statut
Membre
Dernière intervention
27 octobre 2008
10
Autre petit point.
Dans ta boucle la plus interne (sur la variable s), tu fait des appels à des cellules dont les coordonnées dépendent de x et t.
Sur toute une boucle pour s, x et t (qui sont ds les boucles exterieures) ne varient pas. Tu pourrait donc stocker les valeurs qui en dépendent dna sdes variables. Et comme tu fait un CDate dessus sur l'une, stocke cela dans une var de type Date.

Dim DateT As Date, ValX As String

t = 2
lm = 1
While Worksheet(1).Cells(2, t) <> ""
x = 4
While Worksheet(1).Cells(x, 1) <> ""
s = 161
DateT = CDate(Worksheet(1).Cells(2, t))
ValX = Worksheet(1).Cells(x, 1)
While ((Worksheet(2).Cells(s, 1) <> "") And (lm = 1))
If ((CDate(Worksheet(2).Cells(s, 1)) DateT) And (Worksheet(2).Cells(s, 2) "SC") And (Worksheet(2).Cells(s, 3) = Valx)) Then
...
' je remplit le tableau qui se trouve dans la feuille Worksheet(1)
...
end if
s = s + 1
Wend
lm = 1
x = x + 1
Wend
t = t + 1
Wend

Cela va aaccéléré substanciellement le code et en plus c'est plus lisible.
Je ne sais pas ce qu'il y a dans les cellules variant sur X alors j'ai mis une string pour ValX, mais si c'est un type autre, utilise le meilleur.
Messages postés
201
Date d'inscription
mardi 7 octobre 2003
Statut
Membre
Dernière intervention
10 mai 2016

tu peux faire aussi la méthode tout_en_memoire ... :-))

qqs indices :

1 - ta dernière ligne utilisée dans une feuille avec usedrange
2 - tu colles tout ça dans 2 variant (tes deux feuilles): matab = cells.value(=tableau a 2 dimensions)
3 - tu fais tes calculs à partir de ces tableaux...

4 - tu colles du
application.enablevent = false
Application.ScreenUpdating = False

afin d'optimiser encore un peu avant "je remplit le tableau ... "

n'oublie pas les true après ...
ça devrait prendre 1 ou 2 secondes tout ça ....
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007

hello !


merci a vous trois pour vos reponses!!!


j'ai appris plein de trucs pratique pour accelerer ma compilation!


je ne savais pas que passer par des variables pouvais me faire gagner du temps (cf : 1121413 Kristof_Koder ) , ou encore dans la boucle if  qu'il fallait mettre les tests du plus rapide au plus lent (cf:  DARKSIDIOUS ). 

j'ai mis cette instruction au tout debut de mon code:
Application.ScreenUpdating = False
( et le true, a la fin du code). mais ca ne change rien à la vitesse de compilation...
j'ai fait le tst... le temps est le meme!

par contre je ne conaissais pas cela:
application.enablevent = false
donc vais le tester des maintenant !

Je test tout cela des demain matin et je vous tiens au courant!
encore merci beaucoup!!!!

Monaldinho

 faites comme moi, éssayer d'éviter le coté obscur de la force
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007

hello!

avec les conseils de darksidius et de etnik, j'ai gagné 30secondes.


maintenant je vais metre des variables partout ( conseil de kristof_koder).


On m'a parlé de la methode FIND, en me disant qu'elle pouvait remplacer mes trois boucles while et rendre mon code beaucoup plus rapide!


je me suis renseigné sur comment elle fonctionne et je ne voit pas du tout comment l'utiliser dans mon cas. je verrais ca apres les variables!

merci encore à vous!


Monaldinho.

 faites comme moi, éssayer d'éviter le coté obscur de la force
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007

hello !


J'ai mis en variable tout ce que je pouvais... j'ai gagné 1minute!!!
Maintenant il ne me reste plus qu'à remplacer ces trois boucles while imbriqués!
J'ai besoin d'un serieux coup de main la.
Il faut absolument que je fasse intervenir la fonction FIND.
Si quelqu'un a déjà utiliser cette fonction et la maitrise, ca serait cool qu'il m'aide!

merci d'avance!

Monaldinho.

 faites comme moi, éssayer d'éviter le coté obscur de la force
Messages postés
74
Date d'inscription
jeudi 24 mai 2007
Statut
Membre
Dernière intervention
25 octobre 2007

yo !

j'ai réussi à amelioré un bout de mon code grace a la fonction FIND ( cf : voir le sujet "Probleme avec la fonction FIND" ) et j'ai gagné encore 30secondes!

il ne me reste plus que 2minutes à perdre...

merci a vous!
 
Monaldinho.

 faites comme moi, éssayer d'éviter le coté obscur de la force