Petit problème vba avec des conditions et la formule "For Each C in"

JEJSLY

XLDnaute Nouveau
Bonjour à tous,

Je suis tout débutant en VBA, et j'ai un petit problème avec les conditions et la formule "For Each C in".

Voila mon souci:
Dans un classeur1, j'ai plusieurs feuilles liés et différentes macros, l'une de ces macro doit vérifier dans un autre classeur (archives) si des enregistrements existent et dans certaines conditions, lancer d'autres macro, ou avertir l'utilisateur avec des MsgBox.

J'ai commencé à coder cette macro, mais bien évidemment cela ne fonctionne pas.

Je montre le code quand même, en espérant que quelqu'un pourra m'aider à le corriger.
Code:
Sub Verifdoublon()

    Dim Lieu As String
    Dim Colp As String
    Dim Jour As Long
    Dim Soirée As String
    Dim Début As Long
    Dim Fin As Long
    Lieu = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("D2").Value
    Colp = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("K2").Value
    Jour = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("C2").Value
    Soirée = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("I2").Value
    Début = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("G2").Value
    Fin = Workbooks("Classeur1.xlsm").Sheets("Archives").Range("H2").Value
    
' On vérifie si le même enregistrement éxiste déjà dans les archives
    Windows("Archives.xlsb").Activate
    Sheets("Archives").Select
    
    Dim co As Boolean
    Dim jo As Boolean
    Dim li As Boolean
    Dim so As Boolean
    Dim dé As Boolean
   
    Dim Plagecolp As Range
    Set Plagecolp = Range("K2:K65536").SpecialCells(xlCellTypeVisible)
    For Each C In Plagecolp
    If C Like Colp Then
    co = True
    End If
   
    Dim Plagejour As Range
    Set Plagejour = Range("C2:C65536").SpecialCells(xlCellTypeVisible)
    For Each C In Plagejour
    If C Like Jour Then
    jo = True
    End If
    
    Dim Plagelieu As Range
    Set Plagelieu = Range("D2:D65536").SpecialCells(xlCellTypeVisible)
    For Each C In Plagelieu
    If C Like Lieu Then
    li = True
    End If

    Dim Plagesoirée As Range
    Set Plagesoirée = Range("I2:I65536").SpecialCells(xlCellTypeVisible)
    For Each C In Plagesoirée
    If C Like Soirée Then
    so = True
    End If

    Dim Plagedébut As Range
    Set Plagedébut = Range("G2:G65536").SpecialCells(xlCellTypeVisible)
    For Each C In Plagedébut
    If C Like Début Then
    dé = True
    End If
    
    
    If co = True And jo = True And dé = True Then
    If MsgBox.Show("1° information", MsgBoxStyle.YesNo Or MsgBoxStyle.Exclamation) = MsgBoxResult.Yes Then
'On archive le nouvel enregistrement
    Call archiver
    Else
     Windows("Classeur1.xlsm").Activate
     Sheets("CONSOLE").Select
     Range("C3").Select
    Exit Sub
    End If
    End If
    
    If so = True And jo = True And li = True Then
    If MsgBox.Show("2° information", MsgBoxStyle.YesNo Or MsgBoxStyle.Exclamation) = MsgBoxResult.Yes Then
'On archive le nouvel enregistrement
    Call archiver
    Else
     Windows("Classeur1.xlsm").Activate
     Sheets("CONSOLE").Select
     Range("C3").Select
    Exit Sub
    End If
    End If
    
    
End Sub

Merci d'avance
 

Cousinhub

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Bonsoir,
A priori, tu initialises plusieurs boucles, sans reboucler...

exemple :

Code:
For Each C In Plagejour
    If C Like Jour Then
    jo = True
    End If
