VBA - Problème de Boucle et Répétition des Résultats
Bonjour à tous,
Je me présente rapidement Stéphane, je viens très régulièrement sur ce forum, plutôt en visiteur, et jusqu'à présent j'ai toujours réussit à me débrouiller avec vos explications et exemples. Mais dans le cas présent j'avoue que je bloque sérieusement sur un code.
(A noter qu'en code VBA j'ai plutôt un niveau "Dépatouilleur" que même débutant...)
Vous trouverez un exemple du fichier que je tente de mettre en place.
Les 2 colonnes concernées par ma recherche sont les E et H, avec en conditions :
- Si dans la Colonne E les cellules sont saisies avec la valeur "E" (ou vierge), alors j'envoi un mail
- Si dans la Colonne E les cellules sont saisies avec la valeur "E", et que leur pendant en colonne H contient une donnée, alors j'envoie un mail
- Si dans la colonne E les cellules sont saisies avec la valeur "E", mais que leur pendant en colonne H est vierge, alors j'affiche un message d'erreur.
J'arrive à créer ces conditions et résultats pour une seules et même ligne, mais dés lors que je veux répéter sur plusieurs lignes, ou mettre une boucle, alors les résultats se multiplient autant de fois que de ligne à regarder.
Auriez vous une idée ? (Dans le cas du fichier, je suis revenu à un code relativement simple, du moins je pense, qui ne reprend qu'une seule ligne)
En vous remerciant par avancez de votre aide.
Bonjour et bienvenue,
Votre code est très correct pour quelqu'un qui se considère comme débutant. Si j'ai bien compris (pas sur), vous souhaitiez boucler sur le tableau visible dans la macro Vérification_Données. Ci-après une proposition et quelques notes.
Mais je ne sais pas comment marche la macro d'envoi de mails, et si elle est générique ou doit s'adapter à la ligne parcourue. Il me semble que non donc je ne l'ai pas modifiée.
Sub Vérification_Données()
Dim derniereLigne As Long
derniereLigne = 28
Dim numeroLigne As Long
Dim target As Range
' c'est important, voir essentiel
' car si vous avez une autre feuille active la macro va faire n'importe quoi
Sheets("Saisie").Activate
For numeroLigne = 9 To derniereLigne
Set target = ActiveSheet.Range("E" & numeroLigne)
If target.Value <> "E" Then
envoi_mail ' pas besoin de "Call", c'est une instruction obsolete
ElseIf target.Value = "E" And Not IsEmpty(Range("H" & numeroLigne)) Then
envoi_mail
ElseIf target.Value = "E" And IsEmpty(Range("H" & numeroLigne)) Then
MsgBox "un E doit obligatoirement faire l'objet d'un H", vbExclamation
' utiliser Activate plutot que Select force a ne selectionner qu'un element
' c'est un détail mais pour votre cas c'est plus correcte
Sheets("Saisie").Activate
Range("H" & numeroLigne).Activate
End If
Next numeroLigne
End SubPensez à déclarer vos variables (Dim), cela vous donnera accès à l'autocomplétion via IntelliSense.
Faites attention, par défaut écrire "Range(blablabla)" fait référence à la feuille active... qui n'est pas toujours celle sur laquelle on travaille ! Il est préférable d'écrire Thisworkbook.Worksheets("nomfeuille").Range(blablabla). C'est plus long mais ca ne bugue pas.
Déjà un très grand merci pour ce retour très rapide, et surtout pour ces petites annotations dans votre Code qui me permettent de comprendre (super sympas)
En revanche cela ne fonctionne pas comme souhaité, les actions se répètent toujours à chaque contrôle de ligne (28 lignes, 28 Contrôles, 28 actions).
Mais en même temps je m'aperçois que je n'ai pas été suffisamment clair dans ma recherche.
De façon très simpliste, je cherche :
1- A ce que le fichier s'envoi automatiquement par mail dés lors que l'on clique sur "envoyer" (un seul mail envoyé, quelque soit le nombre et la condition recherchée/trouvée) - Le code pour l'envoi du mail est écrit, je n'ai pas de souci sur ce point.
2- SAUF si dans la colonne E les cellules sont saisies avec la valeur "E", mais que leur pendant en colonne H est vierge (Contrôle E9 par rapport à H9, E10/H10, etc.)
Dans se second cas, pas d'envoi de mail, mais un blocage et une alerte MsgBox. Ce blocage et alerte (dans la même idée que le point 1) ne devant se répéter qu'une seule fois dés lors que le code trouve une condition FALSE.
In fine, un contrôle des 28 lignes en lien avec le point 2, mais avec une seule action finale : Envoi mail ou blocage MsgBox
En vous présentant mes excuses pour mon absence de clarté, et en espérant que ces lignes vous aide à mieux comprendre ma recherche.
Bonjour,
Ah je me disais bien que quelque chose m'échappait… Je me demandais pourquoi envoyer 10x le meme mail, maintenant tout prend sens !
Ci-après la macro adaptée, en reprenant les conseils que j'évoquais plus haut. Si vous avez des questions n'hésitez pas.
Le principe est expliqué dans les commentaires du code.
Sub Vérification_Données()
Dim derniereLigne As Long
derniereLigne = 28
Dim numeroLigne As Long
With ThisWorkbook.Worksheets("Saisie") ' pour utiliser ".Range" apres
For numeroLigne = 9 To derniereLigne
If .Range("E" & numeroLigne).Value = "E" _
And IsEmpty(.Range("H" & numeroLigne)) Then
' probleme : la ligne contient "E" ET il manque l'info en H :
' on quitte la boucle et on va afficher un msg alerte
Exit For
End If
Next numeroLigne
End With
' on vérifie si toutes les lignes ont passé le test
' comment ?
' si numeroLigne = derniere ligne, alors
' on n'a pas quitté la boucle avant la fin, toutes les lignes sont correctes
' sinon,
' on a quitté la boucle avant la fin, numeroLigne < derniereLigne
If numeroLigne < derniereLigne Then
MsgBox "un E doit obligatoirement faire l'objet d'un H", vbExclamation
' sélection de la cellule incomplète
With ThisWorkbook.Worksheets("Saisie")
.Activate
.Range("H" & numeroLigne).Activate
End With
Else
' sinon on est tout bon, on peut envoyer le mail
envoi_mail
End If
End SubExtra. Cela fonctionne à la perfection.
Un considérable merci pour votre aide.
Bonjour,
En consultant votre post, je vois qu'il y a une petite erreur au niveau du traitement en sortie de boucle.
Lorsqu'une boucle For/Next se termine normalement (sans interruption), le compteur est égale à la borne fin +1.
Dans le cas présent, si la dernière ligne (ligne 28) est en anomalie, elle n'est pas signalée.
Il suffit de modifier le test
If numeroLigne < derniereLigne Then en If numeroLigne - 1 < derniereLigne Then
Bonne journée
Effectivement, grave erreur de ma part ! Merci pour le retour, à corriger absolument !