Copier une ligne entière dans un onglet en fonction de mot clé

Bonjour,

Dans mon message précédent, je pensais que la macro répondait à la totalité de mes problèmes. Or je m'aperçois qu'elle ne sélectionne pas les lignes où dans la colonne K il y a deux noms. Or le tableau final que l'on retrouve dans l'onglet filtre des noms devrait comporter quand je sélectionne Mr X mais aussi les lignes où il est en commun avec Mr B. De plus la macro actuelle quand je la lance sur mon fichier original qui comprend une quarantaine d'onglet de recherche, elle est très longue, je me dis alors qu'il serait plus judicieux de rechercher que les lignes de Mr X (soit la colonne K y compris quand il est en commun avec Mr B) ou il reste encore des actions à réaliser soit une case rouge dans le tableau qui va de la colonne M à X.

Est il possible au final que dans filtre des noms, ce tableau apparaisse avec des bordures comme dans l'exemple du fichier en sachant que chaque responsable a un tableau avec un nombre de ligne différente.

Merci pour votre aide

13copie-p1-copie.xlsm (210.65 Ko)

Salut cpin,

impatiente, va!

Je ne m'explique toujours pas la cause de la lenteur excessive...

Private Sub Worksheet_Change(ByVal Target As Range)
'
Dim tData
Dim sData As String, sNom As String, sSheet As String
'
Application.EnableEvents = False
Application.ScreenUpdating = False
'
If Not Intersect(Target, Range("D6")) Is Nothing Then               'si changement en [D6]
    sNom = Target                                                  'sData = nom
    iRow = Range("D" & Rows.Count).End(xlUp).Row                    'fond de la colonne [C] pour nettoyage...
    If iRow > 24 Then                                               '... si c'est déjà rempli
        Range("A25:F" & iRow).ClearContents
        Range("G25:R" & iRow).Interior.Color = xlNone
        Range("A25:R" & iRow).Borders.LineStyle = xlNone
    End If
    iRow = 24
    'préparation pour nouvel affichage
    For x = 1 To 3
        sSheet = Choose(x, "P1", "P2", "P3")                        'choix des feuilles à scanner...
        With Worksheets(sSheet)
            For y = 4 To .Range("K" & Rows.Count).End(xlUp).Row     '... jusqu'au fond de la colonne [K]
                If Right(.Cells(y, 11), 1) <> Chr(10) Then sData = .Cells(y, 11) & Chr(10)
                tData = Split(sData, Chr(10))
                If InStr(sData, sNom) > 0 Then                      'si cellule contient sNom
                    For k = 13 To 24
                        If .Cells(y, k).Interior.Color = RGB(255, 0, 0) Then
                            iRow = iRow + 1                                 'ligne d'affichage
                            Cells(iRow, 3) = sSheet & "  -  " & y           'nom feuille + ligne
                            Cells(iRow, 4) = sNom                           'nom
                            For Z = 5 To 6
                                If .Range(IIf(Z = 5, "D", "J") & y).MergeCells Then
                                    Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).MergeArea.Cells(1, 1)
                                Else
                                    Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).Value      'risque
                                End If
                            Next
                            For Z = 1 To 12                                 'couleurs
                                Cells(iRow, 6 + Z).Interior.Color = .Cells(y, 12 + Z).Interior.Color
                            Next
                            If UBound(tData) > 1 Then
                                For Z = 0 To UBound(tData) - 1
                                    If tData(Z) <> sNom Then
                                        iRow = iRow + 1
                                        Cells(iRow, 4) = tData(Z)
                                    End If
                                Next
                            End If
                            Exit For
                        End If
                    Next
                End If
            Next
        End With
    Next
    iRow = Range("D" & Rows.Count).End(xlUp).Row
    If iRow > 24 Then Range("A25:R" & iRow).Borders.LineStyle = xlContinuous
End If
'
Application.ScreenUpdating = True
Application.EnableEvents = True
'
End Sub

A+

12copie-p1-copie.xlsm (215.63 Ko)

Bonjour,

