Microsoft 365 Faire une collection de collection en VBA

GuillaumeFranceschi

XLDnaute Nouveau
Bonjour à tous,

Je me présente, je suis nouveau membre sur Excel-Downloads, je m'appelle Guillaume et je suis très heureux de pouvoir lire tous les post intéressants que le forum propose.
Pour mon entrée en matière sur le forum j'aimerais vous partager une problématique pour laquelle je sillonne internet et ce forum depuis quelques jours en quête d'une solution... sans succès pour le moment. Je vous expose mon problème du mieux que je le peux mais n'hésitez pas à me faire préciser tout ce qui nécessite éclaircissement :

Je travaille actuellement dans une équipe informatique à la SNCF au sein de laquelle je suis amené à manipuler des données ferroviaires. Ces données ferroviaires ne sont rien d'autre qu'une liste de voyages avec des points de passage. La liste Excel se présente ainsi :

1690538073787.png


Là c'est un échantillon dans lequel un seul voyage est représenté mais il faut imaginer des tableaux avec des milliers de lignes. J'ai donc mes points de passage sur la colonne B et dans la colonne A j'ai le numéro du voyage (c'est l'équivalent du numéro de train que vous voyez en gare quand vous voyagez :)) qui est répété sur chaque ligne.
Voilà, seulement ce format de représentation des données ne me convient pas pour la suite et j'aimerais ranger ces données dans une collection de voyage qui s'appelle "tripCollection" dans le fichier que je vous ai joint.
Je suis bien loin de maitriser les collections mais faire une collection d'objets Voyages ne me semble pas insurmontable. Pour ceci j'ai :
  • Créé un module de classe qui se nomme "trip" et dans laquelle j'ai défini les variables de la manière suivante :
VB:
Option Explicit

Public numero As String
Public listePoints As Collection

  • Mon problème va se situer dans la définition d'une variable comme une collection mais nous allons voir ça plus bas
  • J'ai ensuite créé une procédure pour instancier mes objets "Voyages" et les insérer à ma collection "tripCollection" en fonction des informations que je trouve dans mon tableau :
VB:
Dim tripCollection As New Collection
Sub remplirTripCollection()

Dim i, derligne, k As Long
Dim numVoyage As String
Dim voyage As trip
Dim listePointsVoyage As New Collection

derligne = Sheets("test").Cells(Rows.Count, 1).End(xlUp).Row

For i = 1 To derligne

    numVoyage = Sheets("test").Cells(i, 1).Value
    
    Set voyage = New trip
    voyage.numero = numVoyage
    
    
    k = i
    Set listPointsVoyage = Nothing
    
    Do While Sheets("test").Cells(k, 1).Value = numVoyage
    
        nouveauPoint = Sheets("test").Cells(k, 2).Value
        listePointsVoyage.Add nouveauPoint
        
    k = k + 1
    Loop

voyage.listePoints = listePointsVoyage
tripCollection.Add voyage

Next i

End Sub

  • En fait je veux faire une collection de voyages, mais pour chaque voyage j'aimerais que la liste de points (qui est variable car différente pour chaque voyage) soit également stockée dans une "sous-collection". C'est pour cela que je me suis dit que mettre une collection "listePoints" en variable de ma classe "trip" était une bonne idée mais en fait ça ne ne fonctionne pas. En effet j'arrive à remplir la collection "listePointsVoyages" mais je n'arrive pas ensuite à la renseigner dans mon objet voyage. Ma ligne de code "voyage.listePoints = listePointsVoyage" bug au lancement de la macro et je finis avec le message d'erreur suivant :
1690539016014.png


Conclusion :

Je débute sur la manipulations des collections et des modules de classe et je n'arrive pas à faire ce premier exercice. Auriez-vous des idées pour me débloquer s'il vous plait ?

Je vous remercie tous par avance de l'attention que vous pourrez porter à ma demande

Une très bonne journée à tous et à bientôt sur le Forum

Guillaume
 

Pièces jointes

  • collectionVoyages.xlsm
    21.3 KB · Affichages: 7
Solution
Bonjour,
voila une piste!
j'ai rajouter un onglet Result!

j'ai pris les valeurs Arrivée & Départ pour charger l'intérieur du tableau pour bien montrer l'utilité des Dictionary Voyages & Points mais tu vas vite intégrer le principe!
VB:
Sub test()
Dim Voyages As Object, Points As Object, Col As Integer, Lin As Integer
Col = 3: Lin = 7
Set Voyages = CreateObject("scripting.dictionary")
Set Points = CreateObject("scripting.dictionary")

Sheets("Result").Cells.Delete
With Range("Tableau1")
    For i = 2 To .Rows.Count
      If Not Voyages.exists(CStr(.Cells(i, "A"))) Then
        Col = Col + 1
        Voyages(CStr(.Cells(i, "A"))) = Col
      End If
       If Not Points.exists(CStr(.Cells(i, "B"))) Then
        Lin = Lin + 1...

GuillaumeFranceschi

XLDnaute Nouveau
C'est parce que le second paramètre est un ParamArray, c'est à dire une série de paramètres en nombre indéterminé qui se récupère sous forme d'un tableau dans la procédure.
TableauAquis est une Function du même module qui s'accommode de plein de sortes de sources pour en déduire toujours un tableau dynamique.
IndexerParFusion est une Sub du même module qui établit un tableau de Long des numéros de lignes rangé par ordres de valeurs des contenus. C'est en somme un classement qui, au lieu de changer l'ordre des données, indique plutôt dans quel ordre il faut les parcourir.
C'est sûr que dans la fonction gigogne, l'instruction qui fabrique la collection est très discrète, puisque c'est juste la Set Gigogne = SousGroupes(1)
La SousGroupe, par contre, elle est récursive et pas piquée des hannetons !
Merci beaucoup pour toutes ces réponses @Dranreb
 

GuillaumeFranceschi

XLDnaute Nouveau
Bonjour,
Je ne comprends pas ,tu t'intéresse aux collections et aux modules de classe pour le fun ou dans un but bien défi ?

Il pourrait être judicieux de nous préciser la finalité de tous ça pour nous permettre de te proposer la meilleure solution et pas forcément celle que tu imagines.
Bonjour,
Ce n'est ni pour le fun ni pour le défi, c'est que j'avais l'impression que c'est ce qui répondrait le mieux à ma problématique de stockage de données mais en tant que débutant je suis en effet totalement disposé à entendre qu'il existe d'autres fonctionnalités pour gérer cela. Je vais donc me pencher sur les dictionnaires qui semblent mieux répondre à ma demande.
J'essaie de vous expliquer ici au mieux ce que je veux comme affichage final en espérant ne pas vous embrouiller avec du détail :
A partir de la liste que je vous ai transmise je vais devoir par la suite re disposer mes voyages selon le format suivant :
1690816461066.png

  • Chaque voyage est repris en colonne
  • Et ensuite, pour chaque voyage je vais devoir reporter l'horaire au point de passage dans la grille
Et vu la quantité de données et la différence de mise en forme entre la liste initiale et celle-ci, je voulais tout d'abord ranger tous mes voyages dans quelque chose (dictionnaire, collection ou autre méthode..) pour n'avoir ensuite qu'à parcourir mes données organisées pour les re disposer sous ce format de grille

Je ne sais pas si ça t'aide à y voir plus clair dans la suite de mon projet
Merci d'avance
 

GuillaumeFranceschi

XLDnaute Nouveau
un bon lien pour ces dictionaires https://excelmacromastery.com/vba-dictionary/
un exemple vite fait avec votre fichier, un dictionaire qui lit ce tableau et crée vos 157 differents voyages.
2ième dictionaire, comme démo, qui lit ces 157 voyages et crée une liste de tous les voyages qui passent un point (en feuille points) (il n'y a que 26 points différents) et un voyage passe plusieurs fois le même point.
Merci beaucoup @bsalv je suis tombé sur ce lien ce WE, les tutos de cette personne sont vraiment bien j'ai commencé à les regarder. Merci également pour le fichier je suis en train de m'en inspirer
 

GuillaumeFranceschi

XLDnaute Nouveau
Bêtement, dans un élan de simplification de mon fichier avant de vous l'envoyer j'ai supprimer une colonne qui venait à distinguer ces deux voyages. Je l'avais retirée pensant que cette colonne allait plus vous polluer qu'autre chose :
1690817338420.png

Mes voyages appartiennent à des groupes différents depuis l'outil duquel je les ai extraits
 

dysorthographie

XLDnaute Accro
Bonjour,
voila une piste!
j'ai rajouter un onglet Result!

j'ai pris les valeurs Arrivée & Départ pour charger l'intérieur du tableau pour bien montrer l'utilité des Dictionary Voyages & Points mais tu vas vite intégrer le principe!
VB:
Sub test()
Dim Voyages As Object, Points As Object, Col As Integer, Lin As Integer
Col = 3: Lin = 7
Set Voyages = CreateObject("scripting.dictionary")
Set Points = CreateObject("scripting.dictionary")

Sheets("Result").Cells.Delete
With Range("Tableau1")
    For i = 2 To .Rows.Count
      If Not Voyages.exists(CStr(.Cells(i, "A"))) Then
        Col = Col + 1
        Voyages(CStr(.Cells(i, "A"))) = Col
      End If
       If Not Points.exists(CStr(.Cells(i, "B"))) Then
        Lin = Lin + 1
        Points(CStr(.Cells(i, "B"))) = Lin
      End If
     Sheets("Result").Cells(Points(CStr(.Cells(i, "B"))), "A") = CStr(.Cells(i, "B"))
     Sheets("Result").Cells(4, Voyages(CStr(.Cells(i, "A")))) = CStr(.Cells(i, "A"))
     Sheets("Result").Cells(Points(CStr(.Cells(i, "B"))), Voyages(CStr(.Cells(i, "A")))) = CStr(.Cells(i, "C")) & Chr(10) & CStr(.Cells(i, "D"))
    Next
End With

End Sub
 
Dernière édition:

GuillaumeFranceschi

XLDnaute Nouveau
Bonjour,
voila une piste!
j'ai rajouter un onglet Result!

j'ai pris les valeurs Arrivée & Départ pour charger l'intérieur du tableau pour bien montrer l'utilité des Dictionary Voyages & Points mais tu vas vite intégrer le principe!
VB:
Sub test()
Dim Voyages As Object, Points As Object, Col As Integer, Lin As Integer
Col = 3: Lin = 7
Set Voyages = CreateObject("scripting.dictionary")
Set Points = CreateObject("scripting.dictionary")

Sheets("Result").Cells.Delete
With Range("Tableau1")
    For i = 2 To .Rows.Count
      If Not Voyages.exists(CStr(.Cells(i, "A"))) Then
        Col = Col + 1
        Voyages(CStr(.Cells(i, "A"))) = Col
      End If
       If Not Points.exists(CStr(.Cells(i, "B"))) Then
        Lin = Lin + 1
        Points(CStr(.Cells(i, "B"))) = Lin
      End If
     Sheets("Result").Cells(Points(CStr(.Cells(i, "B"))), "A") = CStr(.Cells(i, "B"))
     Sheets("Result").Cells(4, Voyages(CStr(.Cells(i, "A")))) = CStr(.Cells(i, "A"))
     Sheets("Result").Cells(Points(CStr(.Cells(i, "B"))), Voyages(CStr(.Cells(i, "A")))) = CStr(.Cells(i, "C")) & Chr(10) & CStr(.Cells(i, "D"))
    Next
End With

End Sub
Bonjour @dysorthographie,
Un grand merci pour la simplicité de cette méthode qui m'a appris une nouvelle façon de voir les choses et qui m'a surtout ouvert la voie des dictionnaires
Cela m'a beaucoup aidé
Je te souhaite une bonne journée et à bientôt sur le forum
Guillaume
 

GuillaumeFranceschi

XLDnaute Nouveau
Bonjour à tous,
De manière générale, merci à tous pour votre temps et vos réponses sur ce sujet, toutes les infos que j'ai lues ici m'on été utiles pour l'avancer de ma macro
Merci encore @Dranreb, à cause de mon niveau, je n'ai pas forcément su apprécier pleinement les solutions proposées mais ça va me permettre d'avoir une super base pour passer à l'étape supérieure
A bientôt sur le forum
Guillaume
 

dysorthographie

XLDnaute Accro
Bonjour,
Il est important, à mes yeux,de ne pas se contenter de poser une question mais de présenter la finalité du problème. Tu risques d'avoir des réponses à ta question sans pour autant résoudre ton problème.😝

Ravi si j'ai pu t'apporter des éléments de réponse.
 

Discussions similaires

Réponses
29
Affichages
920

Statistiques des forums

Discussions
312 209
Messages
2 086 266
Membres
103 168
dernier inscrit
isidore33