Séparer des contacts dans une même cellule et compter leur valeur associée

Ben_R

XLDnaute Nouveau
Bonjour à tous, je bute sur un problème :

J’ai une liste de contacts avec 2 colonnes comme suit :
Une Colonne avec plusieurs contacts séparés par des points virgules
Une colonne avec un nombre associé à chaque ligne

Je souhaite isoler chaque contact et obtenir le nombre associé à la ligne ou il était


Colonne 1 Colonne 2
Pierre jean; sylvian dufour 3
Guillaume Le Breton ; Guillaume Gilles, Martin de Normandie 2


Afin d’obtenir les résultats comme suit :

Colonne 1 Colonne 2
Pierre jean 3
Sylvian dufour 3
Guillaume le breton 2
Guillaume Gilles 2
Martin de Normandie 2


Merci par avance pour votre aide précieuse !

Cordialement
 

laurent950

XLDnaute Barbatruc
Bonsoir Lone-wolf,

Il est tard mais comme j'ai lu j'ai modifié avec commentaire pour vous, donc j'ai repris votre module
mis des commentaires (si vous avez des explication par rapport à votre code natif) j'ai juste agrémenté sans perdre votre logique pour arrivé à un résultat.

VB:
Option Explicit

Sub test1()
Dim c As Range, Item As Variant, Ligne As Long, Plage As Range, Ctr As Integer
    Ligne = 1
    With Sheets("Feuil1")
    ' Transformation de votre code
    ' commentaire ci-dessous
    '.Range(.[B2], .Cells(.Cells(.Rows.Count, 2).End(xlUp).Row, 3)).Select
        ' Vous
        ' Set Plage = .Range(.[B2], .Cells(.Rows.Count, 2).End(xlUp))
        ' Moi
        Set Plage = .Range(.[B2], .Cells(.Cells(.Rows.Count, 2).End(xlUp).Row, 3))
        For Each c In Plage
            ' MsgBox c.Address
            ' Ici j'ai pas compris l'utilité
            ' Ctr = c.Offset(, -1).Value
            ' MsgBox Ctr
            ' Pour moi je test dans la plage de 3 lignes et 2 colonnes
            ' comme For each balais la plage comme suit
            ' Toutes les ligne de la premiére colonne
            ' Puis toutes les lignes de la deuxiéme colonne
            ' alors lorsque c aura l'adress de la deuxiéme colonne
            ' et que se sont que des valeurs numéric je saute
            ' cette instruction avec ceci : Not IsNumeric(c.Value)
            ' se ne sont pas des valeurs numérique
            If c.Value <> "" And Not IsNumeric(c.Value) Then
                For Each Item In Split(c.Value, "; ")
                    Ligne = Ligne + 1
                    ' Ici j'ai pas compris aussi l'utilité en dessous en commentaire
                    'If Ctr <> 0 Then
                        '.Cells(Ligne, 2) = Ctr
                        'Ctr = 0
                    'End If
                    .Cells(Ligne, 5) = Item                 ' Nom et Prénom
                    ' Ici comme je ne traite pas les valeurs numéric
                    ' j'utilise offset pour récupérer la valeur de la deuxiéme colonne
                    ' avec ceci : c.Offset(0, 1).Value
                    ' C'est pour cela que j'ai pas compris le Ctr = c.Offset(, -1).Value du début
                    .Cells(Ligne, 6) = c.Offset(0, 1).Value ' Numéro consultation
                Next Item
            End If
        Next c
    End With
End Sub

Au plaisir de partager

Laurent
 

Pièces jointes

  • Copie de test (4).xlsm
    20.4 KB · Affichages: 31

ChTi160