[COLOR="Red"]' Ici, il manque le 
Next C[/COLOR]
 

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut JEJSLY, bhbh et le forum
Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim c As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Long
Dim Soirée As String
Dim Début As Long
Dim Fin As Long
Dim co As Boolean
Dim jo As Boolean
Dim li As Boolean
Dim so As Boolean
Dim dé As Boolean
'MEI =========================================================
With Workbooks("Classeur1.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
' On vérifie si le même enregistrement éxiste déjà dans les archives
' Initialisation des variables booléennes =====================
Workbooks("Archives.xlsb").Activate
Sheets("Archives").Activate
For Each c In Range("C2:C" & _
        UsedRange.SpecialCells(xlCellTypeLastCell).Rows).SpecialCells(xlCellTypeVisible)
    If c Like Jour Then jo = True                   'C
    If c.Offset(0, 1) Like Lieu Then li = True      'D
    If c.Offset(0, 4) Like Début Then dé = True     'G
    If c.Offset(0, 6) Like Soirée Then so = True    'I
    If c.Offset(0, 8) Like Colp Then co = True      'K
    If jo And li And dé And so And co Then Exit For
Next c
'Traitement =================================================
If co And jo And dé Then
    If MsgBox.Show("1° information", MsgBoxStyle.YesNo Or _
       MsgBoxStyle.Exclamation) = MsgBoxResult.Yes Then
     'If MsgBox("1° information", vbExclamation + vbYesNo, "archivage") = vbYes Then
        Call archiver
    Else
        Windows("Classeur1.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
    End If
End If
If so And jo And li Then
    If MsgBox.Show("2° information", MsgBoxStyle.YesNo Or _
       MsgBoxStyle.Exclamation) = MsgBoxResult.Yes Then
    'If MsgBox("2° information", vbExclamation + vbYesNo, "archivage") = vbYes Then
        Call archiver
    Else
        Windows("Classeur1.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
    End If
End If
End Sub
ça devrait améliorer la vitesse de traitement

l'indentation du code n'est pas une histoire de faire beau ou pas : quand tu fait des codes long, ça te permets de situer les groupes d'instructions dans la boucle, le test, etc..;
quand tu as des imbrications boucles tests boucles tests ... tu dois retrouver au même niveau d'indentation les instructions de défut et de fin.
Dans ton dernier test, (If so And ...) d'un coup d'oeil, tu peux voir quels sont les intructions concernées par la partie True et celles par la partie False.

Quand tu as une succession de boucle, il faut rechercher si tu ne peut pas réduire le nombre d'instruction. Même si c.offset est plus lent que c, c'est quand même plus rapide que For...Next

"C2:C65536" : c'est une instruction typique version 2003 et antérieure.
La version 2007 à des limites plus grandes.

Dans ta macro, tu balaies 65534 lignes (que celles visibles, je sais)
Si l'instruction avec UsedRange ne fonctionne pas (elle limite les lignes à la dernière utilisée), en revenant à 65536, tu sorts de la boucle dès que toutes tes variables sont à true : si à la ligne 10, tu as le résultat, pourquoi continuer.

Dans ta macro, tu déclares tes variables : c'est bien (mais pourquoi pas c ? il t'a fait quelque chose ?). Mais je pense qu'il est préférable de regrouper les déclarations en un seul endroit. Quelque soit l'endroit (dans la macro) où une variable est déclarée, VBA fait un premier passage sur le code pour rechercher les déclarations, réserve la place en RAM et commence à exécuter la première instruction. Donc si ça ne change rien, pourquoi les mettre dans tout le code ?

A+

PS ne disposant pas de la version 2007, je n'ai pas testé le code. Il me semble bon, à par la partie MsgBox que je suppose pur Version 2007. j'ai mis en commentaire ce que j'aurais codé
 
Dernière édition:

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut ,Gorfael, bhbh, le forum,

Merci à vous deux de m'avoir répondu aussi vite!

-bhbh, j'ai bien lut ton commentaire, et j'en prend note pour d'autres cas, mais Gorfael dans son post me propose de réduire le code et d' optimiser cette macro, je vais donc suivre sa solution.

-Gorfael, tout ce que tu m'as dit me semble très logique, et en relisant le code, je crois comprendre à peu près tout, si ce n'est:

If c.Offset(0, 1) Like Lieu Then li = True 'D
If c.Offset(0, 4) Like Début Then dé = True 'G
If c.Offset(0, 6) Like Soirée Then so = True 'I
If c.Offset(0, 8) Like Colp Then co = True 'K

là j'ai pas compris?

Sinon, lorsque j'appelle la macro, j'ai une erreur d'exécution "424"
sur cette ligne:

Code:
For Each c In Range("C2:C" & _
UsedRange.SpecialCells(xlCellTypeLastCell).Rows).SpecialCells(xlCellTypeVisible)

Que dois je faire?

Cordialement
 

cbea

XLDnaute Impliqué
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Bonsoir à tous,

Peux-tu essayer ceci ?

Code:
For Each c In Range("C2:C" & _
UsedRange.SpecialCells(xlCellTypeLastCell).Rows.SpecialCells(xlCellTypeVisible).Row)
 

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut à toutes et à tous
c va de C2à C65536
If c.Offset(0, 1) Like Lieu Then li = True 'D
c décalé de une colonne vers la doite
donc, si c=C2, c.Offset(0, 1)revient à écrire D2
If c.Offset(0, 4) Like Début Then dé = True 'G
c=c2 décalé de 4 colonne (D,E,F;G) => c=G2
If c.Offset(0, 6) Like Soirée Then so = True 'I
C2 + 6 colonnes (D, E, F, G, H, I) => c=I2
If c.Offset(0, 8) Like Colp Then co = True 'K
C2 décalé de 8 (D, E, F, G, H, I, J, K) c=K2

[C2].offset(0,0) <=> [C2]
[C2].offset(1,0) <=> [C3]
[C2].offset(0,1) <=> [D2]
[C2].offset(1,1) <=> [D3]
A+
 

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut à tous,

Avec ton dernier post, Gorfael, je comprends mieux la formule.
Par contre, j'ai apliqué la modif de cbea, mais j'ai toujours la même erreur d'exécution "424" à la même ligne.

Cordialement
 

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut JEJSLY
Code:
For Each c In Range("C2:C" & _
UsedRange.SpecialCells(xlCellTypeLastCell).Row).SpecialCells(xlCellTypeVisible)
Oooups !
UsedRange.SpecialCells(xlCellTypeLastCell).Row <= pas de "s" à Row
à faire vite.... on fait vite fait des conn.... :eek:
UsedRange : la plage utilisée
SpecialCells(xlCellTypeLastCell) : la dernière cellule de la plage
Row : la ligne

Sinon, remplace cette instruction par
Code:
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
Tu maîtrises mieux.
A+
 

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Bonjour, Gorfael, le forum,

Avec ce code:
Code:
For Each c In Range("C2:C" & _
UsedRange.SpecialCells(xlCellTypeLastCell).Row).SpecialCells(xlCellTypeVisible)
J'ai toujours l'erreur 424.

Avec ce code:
Code:
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
cela fonctionne.

Par contre, le petit souci, c'est que les variables Jour Début et Fin, sont une date et des heures, donc déclaré en Long.
Mais lors du traitement de la macro, elle ne sont pas reconnu comme déjà existante.
Je pourrais bricolé sans problème pour y arriver mais cela alourdirait conséquemment le traitement.
Aurais tu une suggestion?

merci pour tout

cordialement
 

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut JEJSLY
Par contre, le petit souci, c'est que les variables Jour Début et Fin, sont une date et des heures, donc déclaré en Long.
Mais lors du traitement de la macro, elle ne sont pas reconnu comme déjà existante.
Comme quoi, on voit le petit problème et pas le gros :D

les dates, heures sont déclarées dans excel en nombre décimal :
nombre de jours depuis le 1/1/1900, heures (pour le calcul, change une date en format de cellule standard et tu verras comment Excel stoque la valeur qu'il affiche.

Donc, je te conseillerais de te faire une petite macro qui compaare juste 1 cellule du genre :
sub test
dim a as Date
if [X1] like [Y1] then [Z1]="oui" else [Z1]="Non"
if [X1] = [Y1] then [Z2]="oui" else [Z2]="Non"
end sub
et de tester ce qui répond le mieux à ce que tu veux avoir comme résultat avec en cellule Y1 la valeur correspondant à jour, puis à heure, etc..
J'ai juste mis Like et =, mais tu peux tester avec tous les opérateurs et valeurs, pour trouver ce qui correspond le mieux.

Il est toujours difficile d'aider dans une question comme ça, sans les valeurs réellement utilisées.
A1 : =AUJOURDHUI() => affiche 29/03/2008
A2 : =A1 + 0,01 => affiche 29/03/2008
en format de date choisi par excel. Pourtant, 39536 est différent de 39536,01 et Excel le sait bien (^^)
Il faudrait sans doute passer par une transformation des valeurs INT() sur comparant et comparé pour les jours et une manipulation du même acabit pour les heures INT((Valeur-INT(valuer))*100000).

Seul, un bout de fichiers Excel, permet de comprendre le problème et d'envisager une solution.

A+
 
Dernière édition:

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut Gorfael,

Bon je m'en suis sorti, en créant deux petites macro, l'une qui change le format de mes cellules ou colonnes concerné en "Général" et les variables deviennent "Variant"
et l'autre qui fait l'inverse, pour que cela soit plus lisible pour l'utilisateur.

Cela fonctionne bien, sans trop ralentir le traitement.

J'aimerais améliorer un peu cette macro, en changeant la couleur de fond des cellules de la Feuille "Archives" du Classeur "Archives" qui contiennent la même valeur que les variables déclarées, Afin de faciliter la décision de l'utilisateur.
J'ai mis dans le code, dans la partie Traitement une meilleur explication:

Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim c As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Variant
Dim Soirée As String
Dim Début As Variant
Dim Fin As Variant
Dim co As Boolean
Dim jo As Boolean
Dim li As Boolean
Dim so As Boolean
Dim dé As Boolean
'MEI =========================================================
With Workbooks("Console colporteurs.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
' On vérifie si le même enregistrement éxiste déjà dans les archives
' Initialisation des variables booléennes =====================
Workbooks("Colporteursarchives.xlsb").Activate
Sheets("Archives").Activate
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
If c Like Jour Then jo = True                   'C
    If c.Offset(0, 1) Like Lieu Then li = True      'D
    If c.Offset(0, 4) Like Début Then dé = True     'G
    If c.Offset(0, 6) Like Soirée Then so = True    'I
    If c.Offset(0, 8) Like Colp Then co = True      'K
    If jo And li And dé And so And co Then Exit For
Next c
'Traitement =================================================
If co And jo And dé Then
        'On colorie en rouge le fond de chaques cellule co, jo et dé de la feuille Archives si:(co=Colp, jo=Jour et dé=Début)
        'et uniquement pour les lignes dans lesquelles les trois conditions sont remplis
        'cela serait plus pratique que ces lignes soient visibles sous la MsgBox
        'cell.Interior.ColorIndex = 3
        Call Formatdate
     If MsgBox("Ce colporteur travaille déjà ce jour là, à cet horaire là!" & Chr(13) & "Voulez vous quand même sauvegarder l'enregitrement?", vbExclamation + vbYesNo, "archivage") = vbYes Then
        Call archiver
        Exit Sub
    Else
        Call Formatdate
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
    End If
End If
If so And jo And li Then
       Call Formatdate
    If MsgBox("Ce flyer est déjà distribué ce jour là à cet endroit là!" & Chr(13) & "Voulez vous quand même sauvegarder l'enregitrement?", vbExclamation + vbYesNo, "archivage") = vbYes Then
       Call archiver
       Exit Sub
    Else
        Call Formatdate
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
    End If
End If
End Sub

Y'aurait il une solution?

En éspérant ne pas abuser de ta gentillesse et de ta patience.
Cordialement
 
Dernière édition:

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut JEJSLY
J'aimerais améliorer un peu cette macro, en changeant la couleur de fond des cellules de la Feuille "Archives" du Classeur "Archives" qui contiennent la même valeur que les variables déclarées, Afin de faciliter la décision de l'utilisateur.
Tu ne peux pas : j'ai suivi ton fonctionnement sans l'analyser. Ton raisonnement n'est pas bon (celui que je lis en interprétant ton code).
Donc, je l'ai modifié
Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim c As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Variant
Dim Soirée As String
Dim Début As Variant
Dim Fin As Variant
'MEI =========================================================
With Workbooks("Console colporteurs.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
' On vérifie si le même enregistrement éxiste déjà dans les archives
' Initialisation des variables booléennes =====================
Workbooks("Colporteursarchives.xlsb").Activate
Sheets("Archives").Activate
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
    Union(c, c.Offset(0, 8), c.Offset(0, 4)).Interior.ColorIndex = xlNone
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) And (c.Offset(0, 4) Like Début) Then
        Union(c, c.Offset(0, 8), c.Offset(0, 4)).Interior.ColorIndex = 3
        Call FormatDate
        If MsgBox("Ce colporteur travaille déjà ce jour là, à cet horaire là!" & _
                 Chr(13) & "Voulez vous quand même sauvegarder l'enregitrement?", _
                 vbExclamation + vbYesNo, "archivage") = vbYes Then
            Call archiver
            Exit Sub
        Else
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Select
            Range("C3").Select
            Exit Sub
        End If
    End If
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) Then
        Union(c, c.Offset(0, 8)).Interior.ColorIndex = 3
        Call FormatDate
        If MsgBox("Ce flyer est déjà distribué ce jour là à cet endroit là!" & _
              Chr(13) & "Voulez vous quand même sauvegarder l'enregitrement?", _
              vbExclamation + vbYesNo, "archivage") = vbYes Then
           Call archiver
           Exit Sub
        Else
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Range("C3").Select
            Exit Sub
        End If
    End If
Next c
End Sub
petite réflexion : si tu donnes un code en disant, il ne fonctionne pas. On peut t'aider à trouver les erreurs d'instruction (ce qui a été fait au départ).

si tu nous donnes l'algorythme de ta macro (ce qu'elle doit réellement faire, son fonctionnement en français) et le code que tu as fait qui ne fonctionne pas comme tu le souhaites. On peut te direles erreurs de codage, mais aussi les erreurs de raisonnement dans l'utilisation du code. Et éventuellement (mais relativement souvent, vu les fous qui se balladent sur ce site) te proposer une autre approche de ton problème.

Avec l'habitude, on arrive à décrypter le problème qui a induit le code. Mais ce n'est qu'une extrapolation en partant du code. Et comme Excel, pour un même problème à des possibilités d'approches pratiquement infinies, si tu n'expliques pas ce que tu veux faire, tu fermes la porte à toutes les approches qui ne colles pas parfaitemant avec la tienne.

un exemple : tu as l'air d'avoir un temps de traitement assez long.
on pourrait par exemple utiliser le filtre auto dans la feuille archive, ou peut-être la méthode Find, ce qui serait plus rapide qu'une boucle si les lignes sont nombreuses. Mais sans savoir le but, c'est impossible (pourquoi utiliser Like au lieu de = ?).

A+
 

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Bonjour Gorfael,
Tes remarques sont très intéressantes! :)

Le fond du problème, c'est que je ne suis qu'un simple bidouilleur, j'ai une toute petite société et j'essaie par moi même d'automatiser certaines taches de gestion et de logistique; car nous n'avons pas les moyens de faire appel à des développeurs.

Ma méthode de travail (développement) n'est donc certainement pas la meilleur, car les résultats recherchés se créent en même temps que les outils.

Mais tu as raison, pour d'autres questions, j'essaierai d'être plus explicite au départ quand aux résultats recherchés. ;)

Pour revenir sur ce cas précis, J'ai:
-Un classeur avec
une feuille principal (CONSOLE) qui est l'interface pour mes utilisateurs, sur cette feuille il y'a plusieurs champs à remplir, listes déroulantes, case à cocher...
une feuille secondaire (Archives) avec une ligne qui se rempli en temps réel avec les données de la console.
-Un deuxième classeur avec une seule feuille (Archives) dans laquelle les nouveaux enregistrements viennent s'archiver.

Le but de cette macro (Sub Vérifdoublon)
est d'interdire certains enregistrement, et d'aider le choix de l'utilisateur en fonction des doublons existants.

un exemple : tu as l'air d'avoir un temps de traitement assez long.
on pourrait par exemple utiliser le filtre auto dans la feuille archive

Donc voila les modifs que j'ai fait:
Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim c As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Variant
Dim Soirée As String
Dim Début As Variant
Dim Fin As Variant
'MEI =========================================================
With Workbooks("Console colporteurs.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
' On vérifie si le même enregistrement éxiste déjà dans les archives
' Initialisation des variables booléennes =====================
'c.Offset(0, 8)=>Colp
'c.Offset(0, 4)=>Début
'c.Offset(0, 5)=>Fin
'c.Offset(0, 6)=>Soirée
'c.Offset(0, 1)=>Lieu
Workbooks("Colporteursarchives.xlsb").Activate
Sheets("Archives").Activate
Range("A1").Select
    Selection.AutoFilter
    ActiveSheet.Range("A65536").End(xlUp).AutoFilter Field:=3, Criteria1:=Jour
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
    Union(c, c.Offset(0, 8), c.Offset(0, 6), c.Offset(0, 5), c.Offset(0, 4), _
    c.Offset(0, 1)).Interior.ColorIndex = xlNone
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) And (c.Offset(0, 4) Like Début) _
    And (c.Offset(0, 1) Like Lieu) And (c.Offset(0, 6) Like Soirée) Then
        Union(c, c.Offset(0, 8), c.Offset(0, 6), c.Offset(0, 4), c.Offset(0, 1)).Interior.ColorIndex = 3
        Call Formatdate
        MsgBox (Colp & " distribut déjà le flyer " & Soirée & " au/à " & Lieu & Chr(13) & _
        "Ce jour là à cet horaire là." & Chr(13) & "Enregistrement non autorisé!")
        Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
     End With
            Exit Sub
    End If
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) And (c.Offset(0, 4) Like Début) Then
        Union(c, c.Offset(0, 8), c.Offset(0, 4)).Interior.ColorIndex = 3
        Call Formatdate
        If MsgBox(Colp & " travaille déjà ce jour là à cet horaire là!" & _
                 Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
                 vbExclamation + vbYesNo, "archivage") = vbYes Then
            Call archiver
            Exit Sub
        Else
         Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
    End With
            Range("A1").Select
            Selection.AutoFilter
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Select
            Range("C3").Select
            Exit Sub
        End If
    End If
    If (c Like Jour) And (c.Offset(0, 1) Like Lieu) And (c.Offset(0, 6) Like Soirée) Then
        Union(c, c.Offset(0, 1), c.Offset(0, 6)).Interior.ColorIndex = 3
        Call Formatdate
        If MsgBox("Le flyer " & Soirée & " est déjà distribué ce jour là, au/à " & Lieu & "!" & _
              Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
              vbExclamation + vbYesNo, "archivage") = vbYes Then
           Call archiver
           Exit Sub
        Else
         Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
    End With
            Range("A1").Select
            Selection.AutoFilter
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Select
            Range("C3").Select
            Exit Sub
        End If
    End If
