IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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 :

Boucles imbriquées et temps d'exécution


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Amateur
    Inscrit en
    Août 2007
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Août 2007
    Messages : 50
    Par défaut Boucles imbriquées et temps d'exécution
    Bonjour à tous,

    Je reviens à la charge.

    Le temps d'exécution pour ces boucles imbriquées est de 46 secondes pour 5 000 lignes.

    Une idée de code pour améliorer cette vitesse ?

    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
    60
    Sub Exemple()
     
    t = Timer
     
    Dim tableau0
    Dim tableau1
    Dim tableau2(1 To 200, 1 To 100)
    Dim derniereLigne As Integer
    Dim I As Integer
     
     
    With Sheets("Exercice")
     
    derniereLigne = .Cells(Rows.Count, 1).End(xlUp).Row
     
    tableau0 = .Range("A1:B" & derniereLigne).Value
     
    tableau1 = tableau0
     
    ReDim Preserve tableau1(1 To UBound(tableau0), 1 To 202)
     
    For K = 2 To 200
    For j = K - 1 To UBound(tableau1)
    Somme = 0
    For I = j + 2 - K To j
    Somme = Somme + tableau1(I, 1)
    tableau1(j, K + 2) = Somme / K
    Next
    Next
    Next
     
    For K = 1 To 200
    For L = 1 To 100
     
    For I = 2 To UBound(tableau1)
    For j = K To K
    If tableau1(I, j + 2) > tableau1(I - 1, j + 2) And tableau1(I, 2) > L Then
    tableau1(I, 3) = 1
    End If
    a = 0
    If tableau1(I, 3) = 1 Then
    a = a + tableau1(I, 3)
    End If
    Next
    Next
     
    tableau2(K, L) = a
     
     
    Next
    Next
     
     
    .Range("S1").Resize(UBound(tableau2, 1), UBound(tableau2, 2)).Value = tableau2
     
    End With
     
    MsgBox Timer - t
     
    End Sub

  2. #2
    Membre Expert Avatar de curt
    Homme Profil pro
    Ingénieur Etudes
    Inscrit en
    Mars 2006
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Etudes
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 579
    Par défaut
    Bonsoir Fabrice7627,

    sur la deuxième ligne ajoute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    application.screenupdating = false
    et sur avant-dernière le Msgbox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    application.screenupdating = true
    En recherchant dans la FAQ Excel, tu y trouveras toutes les infos pour améliorer les temps d'exécution des macros

  3. #3
    Membre averti
    Homme Profil pro
    Amateur
    Inscrit en
    Août 2007
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Août 2007
    Messages : 50
    Par défaut
    Non curt, ni le "Application.ScreenUpdating", ni le "Application.Calculation" n'apportent de gain de temps.

  4. #4
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 437
    Par défaut
    Bonjour,

    Je n'ai pas compris (et pas vraiment essayé) ce que cela veut faire , mais il me semble que ceci pourrait un peu réduire le temps de calcul:
    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
    Option Explicit
     
    Sub Exemple()
        Dim t As Date
        t = Timer
        Dim tableau0
        Dim tableau1
        Dim tableau2(1 To 200, 1 To 100)
        Dim derniereLigne As Long               '--- Long
        Dim Somme As Single
        Dim i As Long, j As Long, k As Long, ub1 As Long, a As Long
        With Sheets("Exercice")
            derniereLigne = .Cells(Rows.Count, 1).End(xlUp).Row
            tableau0 = .Range("A1:B" & derniereLigne).Value
            tableau1 = tableau0
            ub1 = UBound(tableau1)
            ReDim Preserve tableau1(1 To UBound(tableau0), 1 To 202)
            For k = 2 To 200
                For j = k - 1 To ub1
                    Somme = 0
                    For i = j + 2 - k To j
                        Somme = Somme + tableau1(i, 1)
                        tableau1(j, k + 2) = Somme / k
                    Next
                Next
            Next
            For k = 1 To 200
                For j = 1 To 100
                    For i = 2 To ub1
                        If tableau1(i, 2) > j Then
                            If tableau1(i, k + 2) > tableau1(i - 1, k + 2) Then
                                tableau1(i, 3) = 1
                            End If
                        End If
                        If tableau1(i, 3) = 1 Then
                            a = 1
                        Else
                            a = 0
                        End If
                    Next
                    tableau2(k, j) = a
                Next
            Next
            .Range("S1").Resize(UBound(tableau2, 1), UBound(tableau2, 2)).Value = tableau2
        End With
        MsgBox Timer - t
    End Sub
    Cordialement.

  5. #5
    Membre averti
    Homme Profil pro
    Amateur
    Inscrit en
    Août 2007
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Août 2007
    Messages : 50
    Par défaut
    Bonjour EricDgn,

    Merci pour votre proposition.

    Le temps d'exécution est de 20 secondes. Beau gain.

    Il est 5h00 du matin, je regarde plus en détail votre code demain après-midi et je vous recontacte.

    Cordialement.

  6. #6
    Membre averti
    Homme Profil pro
    Amateur
    Inscrit en
    Août 2007
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Août 2007
    Messages : 50
    Par défaut
    Bonjour EricDgn,

    Vous avez supprimé une boucle, à juste titre, ce qui me fait gagner 10 secondes.

    Vous avez modifié ma définition de "a", qui se voulait une addition de colonne ; soit. Cela fait gagner 4 secondes.

    Étonnamment, pour moi, la déclaration de toutes les variables semble faire gagner 2 secondes.
    Vous confirmez que le fait de déclarer les variables fait gagner du temps d'exécution ?


    Mais ce qui m'a le plus surpris, c'est qu'en remplaçant mon "And" par un "IF Then", cela fait gagner 10 secondes.

    Doit-on toujours donner la priorité à un "If Then" et bannir le "And" pour optimiser le temps d'exécution d'une macro ?

    En tout cas, merci pour votre analyse et votre réécriture.

    Cordialement.

  7. #7
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 248
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 248
    Par défaut
    Hello,
    Citation Envoyé par Fabrice7627 Voir le message
    Mais ce qui m'a le plus surpris, c'est qu'en remplaçant mon "And" par un "IF Then", cela fait gagner 10 secondes.
    Doit-on toujours donner la priorité à un "If Then" et bannir le "And" pour optimiser le temps d'exécution d'une macro ?
    VBA n'utilise pas d'évaluation booléenne de court-circuit (short-circuit en Angliche).
    Les instructions VBA And et Or évaluent toujours les deux expressions de l'instruction. Avec 2 If imbriqués la deuxième expression ne sera pas évaluée si la première expression échoue donc on peut gagner du temps.
    Ami calmant, J.P

  8. #8
    Expert confirmé
    Homme Profil pro
    retraité
    Inscrit en
    Juin 2012
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Juin 2012
    Messages : 3 437
    Par défaut
    Bonjour,

    Les boucles sur i, j, k sont parcourues 100 * 200 * 5000 = 100.000.000 fois, donc chaque microseconde gagnée a de l'effet.

    Le fait de placer If tableau1(i, 2) > j permet de vérifier en premier la condition la plus simple, et inutile d'aller s'occuper de la seconde si elle n'est pas vérifiée. Le If tableau1(i, k + 2) > tableau1(i - 1, k + 2) prendra toujours plus de temps à vérifier vu qu'elle contient beaucoup plus de calculs indirects que l'autre.
    Il est d'ailleurs possible que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                        If tableau1(i, 2) > j And tableau1(i, k + 2) > tableau1(i - 1, k + 2) Then
                            tableau1(i, 3) = 1
                        End If
    donne le même bon résultat, la contrainte la plus simple à vérifier étant testée en premier.

    Enfin je me demande si les lignes 35 à 39 ne pourraient pas être supprimées, avec la ligne 41 devenant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
                    tableau2(k, j) = IIf(tableau1(ub1, 3) = 1, 1, 0)
    Cordialement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Boucles imbriquées et temps d'exécution
    Par Fabrice7627 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/07/2022, 17h30
  2. Réponses: 0
    Dernier message: 20/04/2011, 14h51
  3. Améliorer le temps d'exécution des boucles imbriquées
    Par alexmam15 dans le forum Débuter
    Réponses: 14
    Dernier message: 22/02/2011, 15h25
  4. Exécuter une action en boucle pendant un temps donné
    Par greg_78 dans le forum Général Python
    Réponses: 10
    Dernier message: 07/10/2010, 07h09
  5. Réponses: 1
    Dernier message: 06/05/2008, 13h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo