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 :

Le mystère de la Boucle For Each [XL-2010]


Sujet :

Macros et VBA Excel

  1. #1
    Membre habitué
    Homme Profil pro
    Back Office Marchés
    Inscrit en
    Mars 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Back Office Marchés
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 65
    Points : 139
    Points
    139
    Par défaut Le mystère de la Boucle For Each
    Bonjour à tous,

    En préambule, je précise que je n'ai pas de problème à résoudre, j'ai une solution qui fonctionne, mais j'aimerais soumettre le problème suivant à votre sagacité.

    Dans un code que je viens d'écrire j'avais une première version qui lit le contenu d'une feuille avec une boucle For Each (ligne). Ma feuille de test contient 8 lignes. L'objectif est de lire 3 critères par ligne pour déterminer la nature de la ligne. La boucle For Each lit bien les données jusqu'à la ligne 4 puis ne trouve plus les informations. J'ai modifié mon code pour faire un For avec un compteur et là tout se passe bien. Ci-dessous les deux codes de test et le résultat de la console.

    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
     
            Set wbkNewedge = Workbooks.Open(strFileName)
            Set rgeDataNewedge = wbkNewedge.Sheets(1).Cells(1, 1).CurrentRegion
     
            Debug.Print "Adresse de la plage = " & rgeDataNewedge.Address
     
     
            ' NOUVEAU 06/11/2017
            ' A chaque ligne du fichier NE
            ' on regarde si c'est une transaction, une position ou une valo
            ' on écrit dans la colonne 2 le résultat
     
            Debug.Print "======== Boucle For Compteur Next ======="
            For i = 1 To rgeDataNewedge.Rows.Count
                Debug.Print "Ligne : " & i & " -> " & rgeDataNewedge.Cells(i, 2).Value & " " & rgeDataNewedge.Cells(i, 4).Value & " " & rgeDataNewedge.Cells(i, 117).Value
            Next i
            Debug.Print vbCrLf
            Debug.Print "======== Boucle For Each Next ==========="
            For Each rgeRow In rgeDataNewedge.Rows
                Debug.Print "Ligne : " & rgeRow.Row & " -> " & rgeRow.Cells(rgeRow.Row, 2) & " " & rgeRow.Cells(rgeRow.Row, 4) & " " & rgeRow.Cells(rgeRow.Row, 117)
    '            If ValueOfType(strType, rgeRow) Then
    '                rgeRow.Cells(rgeRow.Row, 2).Value = strType
    '            End If
            Next rgeRow
    Adresse de la plage = $A$1:$DN$8
    ======== Boucle For Compteur Next =======
    Ligne : 1 -> Message Type Lifecycle Event Eulite Level
    Ligne : 2 -> Trade State New T
    Ligne : 3 -> Trade State New T
    Ligne : 4 -> Trade State New T
    Ligne : 5 -> Trade State New T
    Ligne : 6 -> Trade State New T
    Ligne : 7 -> Trade State New T
    Ligne : 8 -> Trade State Modify P


    ======== Boucle For Each Next ===========
    Ligne : 1 -> Message Type Lifecycle Event Eulite Level
    Ligne : 2 -> Trade State New T
    Ligne : 3 -> Trade State New T
    Ligne : 4 -> Trade State New T
    Ligne : 5 ->
    Ligne : 6 ->
    Ligne : 7 ->
    Ligne : 8 ->

    C'est le grand mystère mystérieux de la semaine... Quelqu'un aurait il une idée de ce qui cloche ? Par avance, je précise que nous avons passé le classeur source au crible et que les données semblent absolument kasher...

    Merci par avance pour votre temps et vos réponses.

    Guillaume.

  2. #2
    Membre émérite Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Points : 2 439
    Points
    2 439
    Par défaut
    Bonjour Golonn,

    Comment est déclaré rgeRow ?!?
    Si pas déclaré elle est de type "Row". Car utilisée pour boucler sur une collection de row (rows).
    En réalité le type Row n'existe pas et il s'agit en fait d'un type Range de dimension (1,n).

    rgeRow.cells(a,b) avec a>1 provoque donc des confusions (Voir le comportement de .Cells(a,b) en fonction du Range devant et des paramètres a et b).

    Test avec ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    For Each rgeRow In rgeDataNewedge.Rows
                Debug.Print "Ligne : " & rgeRow.Row & " -> " & rgeRow.Cells(2) & " " & rgeRow.Cells(4) & " " & rgeRow.Cells(117)
            Next rgeRow

    Un petit test à faire :
    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 test()
        Dim ObjRange
            Debug.Print "Boucle sur les cellules"
            For Each ObjRange In Range("A1:B2")
                Debug.Print ObjRange.Address
            Next
            Debug.Print "Boucle sur les lignes"
            For Each ObjRange In Range("A1:B2").Rows
                Debug.Print ObjRange.Address
            Next
            Debug.Print "Boucle sur les lignes avec .cells(3,3)"
            For Each ObjRange In Range("A1:B2").Rows
                Debug.Print ObjRange.Cells(3, 3).Address
            Next
    End Sub
    La troisième boucle affiche des adresses hors des lignes sur lesquelles on boucle.
    Antony

    Mieux vaut ne rien dire et passer pour un con que de l'ouvrir et ne laisser aucun doute à ce sujet.
    Gustave Parking


    Si le post vous est utile un petit fait toujours plaisir et pensez à passer en

    Et surtout -> Balise CODE

  3. #3
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 379
    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 379
    Points : 12 075
    Points
    12 075
    Billets dans le blog
    8
    Par défaut RE
    BONSOIR

    regarde bien ta 1 ere boucle et regarde quel parent j'utilise
    dans la 2d boucle aussi regarde bien le parent
    et il faut faire pareil pour les colonnes mais n'en sachant pas plus ???????

    en effet
    rgeDataNewedge.cells(x,4) n'est pas pareil que rgeDataNewedge.parent.cells(x,4)

    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
    Set wbkNewedge = Workbooks.Open(strFileName)
    Set lesheet = wbkNewedge.Sheets(1)
    Set rgeDataNewedge = lesheet.Cells(1, 1).CurrentRegion
    Debug.Print "Adresse de la plage = " & rgeDataNewedge.Address
     
    ' NOUVEAU 06/11/2017
    ' A chaque ligne du fichier NE
    ' on regarde si c'est une transaction, une position ou une valo
    ' on écrit dans la colonne 2 le résultat
    Debug.Print "======== Boucle For Compteur Next ======="
    'ATTENTION ICI LA VARIABLE I INCREMENTEE REPRESNTE PAS FORCEMENT L INDEX DE LIGNE SAUF SI L ON COMMENCE EN LIGNE 1
    For i = 1 To rgeDataNewedge.Rows.Count
        Debug.Print "Ligne : " & i & " -> " & lesheet.Cells(rgeDataNewedge.Rows(i), 2).Value & " " & lesheet.Cells(rgeDataNewedge.Rows(i), 4).Value & " " & lesheet.Cells(rgeDataNewedge.Rows(i), 117).Value
    Next i
    Debug.Print vbCrLf
    Debug.Print "======== Boucle For Each Next ==========="
     
    For Each rgeRow In rgeDataNewedge.Rows
     
        Debug.Print "Ligne : " & rgeRow.Row & " -> " & lesheet.Cells(rgeRow.Row, 2) & " " & lesheet.Cells(rgeRow.Row, 4) & " " & lesheet.Cells(rgeRow.Row, 117)
        '            If ValueOfType(strType, rgeRow) Then
        '                rgeRow.Cells(rgeRow.Row, 2).Value = strType
        '            End If
    Next rgeRow
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

  4. #4
    Membre émérite Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Points : 2 439
    Points
    2 439
    Par défaut
    En fait ObjetRange.cells(x,y) fait toujours la même chose.
    On part de la cellule en haut à gauche de l'objetRange puis on descend de x ligne(s) de décale a droite de y colonne(s) (x>=0 et y>=0). Le résultat est un Range d'une seule cellule.

    Si on utilise ObjetWorksheet.Cells(x,y) (comme l'indique Patrick avec ObjRange.Parent.Cells(x,y)) on fait on utilise un range qui fait toute la feuille ObjetWorkSheet (qui commence toujours en A1).
    Pour moi c'est la même chose modulo un changement de TopLeftCell.


    Il faut simplement comprendre que le plus important, lorsqu'on utilise .Cells(x,y), c'est la TopLeftCell du range spécifié et que le résultat sera un Range d'une seule cellule. Contrairement à Offset qui décale de x ligne(s) et y colonne(s) (avec x et y pouvant être négatifs) mais conserve la dimension du Range.


    En résumé pas de mystère dans ta boucle juste une confusion dans l'utilisation de .Cells(,).
    En changeant les données de ta feuille tu pourras même constaté que le résultat de la fenêtre d'exécution n'est pas celui escompté (décalage de ligne(s)). La boucle ne s'arrête pas après la ligne 4 mais renvoi des données sous la ligne 8 qui sont vides.
    Antony

    Mieux vaut ne rien dire et passer pour un con que de l'ouvrir et ne laisser aucun doute à ce sujet.
    Gustave Parking


    Si le post vous est utile un petit fait toujours plaisir et pensez à passer en

    Et surtout -> Balise CODE

  5. #5
    Membre expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 267
    Points : 3 663
    Points
    3 663
    Par défaut
    Bonjour,

    On part de la cellule en haut à gauche de l'objetRange puis on descend de x ligne(s) de décale a droite de y colonne(s) (x>=0 et y>=0).
    Pas tout à fait.
    .Cells(x,y) donne la cellule de coordonnées (x,y), la grille partant de la cellule haut-gauche de coordonnées (1,1).
    En l'absence d'expression devant c'est la feuille qui est prise en compte, ce qu'on fait habituellement.
    Pour être précis c'est donc un offset(x-1,y-1)
    eric

  6. #6
    Membre émérite Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Points : 2 439
    Points
    2 439
    Par défaut
    @eriiic

    C'est exactement ce que j'ai écris.

    Première ligne de mon précédent post c'est dans le cas d'un Range devant.
    Deuxième ligne c'est dans le cas d'un Worksheet devant. Je n'ai juste pas précisé qu'en l'absent d'objet devant Cells(,xy) c'est ActiveSheet qui est pris en compte et comme je l'indique, la TopLeftCell d'une feuille est toujours A1.
    Antony

    Mieux vaut ne rien dire et passer pour un con que de l'ouvrir et ne laisser aucun doute à ce sujet.
    Gustave Parking


    Si le post vous est utile un petit fait toujours plaisir et pensez à passer en

    Et surtout -> Balise CODE

  7. #7
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 379
    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 379
    Points : 12 075
    Points
    12 075
    Billets dans le blog
    8
    Par défaut re
    Bonjour
    ce que j'ai essayé d'expliquer est tout simplement d'éviter l'utilisation de objetrange.cells(x,y)

    mais plutôt objectsheet.range(x,y)

    pour la simple et bonne raison et ne me demandez pas pourquoi je n'ai jamais trouvé la réponse que objectrange.cells(x,y) donne sur certaines installation des résultats surprenants

    tandis que si l 'on fait objectrange.cells(x) ca fonctionne x étant la NEmme cellule de la plage

    c'est pourquoi l'écriture par le parent (sheets) est plus sur
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 267
    Points : 3 663
    Points
    3 663
    Par défaut
    @eriiic
    C'est exactement ce que j'ai écris.
    Tu as écris : puis on descend de x ligne(s) de décale a droite de y colonne(s)
    C'est : on descend de x-1 ligne(s) de décale a droite de y-1 colonne(s).
    Pas bien grave en soit, mais dans l'absolu ce n'est pas équivalent à offset. Simple soucis de précision.

  9. #9
    Membre émérite Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Points : 2 439
    Points
    2 439
    Par défaut
    Mea culpa, Tu as raison eriiic.

    Pardon pour cette erreur
    Antony

    Mieux vaut ne rien dire et passer pour un con que de l'ouvrir et ne laisser aucun doute à ce sujet.
    Gustave Parking


    Si le post vous est utile un petit fait toujours plaisir et pensez à passer en

    Et surtout -> Balise CODE

  10. #10
    Membre habitué
    Homme Profil pro
    Back Office Marchés
    Inscrit en
    Mars 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Back Office Marchés
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 65
    Points : 139
    Points
    139
    Par défaut Mystère résolu !
    Citation Envoyé par antonysansh Voir le message
    Bonjour Golonn,

    Comment est déclaré rgeRow ?!?
    Bonjour antonysansh,

    Tout d'abord merci pour ta réponse . rgeRow est déclaré comme un Range dans mon. Ton code qui appelle Cells(x) fonctionne parfaitement et lit bien toutes les données.

    Pour résumer si j'ai bien compris :

    On ne doit pas appeler .Cells(x,y) sur un ObjetRange : cela génère une confusion car le résultat est un range d'une cellule et .cells(x,y) réagit comme Offset. On appelle plutôt la feuille.

    Merci également à patricktoulon (toujours disponible !) et à eriiic pour vos contributions et précisions. J'adore ce forum pour ce genre de réponses précises, expertes et détaillées.

    Guillaume, qui va se coucher moins bête ce soir...

  11. #11
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bonjour à tous
    Traiter tout simplement les choses (quelles qu'elles soient) comme des ensembles et leurs sous-ensembles.
    Il est alors aisé de comprendre que la position d'un élément dans un ensemble est déterminée par rapport à une origine de l'ensemble et que la position d'un élément dans un sous-ensemble est déterminée par rapport à une origine dans ce sous-ensemble.
    Si l'on spécifie le sous-ensemble -->> ce sera par rapport à ce sous-ensemble-là.
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 267
    Points : 3 663
    Points
    3 663
    Par défaut
    On ne doit pas appeler .Cells(x,y) sur un ObjetRange
    Mais si tu peux, c'est prévu pour.
    Personnellement je n'ai jamais eu de soucis avec.
    Il n'y confusion que si tu as mal assimilé le principe.
    .cells(x,y) se réfère à ta plage (qui est le plus souvent la feuille entière, mais pas que...)
    Si tu as une plage 3x3 au milieu de ta feuille, et bien ta_plage.cells(2,2) sera la cellule au centre de cette plage 3x3.

  13. #13
    Membre régulier Avatar de GESCOM2000
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 107
    Points : 79
    Points
    79
    Par défaut
    perso je prefere tout recuper dans un tablo et faire ma tambouille puis apres le resultat voulu le transposer le tablo dans les cellules
    ca va plus vite...

  14. #14
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bonjour GESCOM2000
    Comme beaucoup d'entre nous (chaque fois que possible)
    Mais mécanisme inadapté lorsque la plage à traiter (qu'elle soit la source ou la destination) n'est pas continue.
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

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

Discussions similaires

  1. boucle for each
    Par jadey dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 30/08/2006, 20h50
  2. [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, 15h47
  3. aide vba boucle for each paramétrée en range
    Par gotlieb dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 27/07/2006, 08h55
  4. [VBA-E] erreur boucle for each
    Par Mut dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 15/02/2006, 16h38
  5. Boucle For each
    Par roots_man dans le forum ASP
    Réponses: 10
    Dernier message: 18/02/2005, 09h55

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