Next c
    Range("A1").Select
    Selection.AutoFilter
    Call archiver
End Sub
Cela fonctionne, à part deux choses:
-Seules les cellules de la première ligne correspondant aux doublons passent en rouge.
-Lorsqu'il y'a plusieurs enregistrement le même Jour au même Lieu avec la même Soirée, la macro s'arrête sur le premier enregistrement correspondant à un doublon et ne "voit" pas les enregistrements suivant. Petit problème car si un enregistrement avec en plus le même Colp se trouve plus bas, cela devrait être un autre MsgBox. (c'était pas facile à expliquer, dis moi si tu ne comprends pas mon explication.)

ou peut-être la méthode Find
Peut être, je ne sais pas comment cela fonctionne.

(pourquoi utiliser Like au lieu de = ?)
Tout simplement parce que le premier code que j'avais trouvé sur le net, adaptable à mes besoins utilisait Like, et que je ne connais pas la différence entre Like et =. :D

Cordialement
PS: je suis très touché de l'intérêt que tu porte à mes problématiques, merci beaucoup.
 

JEJSLY

XLDnaute Nouveau
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Bonjour tout le monde, Gorfael,

Personne n'aurait une petite idée?
cf:
Donc voila les modifs que j'ai fait:
Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim c As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Variant
Dim Soirée As String
Dim Début As Variant
Dim Fin As Variant
'MEI =========================================================
With Workbooks("Console colporteurs.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
' On vérifie si le même enregistrement éxiste déjà dans les archives
' Initialisation des variables booléennes =====================
'c.Offset(0, 8)=>Colp
'c.Offset(0, 4)=>Début
'c.Offset(0, 5)=>Fin
'c.Offset(0, 6)=>Soirée
'c.Offset(0, 1)=>Lieu
Workbooks("Colporteursarchives.xlsb").Activate
Sheets("Archives").Activate
Range("A1").Select
    Selection.AutoFilter
    ActiveSheet.Range("A65536").End(xlUp).AutoFilter Field:=3, Criteria1:=Jour
For Each c In Range("C2:C65536").SpecialCells(xlCellTypeVisible)
    Union(c, c.Offset(0, 8), c.Offset(0, 6), c.Offset(0, 5), c.Offset(0, 4), _
    c.Offset(0, 1)).Interior.ColorIndex = xlNone
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) And (c.Offset(0, 4) Like Début) _
    And (c.Offset(0, 1) Like Lieu) And (c.Offset(0, 6) Like Soirée) Then
        Union(c, c.Offset(0, 8), c.Offset(0, 6), c.Offset(0, 4), c.Offset(0, 1)).Interior.ColorIndex = 3
        Call Formatdate
        MsgBox (Colp & " distribut déjà le flyer " & Soirée & " au/à " & Lieu & Chr(13) & _
        "Ce jour là à cet horaire là." & Chr(13) & "Enregistrement non autorisé!")
        Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
     End With
            Exit Sub
    End If
    If (c Like Jour) And (c.Offset(0, 8) Like Colp) And (c.Offset(0, 4) Like Début) Then
        Union(c, c.Offset(0, 8), c.Offset(0, 4)).Interior.ColorIndex = 3
        Call Formatdate
        If MsgBox(Colp & " travaille déjà ce jour là à cet horaire là!" & _
                 Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
                 vbExclamation + vbYesNo, "archivage") = vbYes Then
            Call archiver
            Exit Sub
        Else
         Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
    End With
            Range("A1").Select
            Selection.AutoFilter
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Select
            Range("C3").Select
            Exit Sub
        End If
    End If
    If (c Like Jour) And (c.Offset(0, 1) Like Lieu) And (c.Offset(0, 6) Like Soirée) Then
        Union(c, c.Offset(0, 1), c.Offset(0, 6)).Interior.ColorIndex = 3
        Call Formatdate
        If MsgBox("Le flyer " & Soirée & " est déjà distribué ce jour là, au/à " & Lieu & "!" & _
              Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
              vbExclamation + vbYesNo, "archivage") = vbYes Then
           Call archiver
           Exit Sub
        Else
         Cells.Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        Range("A1").Select
        Selection.AutoFilter
    End With
            Range("A1").Select
            Selection.AutoFilter
            Windows("Console colporteurs.xlsm").Activate
            Sheets("CONSOLE").Select
            Range("C3").Select
            Exit Sub
        End If
    End If
