Filtrer et combiner sans doublons
Bonjour,
Dans le tableau de suivi en pièce jointe, je souhaite qu'après filtrage des données, les cellules filtrées soient regroupées en une seule (A2 - Region / B2 - Secteur / C2 - Site) et sans doublons.
Je pêche sur la partie "sans doublons", le reste du code semble fonctionner mais je ne comprend pas bien comment intégrer ce paramètre dans le code
Après plusieurs recherches infructueuses, je me tourne vers vous pour de l'aide si possible.
Pourriez-vous m'aider sur ce point s'il vous plaît ?
Merci d'avance
Bonjour :)
Je te propose mon code, il reste une question à éclaircir. Comment compte tu gérer un cas où l'un des trois paramètres (région, secteur ou site) est vide et même question dans le cas où les trois paramètres sont vides ?
De manière provisoire je spécifie quand l'un des paramètres est vide par la mention "VIDE"
EDIT : je me disais, pourquoi masquer des lignes manuellement ? Il est tout à fait possible d'intégrer la condition au code pour ne pas les prendres en compte !
EDIT de 15:09 : MAJ du code
EDIT de 16:14 : J'avais mis le mauvais fichier en PJ
Option Explicit
Private Sub Worksheet_Calculate()
Dim F As Worksheet
Dim i As Long, j As Long, cpt As Long
Dim Plage As Range
Dim TBL()
Dim DICO As Object, Val As Object
Dim tempo As String
Set F = ThisWorkbook.Worksheets("BD")
Set DICO = CreateObject("Scripting.Dictionary")
Set Plage = DimBD(F, 5, "A", 3)
If Plage Is Nothing Then Exit Sub
cpt = 0
For i = 1 To Plage.Rows.Count
tempo = ""
For j = 1 To Plage.Columns.Count
If Plage(i, j) <> "" Then tempo = tempo & Plage(i, j) Else tempo = tempo & "#VIDE"
Next j
If Not DICO.exists(tempo) And F.Rows(Plage(i, j).Row).Hidden = False Then
cpt = cpt + 1
ReDim Preserve TBL(1 To Plage.Columns.Count, 1 To cpt)
For j = 1 To Plage.Columns.Count
If Plage(i, j) <> "" Then TBL(j, cpt) = Plage(i, j) Else TBL(j, cpt) = "#VIDE"
Next j
DICO(tempo) = ""
End If
Next i
For i = 1 To UBound(TBL, 1)
tempo = ""
For j = 1 To UBound(TBL, 2)
If tempo = "" Then tempo = TBL(i, j) Else tempo = tempo & Chr(10) & TBL(i, j)
Next j
F.Cells(2, i) = tempo
Next i
End Sub
Private Function DimBD(Feuille As Worksheet, PremiereLigne As Long, PremiereColonne As String, NombreDeColonne As Long) As Range
Dim DernLig As Long
DernLig = Feuille.Range(PremiereColonne & Feuille.Rows.Count).End(xlUp).Row
If DernLig < PremiereLigne Then MsgBox "Plage vide !", vbExclamation, "Sélection de la plage": Exit Function
Set DimBD = Feuille.Range(PremiereColonne & PremiereLigne).Resize(DernLig - PremiereLigne + 1, NombreDeColonne)
End FunctionA mettre dans le module de la feuille concernée
Bonjour
Merci beaucoup pour ton retour et l'update avec les commentaires dans le code (je vais pouvoir potasser ça à tête reposée
Concernant la question sur les "paramètres vides", les utilisateurs finaux ne devrait normalement pas être confronté à cette situation.
Dans notre panel, chaque site est rattaché à un secteur propre, lui-même rattaché a une région donc pas de cellules vides en colonnes A,B,C (ces données sont extraites directement de notre ErP)
De plus, si aucune sélection n'est réalisée, la ligne 2 reste égale à la ligne 1 (valeurs globales, toutes régions, tous sites, tous secteurs).
Pour ce tableau, je me suis orienté vers un fonctionnement en entonnoir pour les utilisateurs finaux (ces derniers ont des besoins différents, quand certains ont besoin d'un visuel régional de leur portefeuille, d'autres auront besoin d'un visuel de leur secteur voir d'un seul site) avec pour finalité, l'édition rapide de bilans en fonction de leur sélection.
Le niveau vis-à-vis des outils informatiques est très disparate parmi les utilisateurs, je ne souhaite donc pas aller trop loin dans la dépendance du fichier au VBA si possible (également dans un soucis de pérennité du fichier si "je ne suis pas la pour corriger" en cas de problème) même si j'aurai préféré cette idée, je dois prendre en compte ces "contraintes"
C'est pourquoi je laisse cette notion de sélection manuelle.
Le code a donc pour objectif de retranscrire respectivement en A2, B2, C2 les données sélectionnées par l'utilisateur sur les colonnes A, B, C (ce qui semble fonctionner) via concaténation.
Mais par soucis de lisibilité (panel de +100 sites pour ce tableau), je souhaiterai réussir à ne pas afficher les données en doublons (et la je pêche
Pour exemple, le résultat actuel lorsque nous sélectionnons "R1" est celui-ci :
Je dois réussir à arriver à cet affichage pour la version finale :
Encore merci pour ton retour
Je regarde ça dans la matinée ;)
<en tout cas ton petit exemple me permet de clarifier ta demande, à vue d'oeil le code sera (beaucoup) plus simple !
Re
Voilà la nouvelle version ! :
Je rebondi juste sur "normalement pas être confronté à cette situation." en parlant des cellules vides, Crois moi, les oublis, fautes de frappes, les "copier / merdé" et j'en passe il faut les anticiper !
C'est pas pour défendre mon bout de gras mais le code que je t'ai proposé ci-dessus permet de mettre en évidence problèmes de saisies, après tu es "mon client" donc je t'écoute et je conseil comme il me semble juste de le faire
Option Explicit
Private Sub Worksheet_Calculate()
Dim F As Worksheet
Dim L As Long, C As Long
Dim Plage As Range
Dim DICO As Object
Dim Tempo As String, Result As String
Set F = ThisWorkbook.Worksheets("BD") 'Définir la feuille où l'on travail
Set DICO = CreateObject("Scripting.Dictionary") 'Création d'un dictionnaire (il servira à traiter les doublons)
Set Plage = DimBD(F, 5, "A", 3) 'On redimentionne la plage à traiter
If Plage Is Nothing Then Exit Sub 'Si la plage est vide fin de l'execution
For C = 1 To Plage.Columns.Count 'Boucle sur toutes les colonnes de la plage
Result = "": DICO.RemoveAll 'Réinitialisation des variables à chaque changement de colonne
For L = 1 To Plage.Rows.Count 'Boucle sur toutes les lignes de la plage
Tempo = Plage(L, C) 'Tempo prend pour valeur le contenue de la cellule située à l'intersection de C et L
'Si Tempo n'est pas vide et qu'il n'appartient pas au dictionnaire et que la ligne n'est pas masquée alors :
If Tempo <> "" And Not DICO.Exists(Tempo) And F.Rows(Plage(L, C).Row).Hidden = False Then
'si Result est vide alors Result prend pour valeur Tempo
'si Result n'est pas vide on ajout Tempo à Result avec un saut de ligne
If Result = "" Then Result = Tempo Else Result = Result & Chr(10) & Tempo
DICO(Tempo) = "" 'Ajout de Tempo à la liste du dictionnaire
End If
Next L
F.Cells(2, C) = Result 'Transfert du resultat dans la celulle correspondante
Next C
End Sub
Private Function DimBD(Feuille As Worksheet, PremiereLigne As Long, PremiereColonne As String, NombreDeColonne As Long) As Range
Dim DernLig As Long
DernLig = Feuille.Range(PremiereColonne & Feuille.Rows.Count).End(xlUp).Row 'Définit la dernière ligne (visible) sur la colonne définie
'Si la dernière cellule non vide est inférieur à la première ligne définie c'est que la colonne de la BD est vide
If DernLig < PremiereLigne Then MsgBox "Plage vide !", vbExclamation, "Sélection de la plage": Exit Function
Set DimBD = Feuille.Range(PremiereColonne & PremiereLigne).Resize(DernLig - PremiereLigne + 1, NombreDeColonne) 'Redimentionement de la première cellule de la BD aux bonnes dimensions
End Function
Bonjour,
Merci beaucoup pour cette mise à jour du code
(je regarde le code cette après-midi et te fais un retour).
Concernant les cellules vides, je ne peux qu'être d'accord avec toi par expérience.
Avec la main sur l'ensemble des données d'entrées, je me serai clairement orienté vers ta première proposition.
Malheureusement je n'ai pas la main sur notre ErP pour l'enregistrement des sites.
Par contre cet ErP ne peut avoir un site dans la base de donnée sans être associé à un secteur et une région (les utilisateurs sont informés par un message d'erreur dans le cas d'une saisie incomplète, erronées ou en inadéquation avec les données initiales fournies par les commerciaux).
Je dirai qu'il y a un premier "pare feu" sur les erreurs de saisie à ce moment.
Auquel je m'ajoute un point de contrôle complémentaire lors de la mise à jour mensuelle du panel de site sur le tableau (sur laquelle j'ai la main) :
Il y a mieux à faire niveau optimisation, je te l'accorde mais il semblerait que ce soit le "meilleur" compromis pour mes collègues à ce jour.
Par contre, je me garderai ton premier code sous le coude si tu le permet pour une potentielle mise à jour future (après montée en compétence sur les outils informatiques des collègues, et moi-même
Merci beaucoup.
pas de soucis, tu fais ce que tu veux de mon code 😁
je vais voir, mais si les compétences en informatique de tes collaborateurs peuvent être limitées (c'est pas un reproche) je pense qu'il est possible d'avoir le même résultat sans passer par du VBA ! Cela peut rassurer l'utilisateur mais la formule n'en sera pas moins complexe 😂
je reviens vers toi cette après midi si j'ai quelque chose de concluant par le biais d'une formule 😉
Re bonjour,
Merci beaucoup pour le code, tout fonctionne comme je le voulais.
Et les commentaires dans le code également pour la compréhension, je vais pouvoir potasser
Tu as déjà solutionné mon blocage, je ne vais pas abusé trop de ton temps
(même si j’admets que réussir à passer par une formule pique ma curiosité
Encore merci pour ton aide sur ce projet
J'ai pas eu trop de temps de réfléchir, néanmoins voilà une version sans VBA (utilisation de formules et de formules matricielles). Le fichier fonctionne ! Ma méthode est peut-être (un poile) bourrin mais elle a le mérite de fonctionner
Pour le coup si quelqu'un d'autre passe ici, je suis preneur d'une méthode plus efficace et moins archaïque
(Pour comprendre ma méthode n'oublie pas de checker les plages nommées sur le ruban Formules puis Gestionnaire de noms !