XLDnaute Barbatruc
Bonjour Ben_R
Bonjour le Fil ,le Forum
Une autre approche ou je rassemble les Rdv par Contact (peut être hors sujet Lol)
EDIT : Impossible de joindre mon Fichier ?????
je mets donc le Code
j'ai mis un bouton dans la "Feuil1"
puis je lui ai affecté la procédure
soit :
VB:
Private Sub CommandButton1_Click()
Recap_ID
End Sub
puis dans un module Standard j'ai défini les Variables et mis la Procédure:
VB:
Option Explicit
Option Base 1
Public Ws_Cible As Worksheet
Public Coll_ID As Collection
Public Nbr_RDv As Integer

Public Tab_Gen As Variant
Public Tab_Recup As Variant
Public Tab_Recap() As Variant
Public Tab_BY_ID() As Variant

Public DerLgn As Long
Public Lgn As Long
Public DerCol As Byte

Public Str_ID As String
Public x As Long
Public xx As Long
Public i As Integer
Public ii As Integer
Public iii As Integer

Public Sub Recap_ID()
Application.ScreenUpdating = False
Set Ws_Cible = Worksheets("Feuil1") 'on initialise la variable
Set Coll_ID = New Collection 'Initialise la Collection des Noms
x = 1: xx = 1 'on initialise les variables
  With Ws_Cible 'avec la feuille ainsi definie
     DerLgn = .Cells(.Rows.Count, 1).End(xlUp).Row 'on détermmine la derniere ligne non vide de la Colonne A(1) de la feuille Cible
     DerCol = .Cells(1, .Columns.Count).End(xlToLeft).Column 'on dtermine la Derniere colonne non vide de la premiere ligne
    Tab_Gen = .Range(.Cells(2, 1), .Cells(DerLgn, DerCol)).Value 'on récupére les données de la palge ainsi définie dans un tableau
   For Lgn = 1 To UBound(Tab_Gen, 1) 'pour chaque lignes du tableau

        Nbr_RDv = Tab_Gen(Lgn, 2) 'on récupére le nombre de points
    If InStr(1, Tab_Gen(Lgn, 1), ";") <> 0 Then 'si plusieurs ID
        Tab_Recup = Split(Tab_Gen(Lgn, 1), ";") 'on les récuépre dans un tableau temporaire
      Else
        Tab_Recup(1) = Tab_Gen(Lgn, 1) 'si un seul nom on le récupére
    End If
      For i = 0 To UBound(Tab_Recup) 'pour chaque colonnes du tableau temporaire
      ReDim Preserve Tab_Recap(2, x) 'on redimansionne le tableau 2 lignes x colonnes
      Tab_Recap(1, x) = Trim(Tab_Recup(i)) 'on récupére le Contact
      Tab_Recap(2, x) = Nbr_RDv 'on récuépre les Points
      x = x + 1 'on incremente les colonnes du tableau temporaire
      Next i
   Next Lgn
'pour test
    .Cells(1, 4) = "Contacts": .Cells(1, 5) = "rdv" 'on colle les entetes
    .Range("D2").Resize(UBound(Tab_Recap, 2), 2) = Application.Transpose(Tab_Recap) 'ici on récupére la Liste des Rdv
'on va réunir les Rdv par Contact
   On Error Resume Next 'gestion des erreurs
  For ii = 1 To UBound(Tab_Recap, 2) 'pour chaque colonnees du tableau temporaire
  Str_ID = UCase(Tab_Recap(1, ii)) 'on récupére le Contact
'**************
    Coll_ID.Add Str_ID, CStr(Str_ID) 'on l'entre dans la collection des Contacts Unique
'**************
      If Err.Number = 0 Then 'si contact pas encore dans la Collection
          ReDim Preserve Tab_BY_ID(2, xx) 'on redimmansionne le tableau 2 lignes Toujours
            Tab_BY_ID(1, xx) = Str_ID 'on colle le Contact sur la première ligne    
                For iii = 1 To UBound(Tab_Recap, 2) 'on va lister toutes les lignes pour vérifier si contact présent plusieurs fois
                  If UCase(Tab_Recap(1, iii)) = Str_ID Then 'si present
                    Tab_BY_ID(2, xx) = Tab_BY_ID(2, xx) + Tab_Recap(2, iii) 'on cumule les RDVs
                  End If
                Next iii 'autre colonne      
          xx = xx + 1 'on incremente le Nombre de colonnes du tableau
      End If
      Err.Clear
  Next ii
   .Cells(1, 7) = "CONTACTS": .Cells(1, 8) = "RDV" 'on colle les entetes
   .Range("G2").Resize(UBound(Tab_BY_ID, 2), 2) = Application.Transpose(Tab_BY_ID) 'on colle le tableau en l'inversant
  End With
  Application.ScreenUpdating = True
Erase Tab_Gen: Erase Tab_Recup: Erase Tab_Recup: Erase Tab_BY_ID 'on vide les tableaux
End Sub
EDIT : je joins le fichier des que possible !
Bonne journée
Jean marie
 
Dernière édition:

laurent950

XLDnaute Barbatruc
Il faut Prendre le code de Lone-Wolf qui est ultra rapide
j'ai mis mais trois module dans un classeur le plus rapide est test3 mais prendre le code de Lone-Wolf mieux encore

pour le module de sont poste #15 Lone-Wolf

Laurent
 

Pièces jointes

  • Fichier source Test 1-2-3.xlsm
    8.9 MB · Affichages: 29

Staple1600

XLDnaute Barbatruc
Bonsoir à tous

Une autre syntaxe
(NB: pour laquelle je m'abstiens de chercher à savoir si elle est rapide ou pas ;)
C'est juste histoire d'attendre la fin du cycle de ma machine à laver)
VB:
Sub abcd()
Dim t, tt, i&, j&
t = Range("B2", Cells(Rows.Count, "C").End(3)).Value: j = 2
For i = LBound(t) To UBound(t)
tt = Split(t(i, 1), ";")
    With Cells(j, "E").Resize(UBound(tt) + 1)
    .Value = Application.Transpose(tt): .Offset(, 1) = t(i, 2)
    End With
j = Cells(Rows.Count, "E").End(3).Row + 1
Next
End Sub
 

Staple1600

XLDnaute Barbatruc
Re

@Les gars
J'ai pas trop compris pourquoi vous mettez des fichiers exemples si "gigantesques" ?
(Surtout que chez moi, cela plante grave Excel, j'ai du m'y reprendre à trois fois pour finir par ouvrir le premier gros fichier posté par Ben_R)

Sinon (à confirmer par le demandeur), les données (patronymes des contacts) sont bien sur fictives et/ou non confidentielles?
(A vue de nez, je dirai non pour ma part)
D'ailleurs, je suis surpris que les répondeurs aguerris qui se sont manifestés dans le fil n'aient pas abordés le sujet avec Ben_R ?!?

ci-dessous extrait de la charte
5 – La possibilité de joindre des fichiers est donnée sur ce forum. Ne pas hésiter à utiliser cette fonction, tout en veillant que les données soient bidons et donc qu’aucune donnée confidentielle, nominative ne soit dans le fichier.
 
Dernière édition:

ChTi160

XLDnaute Barbatruc
arf
j’enlève le fichier de suite !
je vais juste mettre le Code modifié pour la version avec données Colonnes B:C
VB:
Option Explicit
Option Base 1
Public Ws_Cible As Worksheet
Public Coll_ID As Collection
Public Nbr_RDv As Integer

Public Tab_Gen As Variant
Public Tab_Recup As Variant
Public Tab_Recap() As Variant
Public Tab_BY_ID() As Variant

Public DerLgn As Long
Public Lgn As Long
Public DerCol As Byte

Public Str_ID As String
Public x As Long
Public xx As Long
Public i As Integer
Public ii As Integer
Public iii As Integer

Public Sub Recap_ID()
Application.ScreenUpdating = False
 Set Ws_Cible = Worksheets("Feuil1") 'on initialise la variable
 Set Coll_ID = New Collection 'Initialise la Collection des Noms
 x = 1: xx = 1 'on initialise les variables
  With Ws_Cible 'avec la feuille ainsi definie
     DerLgn = .Cells(.Rows.Count, 2).End(xlUp).Row 'on détermmine la derniere ligne non vide de la Colonne A(1) de la feuille Cible
     DerCol = .Cells(1, .Columns.Count).End(xlToLeft).Column 'on dtermine la Derniere colonne non vide de la premiere ligne
    Tab_Gen = .Range(.Cells(2, 2), .Cells(DerLgn, DerCol)).Value 'on récupére les données de la palge ainsi définie dans un tableau
   For Lgn = 1 To UBound(Tab_Gen, 1) 'pour chaque lignes du tableau   
        Nbr_RDv = Tab_Gen(Lgn, 2) 'on récupére le nombre de points
    If InStr(1, Tab_Gen(Lgn, 1), ";") <> 0 Then 'si plusieurs ID
        Tab_Recup = Split(Tab_Gen(Lgn, 1), ";") 'on les récuépre dans un tableau temporaire
      Else
        Tab_Recup(1) = Tab_Gen(Lgn, 1) 'si un seul nom on le récupére
    End If
      For i = 0 To UBound(Tab_Recup) 'pour chaque colonnes du tableau temporaire
      ReDim Preserve Tab_Recap(2, x) 'on redimansionne le tableau 2 lignes x colonnes
      Tab_Recap(1, x) = Trim(Tab_Recup(i)) 'on récupére le Contact
      Tab_Recap(2, x) = Nbr_RDv 'on récuépre les Points
      x = x + 1 'on incremente les colonnes du tableau temporaire
      Next i
   Next Lgn
'pour test
    .Cells(1, 5) = "Contacts": .Cells(1, 6) = "rdv" 'on colle les entetes
    .Range("E2").Resize(UBound(Tab_Recap, 2), 2) = Application.Transpose(Tab_Recap) 'ici on récupére la Liste des Rdv
'on va réunir les Rdv par Contact
   On Error Resume Next 'gestion des erreurs
  For ii = 1 To UBound(Tab_Recap, 2) 'pour chaque colonnees du tableau temporaire
  Str_ID = UCase(Tab_Recap(1, ii)) 'on récupére le Contact
'**************
    Coll_ID.Add Str_ID, CStr(Str_ID) 'on l'entre dans la collection des Contacts Unique
'**************
      If Err.Number = 0 Then 'si contact pas encore dans la Collection
          ReDim Preserve Tab_BY_ID(2, xx) 'on redimmansionne le tableau 2 lignes Toujours
            Tab_BY_ID(1, xx) = Str_ID 'on colle le Contact sur la premiere ligne       
                For iii = 1 To UBound(Tab_Recap, 2) 'on va lister toutes les lignes pour verifier si contact présent plusieur fois
                  If UCase(Tab_Recap(1, iii)) = Str_ID Then 'si present
                    Tab_BY_ID(2, xx) = Tab_BY_ID(2, xx) + Tab_Recap(2, iii) 'on cumule les RDVs
                  End If
                Next iii 'autre colonne         
          xx = xx + 1 'on incremente le Nombre de colonnes du tableau
      End If
      Err.Clear
  Next ii
   .Cells(1, 8) = "CONTACTS": .Cells(1, 9) = "RDV" 'on colle les entetes
   .Range("H2").Resize(UBound(Tab_BY_ID, 2), 2) = Application.Transpose(Tab_BY_ID) 'on colle le tableau en l'inversant
  End With
  Application.ScreenUpdating = True
Erase Tab_Gen: Erase Tab_Recup: Erase Tab_Recup: Erase Tab_BY_ID 'on vide les tableaux
End Sub
Bonne fin de Soirée
Jean marie
 
Dernière édition:

Statistiques des forums

Discussions
315 156
Messages
2 116 815
Membres
112 876
dernier inscrit
Flo44