Next c
    Range("A1").Select
    Selection.AutoFilter
    Call archiver
End Sub
Cela fonctionne, à part deux choses:
-Seules les cellules de la première ligne correspondant aux doublons passent en rouge.
-Lorsqu'il y'a plusieurs enregistrement le même Jour au même Lieu avec la même Soirée, la macro s'arrête sur le premier enregistrement correspondant à un doublon et ne "voit" pas les enregistrements suivant. Petit problème car si un enregistrement avec en plus le même Colp se trouve plus bas, cela devrait être un autre MsgBox. (c'était pas facile à expliquer, dis moi si tu ne comprends pas mon explication.)

Cordialement
 

Gorfael

XLDnaute Barbatruc
Re : Petit problème vba avec des conditions et la formule "For Each C in"

Salut JEJSLY et le forum
À quoi ça sert que je sois bête si je ne le montre pas ?
On utilise
Code:
ActiveSheet.autofiltermode = false
ActiveSheet.Range("A65536").End(xlUp).AutoFilter Field:=3, Criteria1:=Jour
Mais que sur le critère colonne C = Jour, alors que l'on peut cumuler les critères
Code:
Sub Verifdoublon()
'Déclaration ================================================
Dim Cel As Range
Dim Plage_T As Range
Dim Lieu As String
Dim Colp As String
Dim Jour As Variant
Dim Soirée As String
Dim Début As Variant
Dim Fin As Variant
'MEI =========================================================
With Workbooks("Console colporteurs.xlsm").Sheets("Archives")
    Lieu = .Range("D2")
    Colp = .Range("K2")
    Jour = .Range("C2")
    Soirée = .Range("I2")
    Début = .Range("G2")
    Fin = .Range("H2")
End With
Workbooks("Colporteursarchives.xlsb").Activate
Sheets("Archives").Activate
Set Plage_T = Range([K1], [A65536].End(xlUp))
'Plage de travail A/K, 1/dernière en A **** vérifier que K convient ******
'effacement des couleur =========================
Plage_T.Interior.ColorIndex = xlNone
'Premier test doublons ===========================
ActiveSheet.AutoFilterMode = False
'on désactive le mode filtre auto
Plage_T.AutoFilter Field:=1, Criterial:=Lieu    'Colonne A
Plage_T.AutoFilter Field:=3, Criterial:=Jour    'Colonne C
Plage_T.AutoFilter Field:=4, Criterial:=Début   'Colonne D
Plage_T.AutoFilter Field:=6, Criterial:=Soirée  'Colonne F
Plage_T.AutoFilter Field:=8, Criterial:=Colp    'Colonne H
If Plage_T.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
' le nombre de cellules visibles de la colonne A est supérieure à 1
'(le titre reste visible)
    Intersect(Plage_T, Union(Columns(1), Columns(4), _
                                         Columns(6), Columns(8))).Interior.ColorIndex = 3
    Rows(1).Interior.ColorIndex = xlNone
    Call FormatDate
    MsgBox (Colp & " distribue déjà le flyer " & Soirée & " au/à " & Lieu & Chr(13) & _
        "Ce jour là à cet horaire là." & Chr(13) & "Enregistrement non autorisé!")
    Plage_T.Interior.ColorIndex = xlNone
    Windows("Console colporteurs.xlsm").Activate
    Sheets("CONSOLE").Select
    Range("C3").Select
    Exit Sub