C'est tout simplement le grand nombre d'appels de la fonction "Somcouleur()" qui prend du temps car comme demandée Volatile, les calculs sont prioritaires sur l'exécution de la procédure événementielle "Worksheet_Change()" donc, avant même d'effectuer la recherche, toutes les cellules appelant cette fonction sont calculées ensuite, il faudrait optimiser la recherche peut être avec Find() ou un filtrage car le code de ces fonctions et méthodes est compilé donc bien plus rapide.

Pour s'en rendre compte, il suffit de mettre en commentaire la fonction puis modifier la valeur pour exécuter la recherche.

Bonjour Theze,

merci pour l'explication.

Effectivement, sans cette f... fonction, les résultats sont instantanés.

Il faudrait que cpin nous explique le pourquoi du comment de ces calculs couleurs pour trouver un procédé plus efficace.

A+

Hello Curulis57,

Oui, car il se pourrai qu'un simple appel de la fonction sur l'activation de la feuille soit suffisant ce qui éviterai ce ralentissement permanent !

Bonsoir,

Je vous remercie énormément pour votre travail qui vous ne pouvez pas imaginer comment vous me faciliter le mien!!!! Moi je débute en vba et j'essaie en prenant à droite et à gauche de comprendre et de mettre en oeuvre de simple fonction.

En fait cette fonction me permet de calculer instantanément l'état de mon tableau de bord : je m'explique. En fait j'ai un ensemble de processus avec un ensemble d'actions intégré à ce processus et j'ai besoin de savoir combien d'actions ont été réalisées au 1er trimestre ensuite au 2nd puis au 3ème et en fin d'année sur le nombre d'actions prévues sur le 1er trimestre, 2nd, 3ème et enfin année. Comme je débute j'ai cherché un peu partout et je suis arrivée à ce travail là je reconnais qu'à priori ce n'est pas le sommet mais quand vous connaissez très peu vous trouvez cela formidable. Peut être que vous pouvez l'améliorer mais moi pour l'instant je n'en ai pas les capacités au vue de mes connaissances en vba. J'espère que j'ai été claire dans mon explication

Je vous laisse le soin de le modifier si vous pensez que cela peut améliorer la seconde programmation . Merci pour votre énorme implication. Avez vous besoin d'un nouveau fichier ?

Je reconnais que je suis impatiente .....

Bonsoir

En copiant collant ce programme qui pour moi est exceptionnel... J'aimerai tout de même le comprendre : est il possible d'avoir une explication en plus des explications déjà existante. Sans trop abuser merci

Salut cpin,

explications supplémentaires du code...

Tu as bien demandé que ne soient affichées que les actions non-réalisées!?

Private Sub Worksheet_Change(ByVal Target As Range)
'
Dim tData
Dim sData As String, sNom As String, sSheet As String
'
Application.EnableEvents = False
Application.ScreenUpdating = False
'
If Not Intersect(Target, Range("D6")) Is Nothing Then               'si changement en [D6]
    sNom = Target                                                   'sNom = nom
    iRow = Range("D" & Rows.Count).End(xlUp).Row                    'fond de la colonne [C] pour nettoyage...
    If iRow > 24 Then                                               '... si c'est déjà rempli, on efface tout...
        Range("A25:F" & iRow).ClearContents                         '...texte, couleurs et bordures
        Range("G25:R" & iRow).Interior.Color = xlNone
        Range("A25:R" & iRow).Borders.LineStyle = xlNone
    End If
    iRow = 24                                                       'préparation pour nouvel affichage
    For x = 1 To 3
        sSheet = Choose(x, "P1", "P2", "P3")                        'choix des feuilles à scanner...
        With Worksheets(sSheet)
            For y = 4 To .Range("K" & Rows.Count).End(xlUp).Row     '... de la ligne 4 jusqu'au fond de la colonne [K]
                If Right(.Cells(y, 11), 1) <> Chr(10) Then sData = .Cells(y, 11) & Chr(10)  'j'ajoute un saut de ligne...
                tData = Split(sData, Chr(10))                       '...et je splitte le nom sur base de ce saut de ligne
                If InStr(sData, sNom) > 0 Then                      'si cellule contient sNom
                    For k = 13 To 24
                        If .Cells(y, k).Interior.Color = RGB(255, 0, 0) Then        'si il y a une action en rouge en 2018...
                            iRow = iRow + 1                                 'ligne d'affichage
                            Cells(iRow, 3) = sSheet & "  -  " & y           'nom feuille + ligne
                            Cells(iRow, 4) = sNom                           'nom
                            For Z = 5 To 6                          'si cellule en [D] ou [J] fusionnées, recherche de la valeur
                                If .Range(IIf(Z = 5, "D", "J") & y).MergeCells Then
                                    Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).MergeArea.Cells(1, 1)
                                Else
                                    Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).Value      'risque
                                End If
                            Next
                            For Z = 1 To 12                                 'couleurs
                                Cells(iRow, 6 + Z).Interior.Color = .Cells(y, 12 + Z).Interior.Color
                            Next
                            If UBound(tData) > 1 Then               'si le SPLIT révèle plusieurs valeurs = plusieurs noms
                                For Z = 0 To UBound(tData) - 1
                                    If tData(Z) <> sNom Then        'copie des autres noms
                                        iRow = iRow + 1
                                        Cells(iRow, 4) = tData(Z)
                                    End If
                                Next
                            End If
                            Exit For
                        End If
                    Next
                End If
            Next
        End With
    Next
    iRow = Range("D" & Rows.Count).End(xlUp).Row                    'valeur de fond de colonne [D]...
    If iRow > 24 Then Range("A25:R" & iRow).Borders.LineStyle = xlContinuous    '...pour dessiner bordures
End If
'
Application.ScreenUpdating = True
Application.EnableEvents = True
'
End Sub

Petite question : en 2020, qu'as-tu prévu pour ton tableau?

A+

Bonjour

Je te remercie pour tes explications mais je n'en suis pas encore à ce stade de vba. Pour 2020, il faut voir......

Sans trop insister, pensez vous que l'on peut modifier le premier programme somcouleur pour que le deuxième programme s’exécute plus rapidement : faut il enlever application.volatile ou comment puis je faire différemment ?

Si vous pouviez m'aiguiller pour que je puisse le faire seule, j'avoue que l'explication de theze est au dessus de mes compétences mais je peux essayer : faut il que j'utilise find pour compter le nombre de cellules rouges ? et faire des calculs sur toutes les lignes de façon automatiques ?

merci pour ton aide

Salut cpin,

voilà ma version afin de fuidifier ta recherche.

Toutes les formules sont effacées, la fonction de calcul-couleur bannie.

Tu trouveras la procédure suivante dans le module 'ThisWorkbook', valable donc pour toutes les feuilles 'P1,"P.."

Il te suffit de cliquer sur les cellules couleur (1er clic = vert, 2e rouge, 3e blanc), chacune étant notée 1,2 ou 3 selon sa couleur, les calculs étant exécutés immédiatement.

Le filtrage des noms n'étant plus pollué par la fonction-couleurs, les résultats s'affichent très vite.

Tout ceci ne fonctionnera qu'avec ce fichier, ayant dû valider chaque cellule-couleur pour le nouveau système.

J'ai cru lire un jour que tu devais filtrer 40 feuilles?! Juste?

Il faudrait dans ce cas revoir la macro de filtrage... A toi de me dire...

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
'
Application.ScreenUpdating = False
'
If Left(Sh.Name, 1) = "P" Then
    iRow = Range("K" & Rows.Count).End(xlUp).Row
    If Not Intersect(Target, Range("M4:AJ" & iRow)) Is Nothing And Range("K" & Target.Row) <> "" Then
        iTRow = Target.Row
        iTCol = Target.Column
        'Couleurs
        Target = IIf(Target = 1, 2, IIf(Target = 2, 3, 1))
        Target.Interior.Color = Choose(Target, RGB(0, 180, 80), RGB(255, 0, 0), xlNone)
        Target.Font.Color = Choose(Target, RGB(0, 180, 80), RGB(255, 0, 0), xlNone)
        'Calcul de pourcentage
        iCol = IIf(iTCol Mod 3 = 0, iTCol, iTCol + (3 - iTCol Mod 3))
        sCol1 = Split(Columns(iCol - 2).Address(ColumnAbsolute:=False), ":")(1)
        sCol2 = Split(Columns(IIf(iCol < 25, 38, 52) + Cells(3, iCol)).Address(ColumnAbsolute:=False), ":")(1)
        Range(sCol2 & iTRow).Value = WorksheetFunction.CountIf(Range(sCol1 & iTRow).Resize(1, 3), "1")
        Range(sCol2 & iTRow).Offset(0, 1).Value = WorksheetFunction.CountIf(Range(sCol1 & iTRow).Resize(1, 3), "2")
        Range(sCol2 & iTRow).Offset(0, 2).Value = 0
        If WorksheetFunction.Sum(Range(sCol2 & iTRow).Resize(1, 2)) > 0 Then
            Range(sCol2 & iTRow).Offset(0, 2).Value = Range(sCol2 & iTRow).Value / WorksheetFunction.Sum(Range(sCol2 & iTRow).Resize(1, 2))
        Else
            Range(sCol2 & iTRow).Resize(1, 3) = ""
        End If
        For x = IIf(iCol < 25, 41, 55) To IIf(iCol < 25, 50, 64) Step 3
            iTotal = iTotal + CInt(Cells(iTRow, x)) + CInt(Cells(iTRow, x + 1))
            iTot = iTot + Cells(iTRow, x)
        Next
        Range(IIf(iCol < 25, "BA", "BO") & iTRow).Value = 0
        If iTotal > 0 Then Range(IIf(iCol < 25, "BA", "BO") & iTRow).Value = iTot / iTotal
        '
        Range("K" & Target.Row).Select
    End If
End If
'
Application.ScreenUpdating = True
'
End Sub

A tester, comme on dit...

A+

9copie-p1-copie.xlsm (164.52 Ko)

Salut tout le monde,

petites améliorations sans réelle importance autre que visuelle...

A+

12filtre.xlsm (163.93 Ko)

Bonjour

C'est un travail exceptionnel, félicitation et encore merci : je vais le tester avec mes 45 onglets. Je vous tiens au courant

Encore merci !!!!!

re bonjour,

Pouvez vous m'expliquer votre programme qui maintenant s’exécute avec une vitesse déconcertante afin que je puisse progresser. Je vais copier coller sur mon fichier réel et je vous tiens au courant.

Encore mille merci

Salut cpin,

copier-coller? Les calculs-statistiques ne fonctionneront que si tu valides chaque cellule-couleur en 'P...' en cliquant dessus pour avoir la bonne couleur!

Je redemande : dois-tu filtrer plus que les 'P1', 'P2' et 'P3' que tu as présenté jusqu'ici?

A+

Salut

Oui en fait je filtre de P1 à P17 en sachant que j'ai un P13A et un P13B et que P17 va de P17A à P17H sinon les autres c'est classique P1 P2 P3 P4 etc

En fait je compte copier coller ton programme comme tu me le dis dans les feuilles correspondantes : Dis moi si je dois faire plus

merci de ton aide

A+

Le code actuel ne filtrera que 'P1', 'P2' et 'P3'. C'est facile de changer cela pour prendre les autres en compte mais le temps de traitement risque d'en pâtir.

As-tu d'autres feuilles, n'ayant rien à voir avec le filtrage, dont le nom commence par "P"? Si oui, trouve un autre nom évocateur pour ce(s)(tte) feuille(s).

Donc :

  • ne passe pas ton temps à recalibrer chaque cellule-couleur : je vais écrire une macro pour ce faire ;
  • je vais réécrire la macro de filtrage pour que ça vole.

Si tu as d'autres précisions importantes, idées, demandes ou autre, transmets maintenant, stp!

A+

Salut,

rectification, ça ne saurait voler plus vite du fait de toutes ces cellules fusionnées... du moins dans l'état actuel de mes connaissances!

La macro de filtrage est corrigée selon la situation réelle décrite et si d'autres feuilles commençant par "P" et n'ayant rien à voir avec le filtrage ont bien été renommées.

Macro à copier-coller dans le module de 'Filtre'.

Précision : j'ose croire et espérer que TOUTES les feuilles 'P...' ont STRICTEMENT la même structure!

