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 :

Lenteur d'une boucle For each next


Sujet :

Macros et VBA Excel

  1. #1
    Membre du Club
    Femme Profil pro
    Controlling & BI
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Controlling & BI
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 42
    Points
    42
    Par défaut Lenteur d'une boucle For each next
    Bonjour,

    j'ai un problème avec une boucle, elle marche bien mais est particulièrement lente. Je pense que c'est la syntaxe for each...next.
    Je travaille sur un fichier avec 50 onglets et aurais besoin d'un code qui marche vite:

    Voici mon essai:

    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
    Sub SupprCells()
     
    Dim vcell As Variant
    Application.ScreenUpdating = False
    Dim i As Byte
     
    For i = 5 To ActiveWorkbook.Sheets.Count
    ActiveWorkbook.Sheets(i).Select
    Range(Cells(6, 4), Cells(87, 41)).Select
    For Each vcell In Selection
    If vcell.HasFormula = False And IsNumeric(vcell) = True Then
    vcell.ClearContents
    End If
    Next
    Next
    End Sub
    Merci de votre aide!

  2. #2
    Membre régulier
    Inscrit en
    Mai 2011
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Mai 2011
    Messages : 85
    Points : 122
    Points
    122
    Par défaut
    Tu peux ajouter Application.screenupdating=false au début et Application.screenupdating=true. Normalement ça gagne pas mal de temps.

    Après je pense que tu peux gagner du temps en définissant une plage et en faisant for each vcell in plage plutôt que de selectionner à chaque fois la plage. Parce que la selection fait perdre du temps d'après mes souvenirs.

  3. #3
    Invité
    Invité(e)
    Par défaut
    En général il faut éviter tout appel à la fonction '.Select' car elle est dans la plupart des cas inutile.

    Est-ce que ce code est plus rapide ?
    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
    Option Explicit
     
    Private Sub SupprCells()
    Dim rngCell As Range
    Dim i As Long
     
        Application.ScreenUpdating = False
     
        For i = 5 To ActiveWorkbook.Sheets.Count
            With ActiveWorkbook.Sheets(i)
                For Each rngCell In .Range(.Cells(6, 4), .Cells(87, 41))
                    If rngCell.HasFormula = False And IsNumeric(rngCell) = True Then
                        rngCell.ClearContents
                    End If
                Next rngCell
            End With
        Next
     
    End Sub

  4. #4
    Membre averti
    Homme Profil pro
    Responsable Maintenance
    Inscrit en
    Août 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Responsable Maintenance

    Informations forums :
    Inscription : Août 2012
    Messages : 478
    Points : 442
    Points
    442
    Par défaut
    hello,

    ca devrait accelerer

    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
    Sub SupprCells()
     
    	Dim vcell As Variant
    	Application.ScreenUpdating = False
    	Dim i As Byte
     
    		For i = 5 To ActiveWorkbook.Sheets.Count
    			For Each vcell In ActiveWorkbook.Sheets(i).Range(Cells(6, 4), Cells(87, 41))
    				If vcell.HasFormula = False And IsNumeric(vcell) = True Then
    					vcell.ClearContents
    				End If
    			Next
    		Next
    Application.ScreenUpdating = true
    End Sub

  5. #5
    Membre du Club
    Femme Profil pro
    Controlling & BI
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Controlling & BI
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 42
    Points
    42
    Par défaut Lenteur boucle for each next
    Merci pour vos réponses.
    La proposition de vcottineau ne change rien, l'ordi plante, celle d'Ashireon blocke sur la ligne 8...
    Ce qui est étonnant c'est que, bien que l'ordi n'est pas le plus rapide, il exécute des macros très longues et complexes et se blocke sur ce petit bout de code...

  6. #6
    Membre averti
    Homme Profil pro
    Responsable Maintenance
    Inscrit en
    Août 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Responsable Maintenance

    Informations forums :
    Inscription : Août 2012
    Messages : 478
    Points : 442
    Points
    442
    Par défaut
    Quelle est le message stp

  7. #7
    Membre du Club
    Femme Profil pro
    Controlling & BI
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Controlling & BI
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 42
    Points
    42
    Par défaut
    Erreur 1004, erreur définie par l'application ou par l'objet

  8. #8
    Membre expérimenté
    Homme Profil pro
    retraité
    Inscrit en
    Mars 2013
    Messages
    885
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2013
    Messages : 885
    Points : 1 499
    Points
    1 499
    Par défaut lenteur d'une boucle for each next
    bonjour,

    sur la version Ashireon : peut-être déclarer vCell de type Object.

    cordialement.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Merci pour vos réponses.
    La proposition de vcottineau ne change rien, l'ordi plante, celle d'Ashireon blocke sur la ligne 8...
    Ce qui est étonnant c'est que, bien que l'ordi n'est pas le plus rapide, il exécute des macros très longues et complexes et se blocke sur ce petit bout de code...
    Mon code fonctionne. Tu n'as qu'a réduire le nombre de feuilles pour le vérifier. Et il s'exécute plus rapidement qu'avec ta méthode.

    Tu testes environ 150 000 cellules alors c'est normal que ça prenne un peu de temps.

    Il y effectivement une erreur dans le code Ashireon car les références aux cellules ne sont pas bonnes.
    bonjour,

    sur la version Ashireon : peut-être déclarer vCell de type Object.

    cordialement.
    Non. 'vCell' est de type 'Range'.

  10. #10
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 037
    Points : 1 925
    Points
    1 925
    Billets dans le blog
    5
    Par défaut
    bonjour,

    d'abord le problème de lenteur ne doit pas être dû au ScreenUpdating, mais au calcul. Mets le calcul en manuel. je suppose que tes feuilles sont bourrées de formules.
    réadaptation de ton code
    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 SupprCells()
     
        Dim vcell As Range, r As Range
        'Application.ScreenUpdating = False
        Dim i As Byte
     
        Application.Calculation = -4135
        On Error Resume Next
     
        For i = 1 To ActiveWorkbook.Sheets.Count
            Set r = Range(Sheets(i).Name & "!D4:AO87").SpecialCells(xlCellTypeConstants)
            If Err = 0 Then
                For Each vcell In r.Cells
                    If IsNumeric(vcell) Then vcell = ""
                Next
                Set r = Nothing
            End If
            Err = 0
        Next
     
        Application.Calculation = -4105
     
    End Sub

  11. #11
    Membre du Club
    Femme Profil pro
    Controlling & BI
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Controlling & BI
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 42
    Points
    42
    Par défaut
    Ousmane,

    avec ton code je supprimerai toutes les cellules contenants des formules...
    Il y a deux conditions!

  12. #12
    pgz
    pgz est déconnecté
    Expert éminent Avatar de pgz
    Homme Profil pro
    Développeur Office VBA
    Inscrit en
    Août 2005
    Messages
    3 692
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Office VBA
    Secteur : Conseil

    Informations forums :
    Inscription : Août 2005
    Messages : 3 692
    Points : 6 591
    Points
    6 591
    Par défaut
    Bonjour.

    Je te propose :
    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
    Sub SupprCells()
     
    Dim iSaveCalculationMode As Integer
    Dim bSaveUpdatingMode As Boolean
     
    Dim i       As Integer
    Dim vF      As Variant
    Dim vV      As Variant
    Dim li      As Long
    Dim lj      As Integer
    Dim oSh     As Excel.Worksheet
    Dim oRng    As Excel.Range
     
    iSaveCalculationMode = Application.Calculation
    Application.Calculation = xlCalculationManual
     
    bSaveUpdatingMode = Application.ScreenUpdating
    Application.ScreenUpdating = False
     
    For i = 1 To ThisWorkbook.Worksheets.Count
        Set oSh = ThisWorkbook.Worksheets(i)
        Set oRng = oSh.Range(oSh.Cells(6, 4), oSh.Cells(87, 41))
        vF = oRng.Formula
        vV = oRng.Value
     
        For li = 1 To UBound(vF, 1)
            For lj = 1 To UBound(vF, 2)
                If (vF(li, lj) Like "=*") And (IsNumeric(vV(li, lj))) Then vF(li, lj) = vbNullString
            Next lj
        Next li
     
        oRng.Formula = vF
    Next i
     
    Set oSh = Nothing
    Set oRng = Nothing
    Application.Calculation = iSaveCalculationMode
    Application.ScreenUpdating = bSaveUpdatingMode
     
    End Sub
    Cordialement,

  13. #13
    Expert éminent
    Avatar de Didier Gonard
    Homme Profil pro
    Formateur Office et développeur VBA en freelance
    Inscrit en
    Février 2008
    Messages
    2 805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Formateur Office et développeur VBA en freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 2 805
    Points : 6 699
    Points
    6 699
    Par défaut
    Bonjour,

    Si tu n'as pas de dates* dans tes données, tu peux boucler sur chaque feuille en une seule ligne du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Selection.SpecialCells(xlCellTypeConstants, 1).Clear
    équivalent de sélectionner cellules, constantes, nombres de l'interface feuille.


    * les dates étant des numéros de séries en sous-jacent, elles seraient supprimées aussi par ce biais ultra rapide sinon.

    Le contexte exact permettrait d'autres approches peut-être sinon..

    cordialement,

    Didier

  14. #14
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cuisiniste
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2009
    Messages : 15 374
    Points : 12 068
    Points
    12 068
    Billets dans le blog
    8
    Par défaut heu
    Bonjour
    ormonth a raison
    tu pourrais utiliser les fonction native pour un gain de temps
    un exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for i = 5 to sheets.count
    sheets(i).range("a1:c30").SpecialCells (xlCellTypeFormulas, xlNumbers)=""
    next
    on efface toute les cellules qui ont une formule dont le resultat ne peut qu'etre numerique dans la plage de cellules a1:a30 dans le sheets (i)
    i etant l'index du sheets dans la boucle
    Au plaisir

  15. #15
    Membre du Club
    Femme Profil pro
    Controlling & BI
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Controlling & BI
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 42
    Points
    42
    Par défaut Lenteur...
    Merci à tous pour vos réponses.
    Mon code marchait bien avec un autre ordi et un autre fichier, j'ai également testé ces codes selon vos propositions, ça marche bien aussi.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Sub OrmonthOK()
    Dim vcell As Variant
    Application.ScreenUpdating = False
    Dim i As Byte
     
    For i = 2 To ActiveWorkbook.Sheets.Count
    ActiveWorkbook.Sheets(i).Select
    Range(Cells(6, 4), Cells(87, 41)).Select
    Selection.SpecialCells(xlCellTypeConstants, 1).Clear
    Next
    End Sub
    Par contre, il faut prendre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ...(xlCellsTypeConstants, 1).clear ou = ""
    je voulais justement garder les formules et le texte et juste supprimer les données en dur.
    Merci à tous.

  16. #16
    Expert éminent
    Avatar de Didier Gonard
    Homme Profil pro
    Formateur Office et développeur VBA en freelance
    Inscrit en
    Février 2008
    Messages
    2 805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Formateur Office et développeur VBA en freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 2 805
    Points : 6 699
    Points
    6 699
    Par défaut
    Bonjour,

    Comme dit précédemment, et surtout quand on veut optimiser, il faut éviter tous les Select non indispensables !

    Donc ceci est inutile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range(Cells(6, 4), Cells(87, 41)).Select
    Ensuite...
    Par contre, il faut prendre

    ...(xlCellsTypeConstants, 1).clear ou (xlCellsTypeConstants, 1)= ""
    Clear ou = "" n’ont pas du tout les même effets

    Il vaut mieux être toujours explicite
    La méthode Clear appliquée à l’objet Range efface les données (constantes et formules) et les formats (dont les commentaires).
    Il existe sinon pour être plus sélectif :
    La méthode ClearFormats qui supprime les formats seulement
    La méthode ClearContents qui supprime les données, mais préserve les formats, Range(xx) = "" est l’équivalent de Range(xx) .ClearContents.
    Donc ça dépend de ce que tu veux faire…


    Sinon, toujours afin d’éviter les Select et d’optimiser, il est intéressant de changer la notation de la plage de cellule, celle utilisée actuellement revient en sous-jacent à l’utilisation de la méthode Union qui demande une feuille active, une notation avec l’opérateur de plage «:» sur un range permet de s’en passer ( Mon exemple perso = 3 feuilles et Range("A1:E12")).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Sub OrmonthOKTrue()
    Dim I As Byte 'dépend du nombre de feuilles
    'En VBA, regrouper les déclarations en haut de procédure si multiples, c'est plus lisible
     
    'Application.ScreenUpdating = False 'devient inutile vu que pas de Select
     
    For I = 1 To 3
        With Worksheets(I) 'Vu que tu cibles des feuilles de Calcul, autant employer leur  collection spécifique(pas Sheets)
            .Range("A1:E12").SpecialCells(xlCellTypeConstants, 1).Clear 'En passant par cette notation Range, on évite les Select de feuilles
            'ou ClearContents si on veut garder des formats existants
        End With
    Next I
     
    End Sub
    cordialement,

    Didier

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

Discussions similaires

  1. [XL-2007] Copier coller plage de cellules dans une boucle For Each..Next
    Par JulieD33 dans le forum Excel
    Réponses: 3
    Dernier message: 02/03/2015, 12h19
  2. [XL-2007] Boucles For Each Next: problème de défilement des feuilles avec lenteur d'exécution
    Par camelia.w dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 24/12/2011, 21h08
  3. boucle for each next : sauter une valeur
    Par scavenger dans le forum VBScript
    Réponses: 1
    Dernier message: 18/02/2009, 11h15
  4. Boucle For Each Next non entrée
    Par Kareg dans le forum VBA Access
    Réponses: 9
    Dernier message: 21/05/2008, 15h35
  5. [VBA-E]PB sur une boucle for each next
    Par rond24 dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 31/07/2006, 16h47

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