End If
'2ème Test ==============================================
ActiveSheet.AutoFilterMode = False
'on désactive le mode filtre auto
Plage_T.AutoFilter Field:=3, Criterial:=Jour    'Colonne C
Plage_T.AutoFilter Field:=4, Criterial:=Début   'Colonne D
Plage_T.AutoFilter Field:=8, Criterial:=Colp    'Colonne H
    
If Plage_T.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
    Intersect(Plage_T, Union(Columns(3), Columns(4), Columns(8))).Interior.ColorIndex = 3
    Rows(1).Interior.ColorIndex = xlNone
    Call FormatDate
    If MsgBox(Colp & " travaille déjà ce jour là à cet horaire là!" & _
            Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
             vbExclamation + vbYesNo, "archivage") = vbYes Then
        Call archiver
        Plage_T.Interior.ColorIndex = xlNone
        Exit Sub
    Else
        Plage_T.Interior.ColorIndex = xlNone
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
    End If
End If
    
'3ème test ============================================
 ActiveSheet.AutoFilterMode = False
'on désactive le mode filtre auto
Plage_T.AutoFilter Field:=1, Criterial:=Lieu    'Colonne A
Plage_T.AutoFilter Field:=3, Criterial:=Jour    'Colonne C
Plage_T.AutoFilter Field:=6, Criterial:=Soirée  'Colonne F
    
