Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

Macro de détection de cellules non vides consécutives

  • Initiateur de la discussion Initiateur de la discussion azmodan31
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

A

azmodan31

Guest
Bonjour,

J'ai un fichier pour établir un planning. Ce que je souhaiterai, c'est trouver une macro qui détecte si il y a plus de 7 jours consécutifs de travail pour un employé. J'ai une ligne par employé, qui comprend des périodes de travail et des périodes de repos. Je cherche donc à savoir si j'ai (n'importe où dans le tableau), une série de 7 cellules consécutives qui sont non vides. Un exemple de planning est en pièce jointe.

Merci d'avance à ceux qui voudront bien se pencher sur mon problème🙂
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives

Bonjour,

Tout d'abord merci à tous ceux qui ont pris le temps de me répondre.

Roger2327, ta réponse semble être la plus efficace, mais je t'avoue que ton code est largement au dessus de mes petites compétences en VBA. Je n'arrive pas à le mettre en oeuvre sur mon fichier original. Pourrais-tu me renvoyer ton code en mettant des commentaires? Ca devrait me permettre de corriger mes erreurs 🙂

Merci d'avance
 
Re : Macro de détection de cellules non vides consécutives

Re, Roger2327, job75,

Roger ... redoutable code.

job75, la formule marche bien sur une ligne. Mais si l'employé 2 (au hasard) travaille du 2 au 10 avril, la formule ne permettra pas de le voir dans cette présentation.
C'est aussi pour ça que je proposait une autre présentation du planning.
Bon, d'accord, c'est un peu radical comme modif de philosophie. Mais du coup, tous les traitements deviennent beaucoup plus faciles.
On peut plus facilement gérer l'affichage à l'ouverture, gérer le changement d'année, faire la recherche avec des formules, etc.

On attend le retour de azmodan31.

Abel.

Edit : oups ! Pardon azmodan31, pas rafraichi.
 
Dernière édition:
Re : Macro de détection de cellules non vides consécutives

Re...


Pas rassurant, tout ça... Si le classeur que vous avez fourni correspond à la structure de votre classeur original (ce que j'espère, pour ne pas avoir travaillé pour rien...), le portage du code doit se faire sans problème.
Voyez par exemple le classeur joint : il reprend votre structure, mais j'y ai mis des blocs de quatre semaines au lieu de trois ; j'y ai intercalé des lignes vides ; j'y ai ajouté des employés ; je n'ai pas mis le même nombre d'employés dans chaque bloc et j'ai varié l'ordre des employés dans chaque bloc.
Le code y fonctionne sans aucune modification.

Ceci dit, voici le code agrémenté de quelques commentaires :​
VB:
Sub P7J()
Dim Pers(), HCl(), plgR(), refDate$
Dim i&, j&, k&, p&, d&, VF1 As Boolean, VF2 As Boolean
Dim c&, ep$
Dim d1 As Date, d2 As Date
    With Worksheets("Paramètres")
'Lecture des paramètres.
        On Error GoTo E1
'Liste du personnel. Elle peut comporter des lignes vides, mais pas de doublon.
        Pers = .[A1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row).Value
        On Error GoTo E2
'Liste des mentions ne donnant pas lieu à décompte. Elle peut être vide.
        HCl = .[B1].Resize(.Cells(.Rows.Count, 2).End(xlUp).Row).Value
        On Error GoTo 0
'Intitulé de la ligne portant les dates. Valeur unique.
        refDate = .[C2].Value
    End With
    With Worksheets("Cycle Planning")
'Lecture des données à traiter.
        On Error GoTo E1
'La plage de données à traiter commençant en A1 doit avoir un nombre constant de colonnes.
'Le nombre de lignes est indifférent. Chaque bloc de données peut même avoir un nombre
'différent de lignes. L'ordre des noms des employés peut être différent dans chaque bloc.
        plgR = .[A1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(2, .Columns.Count).End(xlToLeft).Column).Value
        On Error GoTo 0
    End With
'Traitement des données.
'On traite chaque employé tour à tour.
    For p = 2 To UBound(Pers, 1)
        If Not IsEmpty(Pers(p, 1)) Then
            ep = Pers(p, 1)
'Pour un employé donné, on parcourt la plage de données ligne par ligne...
            For d = 1 To UBound(plgR, 1)
'...jusqu'à y trouver une ligne de dates.
                If plgR(d, 1) = refDate Then
'Une ligne de dates étant trouvée on parcourt les lignes suivantes...
                    For i = d + 1 To UBound(plgR, 1)
'...jusqu'à y trouver le nom de l'employé recherché.
                        If plgR(i, 1) = ep Then
'Si le nom de l'employé est trouvé, on parcourt la ligne de données.
                            For j = 2 To UBound(plgR, 2)
'Pour chacune des cellules de cette ligne, on regarde son contenu en utilisant le booléen VF1.
'Si la cellule est vide ou contient une mention ne donnant pas lieu à décompte, on pose VF1=Vrai.
                                VF1 = IsEmpty(plgR(i, j))
                                For k = 2 To UBound(HCl, 1)
                                    VF1 = VF1 Or plgR(i, j) = HCl(k, 1)
                                Next
                                If VF1 Then
'Dans le cas où VF1 est Vrai et où le compteur c d'occurrences successives de "VF1=Faux" excède 6,
'on affiche un message d'alerte.
                                    If c > 6 Then MsgBox ep & " :" & vbLf & "du " & d1 & " au " & d2
'Réinitialisation du booléen VF2 à Faux et du compteur c à zéro.
                                    VF2 = False
                                    c = 0
                                Else
'Dans le cas où VF1 est Faux, on note la date d2 correspondante, et on incrémente le compteur c
'd'occurrences successives de "VF1=Faux".
                                    d2 = plgR(d, j)
                                    c = c + 1
                                    If Not VF2 Then
'Si le booléen VF2 a la valeur Faux, on lui attribue la valeur Vrai et on note la date
'd1 correspondante. (d1 est donc la date de début d'une séquence de cellules telle que
'VF1 garde la valeur Faux.)
                                        VF2 = True
                                        d1 = plgR(d, j)
                                    End If
                                End If
'Passage à la cellule à droite.
                            Next
                        ElseIf plgR(i, 1) = refDate Or IsEmpty(plgR(i, 1)) Then
                            Exit For '...pour passer au bloc de données suivant.
                        End If
                    Next
                End If
'Passage au bloc de données suivant.
            Next
'Tous les blocs de données ayant été explorés, on affiche un dernier message d'alerte si besoin est...
            If c > 6 Then MsgBox ep & " :" & vbLf & "du " & d1 & " au " & d2
'...puis on réinitialise le booléen VF2 à la valeur Faux et le compteur c à zéro...
            VF2 = False
            c = 0
        End If
'...et on passe à l'employé suivant.
    Next
Exit Sub 'Ouf !
'Gestionnaire d'erreurs de lecture des paramètres :
E1:
    MsgBox "Aucun contrôle à faire." 'Parce que la liste du personnel est vide et/ou il
'n'y a pas de données à traiter.
    End
E2:
    ReDim HCl(1 To 1, 1 To 1) '... dans le cas où la iste des mentions ne donnant pas lieu
'à décompte est vide.
    Resume Next
End Sub


Bon courage.


ROGER2327
#6481


Dimanche 8 Pédale 140 (La machine à inspirer l’amour - fête Suprême Tierce)
12 Ventôse An CCXXI, 0,2629h - orme
2013-W09-6T00:37:52Z
 

Pièces jointes

Dernière édition:
Re : Macro de détection de cellules non vides consécutives

Bonjour à tous,
C'est curieux que les formulistes ne se manifestent pas.

Bien que je me considère pas comme formuliste trapu 😕 j'ai commis une tentative par formules/MFC. J'utilise:
  • Deux blocs de colonnes masquées (B:G et AC:AH) qui permettent de rappeler soit la semaine précédente (B:G) soit la semaine suivante (AC:AH) avec une formule de type : =SI(Cnn="";"";Cnn)
  • Une condition rajoutée aux conditions déjà présentes de la MFC (colonnes H:AB) placée en-tête des conditions et avec un point d'arrêt. La condition rajoutée est:
    Code:
     =(MAX(FREQUENCE(SI((DECALER(H3;0;-6;1;13)<>"") * (GAUCHE(DECALER(H3;0;-6;1;13);4) <>"Astr")=1;COLONNE(DECALER(H3;0;-6;1;13));"") ;SI(NON((DECALER(H3;0;-6;1;13)<>"")*(GAUCHE(DECALER(H3;0;-6;1;13);4)<>"Astr")=1); COLONNE(DECALER(H3;0;-6;1;13));""))))>=7
nb: Les jours ayant un code d'astreinte sont considérés comme étant vides.
nb: Un jour faisant partie d'un bloc travaillé de 7 jours ou plus est de format "police orange sur fond noir".
nb: les colonnes masquées permettent de tenir compte des jours de la semaine de fin du bloc de 3 semaines antérieures et de la semaine de début du bloc de 3 semaines postérieures.
Et tout ça, si je me suis pas planté 😱
 

Pièces jointes

Dernière édition:
Re : Macro de détection de cellules non vides consécutives

Bonjour le fil, le forum,

Compte tenu de ceci :

job75, la formule marche bien sur une ligne. Mais si l'employé 2 (au hasard) travaille du 2 au 10 avril, la formule ne permettra pas de le voir dans cette présentation.

j'ai ajouté des SOMMEPROD dans la formule en AR1 :

Code:
=SOMMEPROD(ESTTEXTE(B1:P1)*(GAUCHE(B1:P1;4)<>"Astr")*ESTTEXTE(C1:Q1)*(GAUCHE(C1:Q1;4)<>"Astr")*ESTTEXTE(D1:R1)*(GAUCHE(D1:R1;4)<>"Astr")*ESTTEXTE(E1:S1)*(GAUCHE(E1:S1;4)<>"Astr")*ESTTEXTE(F1:T1)*(GAUCHE(F1:T1;4)<>"Astr")*ESTTEXTE(G1:U1)*(GAUCHE(G1:U1;4)<>"Astr")*ESTTEXTE(H1:V1)*(GAUCHE(H1:V1;4)<>"Astr"))+(SOMMEPROD(ESTTEXTE(Q1:V1)*(GAUCHE(Q1:V1;4)<>"Astr"))=6)*ESTTEXTE(B20)*(GAUCHE(B20;4)<>"Astr")+(SOMMEPROD(ESTTEXTE(R1:V1)*(GAUCHE(R1:V1;4)<>"Astr"))=5)*(SOMMEPROD(ESTTEXTE(B20:C20)*(GAUCHE(B20:C20;4)<>"Astr"))=2)+(SOMMEPROD(ESTTEXTE(S1:V1)*(GAUCHE(S1:V1;4)<>"Astr"))=4)*(SOMMEPROD(ESTTEXTE(B20:D20)*(GAUCHE(B20:D20;4)<>"Astr"))=3)+(SOMMEPROD(ESTTEXTE(T1:V1)*(GAUCHE(T1:V1;4)<>"Astr"))=3)*(SOMMEPROD(ESTTEXTE(B20:E20)*(GAUCHE(B20:E20;4)<>"Astr"))=4)+(SOMMEPROD(ESTTEXTE(U1:V1)*(GAUCHE(U1:V1;4)<>"Astr"))=2)*(SOMMEPROD(ESTTEXTE(B20:F20)*(GAUCHE(B20:F20;4)<>"Astr"))=5)+ESTTEXTE(V1)*(GAUCHE(V1;4)<>"Astr")*(SOMMEPROD(ESTTEXTE(B20:G20)*(GAUCHE(B20:G20;4)<>"Astr"))=6)
Voyez les 7 "aa" en S4:V4 et B23: D23.

Pour que la formule puisse être tirée vers le bas il faut que les employés se succèdent toujours dans le même ordre.

Fichier (2).

A+
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives


Merci pour les commentaires, je comprend mieux le code maintenant. Cependant je n'arrive toujours pas à le faire fonctionner sur mon fichier d'origine, qui me semble-t-il présente la même structure que celui envoyé au départ. Lorsque je lance la macro il n'y a tout simplement rien qui se passe..... Au cas où je me permet de mettre l'original en pièce jointe, j'ai juste remplacé les noms des employés, j'ai ajouté l'onglet paramètres, et la macro que tu as écrit. Si tu trouve pourquoi ça ne fonctionne pas sur mon fichier ça m’intéresse.

Merci encore à tous ceux qui ont pris le temps de répondre 🙂
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives

Bonjour azmodan31,

En l'absence de Roger (il ne m'en voudra pas) j'ai adapté votre fichier :

- les données de la feuille "Paramètres" doivent bien sûr correspondre aux données de la première feuille

- dans cette première feuille il y a des données après la colonne V, donc dans la macro remplacer :

Code:
plgR = .[A1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(2, .Columns.Count).End(xlToLeft).Column).Value
par :

Code:
plgR = .[A1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row, .[V2].Column).Value
A+
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives

Bonjour à tous.


À azmodan31 :
La structure du fichier réel est différente de celle du fichier de test sur au moins deux points :
  • La colonne A de l'onglet Cycle Planning contient d'autres données que l'intitulé des lignes de dates et les noms des employés.
  • La ligne 2 de l'onglet Cycle Planning contient d'autres données que l'intitulé des lignes de dates et que des dates.

Conséquence : la définition dynamique de la plage de données par
VB:
    With Worksheets("Cycle Planning")
        plgR = .[A1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(2, .Columns.Count).End(xlToLeft).Column).Value
    End With
n'est plus pertinente.

Remède : j'ai nommé DATA la plage de données 'Cycle Planning'!$A$1:$V$80 et remplacé le code ci-dessus par​
VB:
    plgR = Worksheets("Cycle Planning").Range("DATA").Value

Ceci fait, la procédure fonctionne... ...et ne renvoie rien.
C'est heureux car
  • l’intitulé de la colonne Ligne de dates figurant en C2 de l'onglet Paramètres ne se retrouve pas dans la colonne A de Cycle Planning ;
  • aucun des noms figurant dans la colonne Personnel de l'onglet Paramètres ne figure dans l'onglet Cycle Planning.

Remède (évident ?) : Rétablir la cohérence entre les données et les paramètres. Les modifications effectuées sont hachurées en vert clair/vert foncé dans le classeur joint.


Bonne journée.


ROGER2327
#6482


Dimanche 8 Pédale 140 (La machine à inspirer l’amour - fête Suprême Tierce)
12 Ventôse An CCXXI, 4,2180h - orme
2013-W09-6T10:07:24Z
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives

Il y a des moments dans la vie où on se sent aussi performant qu'une mouche collée à un chewing-gum.....

Désolé pour les erreurs qui venaient de moi 😱

Merci pour le temps passé, tout fonctionne parfaitement grâce aux explications de Roger2327 et à la connexion effectuée entre mes deux derniers neurones.....

En tout cas ça me sort une belle épine du pied 🙂 merci à tous et particulièrement à Roger
 
Re : Macro de détection de cellules non vides consécutives

Re...


Il y a des moments dans la vie où on se sent aussi performant qu'une mouche collée à un chewing-gum.....

Désolé pour les erreurs qui venaient de moi 😱

(...)
Ben oui ! Il y a des jours comme ça où on ne devrait pas se lever...

Si le code précédent vous convient, celui du classeur joint vous intéressera peut-être. Au lieu que les messages d'alerte soient affichés un à un dans une boîte de message, ils sont affichés tous ensemble dans une zone de texte façon post It™.​


ROGER2327
#6483


Lundi 9 Pédale 140 (Saint Remezy, évêque in partibus - fête Suprême Quarte)
13 Ventôse An CCXXI, 0,5963h - fumeterre
2013-W09-7T01:25:52Z
 

Pièces jointes

Re : Macro de détection de cellules non vides consécutives

Bonjour à tous.

Suite...

... à un message d' azmodan31 me demandant de réutiliser l'affichage façon post It™ dans d'autres procédures, je poursuis la discussion.

Au lieu de récrire la procédure d'affichage dans chaque procédure où elle sera utile, je suggère d'utiliser une fonction d'affichage qu'on appellera autant qu'il sera nécessaire.

Je propose cette fonction :​
VB:
Function Alerte$(Message$, Gauche!, Haut!, Optional Activer As Boolean = True, Optional Inclinaison!, Optional CouleurFond& = 16777215, Optional CouleurTexte&, Optional Graisse As Boolean, Optional Transparence#)
    If Len(Message) Then
'Affichage des alertes dans une zone de texte.
        With ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, Gauche, Haut, 20, 20)
            With .TextFrame
                With .Characters
                    .Text = Message
                    With .Font
                        .Color = CouleurTexte
                        .Bold = Graisse
                    End With
                End With
                .AutoSize = msoAutoSizeShapeToFitText
            End With
            With .Fill
                .ForeColor.RGB = CouleurFond
                .Transparency = Transparence
            End With
            .IncrementRotation -Inclinaison
            If Activer Then .Select
            Alerte = .Name
        End With
    End If
End Function
Comme on le voit,

Alerte$(Message$, Gauche!, Haut!, [Activer As Boolean = True], [Inclinaison!], [CouleurFond& = 16777215], [CouleurTexte&], [Graisse As Boolean], [Transparence#])


prend trois paramètres obligatoires :


  1. Message$____Texte à afficher.
  2. Gauche!_____Décalage depuis le bord gauche de la fenêtre.
  3. Haut!_______Décalage depuis le bord haut de la fenêtre.

et jusqu'à six paramètres facultatifs :


  • Activer As Boolean = True_VRAI (par défaut) pour activer la zone de texte (ce qui permet, après lecture, de la supprimer par une simple pression sur la touche Supprimer) ; FAUX pour obtenir une zone de texte "permanente".
  • Inclinaison!______________Inclinaison de la zone de texte (0 par défaut).
  • CouleurFond& = 16777215___Couleur du fond de la zone de texte (Blanc par défaut).
  • CouleurTexte&_____________Couleur du texte de la zone de texte (Noir par défaut).
  • Graisse As Boolean________FAUX par défaut ; mettre VRAI pour afficher le texte en gras.
  • Transparence#_____________Couleur d'écriture du texte (Noir par défaut).


La fonction renvoie une chaîne de caractères :
  • "" (Chaîne de longueur nulle) s'il n'y a rien à afficher (i.e. si le paramètre Message$ est lui-même une chaîne de longueur nulle).
  • "Nom" de la zone de texte affichée si le paramètre Message$ n'est pas une chaîne de longueur nulle.


Utilisation :


Dans la procédure où la fonction doit être utilisée, on construira une chaîne de caractères à afficher :
VB:
Sub toto()
Dim msg$
'Code...
msg = "Première partie du code : exécuté"
'Code...
msg = msg & vblf & "Deuxième partie du code : exécuté"
'Code...
msg = msg & vblf & "etc."
'Code...
puis on appellera la fonction
VB:
'Code...
Call Alerte(msg, 20, 45)
'Code...
End Sub
Le message sera affiché dans une zone de texte auto-dimensionnée.


Indications complémentaires :


Dans le code du classeur joint au message #26 on trouve :
VB:
'...
    If Len(msg) Then
'Affichage des alertes dans une zone de texte.
        With ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, 90, 45, 240, 20)
            .TextFrame.Characters.Text = vbLf & Left$(msg, Len(msg) - 1)
            .TextFrame2.AutoSize = msoAutoSizeShapeToFitText
            .IncrementRotation -5
            With .Fill
                .ForeColor.RGB = RGB(255, 255, 64)
                .Transparency = 0.12
            End With
            .Select
        End With
    End If
'...

En utilisant la fonction externe, on remplacera cette partie du code par
VB:
    If Len(msg) Then msg = vbLf & Left$(msg, Len(msg) - 1)
'Affichage des alertes dans une zone de texte.
    Call Alerte(Message:=msg, Gauche:=90, Haut:=45, Activer:=True, Inclinaison:=5, CouleurFond:=RGB(255, 255, 64), CouleurTexte:=0, Graisse:=False, Transparence:=0.12)
Mutatis mutandis, ce dernier code pourra être utilisé dans d'autres procédures.

Remarque :
VB:
    Call Alerte(Message:=msg, Gauche:=90, Haut:=45, Activer:=True, Inclinaison:=5, CouleurFond:=RGB(255, 255, 64), CouleurTexte:=0, Graisse:=False, Transparence:=0.12)
'peut s'écrire aussi:
    Call Alerte(msg, 90, 45, True, 5, RGB(255, 255, 64), 0, False, 0.12)
'ou :
    Call Alerte(msg, 90, 45, , 5, RGB(255, 255, 64), , , 0.12)
'ou :
    Alerte msg, 90, 45, , 5, RGB(255, 255, 64), , , 0.12

'En écrivant seulement...
    Alerte msg, 90, 45
'...on aura une zone de texte à fond blanc, activée, sans rotation ni transparence.

'Si on veut récupérer le nom de la zone de texte, on écrira :
Dim Nom_de_la_zone$ 'dans la déclaration des variables et :
    Nom_de_la_zone = Alerte(Message:=msg, Gauche:=90, Haut:=45, Activer:=True, Inclinaison:=5, CouleurFond:=RGB(255, 255, 64), CouleurTexte:=0, Graisse:=False, Transparence:=0.12)


Bon amusement...​



ROGER2327
#6486


Mardi 10 Pédale 140 (Nativité de Saint Tancrède, jeune homme - fête Suprême Quarte)
14 Ventôse An CCXXI, 6,2565h - vélar
2013-W10-1T15:00:56Z


P.S. : voir le message #32 pour une mise à jour.
 
Dernière édition:
Re : Macro de détection de cellules non vides consécutives

Merci beaucoup Roger,

Je fais chauffer mon neurone et je fais un retour dès que possible 😉

Azmo
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD
Assurez vous de marquer un message comme solution pour une meilleure transparence.

Discussions similaires

Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…