Private Sub Worksheet_Change(ByVal Target As Range)
'
Dim tData
Dim sData As String, sNom As String, sSheet As String
'
Application.EnableEvents = False
Application.ScreenUpdating = False
'
If Not Intersect(Target, Range("D6")) Is Nothing Then               'si changement en [D6]
    sNom = Target                                                  'sData = nom
    iRow = Range("D" & Rows.Count).End(xlUp).Row                    'fond de la colonne [C] pour nettoyage...
    If iRow > 24 Then                                               '... si c'est déjà rempli
        Range("A25:F" & iRow).ClearContents
        Range("G25:R" & iRow).Interior.Color = xlNone
        Range("A25:R" & iRow).Borders.LineStyle = xlNone
    End If
    iRow = 24
    'préparation pour nouvel affichage
    For x = 1 To Sheets.Count
        If Left(Sheets(x).Name, 1) = "P" Then
            sSheet = Sheets(x).Name                                     'choix des feuilles à scanner...
            With Worksheets(sSheet)
                For y = 4 To .Range("K" & Rows.Count).End(xlUp).Row     '... jusqu'au fond de la colonne [K]
                    If Right(.Cells(y, 11), 1) <> Chr(10) Then sData = .Cells(y, 11) & Chr(10)
                    tData = Split(sData, Chr(10))
                    If InStr(sData, sNom) > 0 Then                      'si cellule contient sNom
                        For k = 13 To 24
                            If .Cells(y, k).Interior.Color = RGB(255, 0, 0) Then
                                iRow = iRow + 1                                 'ligne d'affichage
                                Cells(iRow, 3) = sSheet & "  -  " & y           'nom feuille + ligne
                                Cells(iRow, 4) = sNom                           'nom
                                For Z = 5 To 6
                                    If .Range(IIf(Z = 5, "D", "J") & y).MergeCells Then
                                        Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).MergeArea.Cells(1, 1)
                                    Else
                                        Cells(iRow, Z) = .Range(IIf(Z = 5, "D", "J") & y).Value      'risque
                                    End If
                                Next
                                For Z = 1 To 12                                 'couleurs
                                    Cells(iRow, 6 + Z).Interior.Color = .Cells(y, 12 + Z).Interior.Color
                                Next
                                If UBound(tData) > 1 Then
                                    For Z = 0 To UBound(tData) - 1
                                        If tData(Z) <> sNom Then
                                            iRow = iRow + 1
                                            Cells(iRow, 4) = tData(Z)
                                        End If
                                    Next
                                End If
                                Exit For
                            End If
                        Next
                    End If
                Next
            End With
        End If
    Next
    iRow = Range("D" & Rows.Count).End(xlUp).Row
    If iRow > 24 Then Range("C25:R" & iRow).Borders.LineStyle = xlContinuous
End If
'
Application.ScreenUpdating = True
Application.EnableEvents = True
'
End Sub

La suite plus tard sauf si tu as décidé de procéder manuellement (mais j'en doute!) au calibrage couleur de chacune de tes cellules-couleur...

A+

Hello !

Bel exemple de mastur......ion intellectuelle qui fait du bien ! j'aime beaucoup les exercices de ce genre.

Mais pour la maintenance, revenons un peu sur terre ... et sans délirer !

C'est quoi le besoin ?

Qu'est-ce qui justifie 45 onglets ?

Ne doit-on pas :

  • faire une base de données ?
  • faire un filtre élaboré ?
  • un TCD ?
  • des MFC ?

Salut Steelson,

puisque les infos arrivent au compte-goutte, d'abord le plaisir de coder! Pas très long!

Quand nous aurons, peut-être..., le fichier complet et les précisions quant à l'évolution annuelle des données, on pourra vraiment décider.

Quelques lignes en plus, mon Dieu...

A+

Re bonjour

Le fichier que j'ai copié est un extrait de mon fichier il s'agit des trois premier onglets que j'ai anonymisé. Voulez vous le fichier complet qu'il faut que j'anonymise en totalité si cela peut vous aider, les trois premiers onglets représentent un tiers du fichier complet.

Si besoin je peux le faire si çà doit vous faciliter le travail

A+

Rechercher des sujets similaires à "copier ligne entiere onglet fonction mot cle"