If Plage_T.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
    Intersect(Plage_T, Union(Columns(1), Columns(3), Columns(6))).Interior.ColorIndex = 3
    Rows(1).Interior.ColorIndex = xlNone
    Call FormatDate
    If MsgBox("Le flyer " & Soirée & " est déjà distribué ce jour là, au/à " & Lieu & "!" & _
              Chr(13) & "Voulez vous quand même sauvegarder l'enregistrement?", _
              vbExclamation + vbYesNo, "archivage") = vbYes Then
        Call archiver
        Plage_T.Interior.ColorIndex = xlNone
        Exit Sub
    Else
        Plage_T.Interior.ColorIndex = xlNone
        Windows("Console colporteurs.xlsm").Activate
        Sheets("CONSOLE").Select
        Range("C3").Select
        Exit Sub
        End If
    End If
End If
Range("A1").Select
activeshett.AutoFilterMode = False
Call archiver
End Sub
J'ai testé sur un fichier d'exemple les fonctions de chaque test, mais comme je ne comprend pas tout, j'ai pas envie de partir sur des hypothèses, alors, faut tester :p
Moi, je testerais sur 4 cas :
- 1 qui répond au premier test
- 1 qui répond au second test
- 1 qui répond au troisième test
- 1 qui ne répond à aucun des tois tests
En mode pas-à-pas, en avançant dans le code avec F8

A+
 

Discussions similaires

Statistiques des forums

Discussions
312 105
Messages
2 085 350
Membres
102 870
dernier inscrit
Armisa