Transformation de données d'arbre à tableau complet

Bonjour à tous!

J'ai un problème que je n'arrive pas à résoudre.

J'ai un arbre avec des catégorie

Categorie 1

Sous categorie 1-1

Sous categorie 1-2

Sous categorie 1-3

Sous categorie 1-4

Sous categorie 1-5

Sous categorie 1-6

Sous categorie 1-7

Sous categorie 1-8

Sous categorie 1-9

Sous categorie 1-10

Categorie 2

Sous categorie 2-1

Sous categorie 2-2

Sous categorie 2-3

Sous categorie 2-4

Sous categorie 2-5

Sous Sous categorie 2-5-1

Sous Sous categorie 2-5-2

Sous Sous categorie 2-5-3

Sous Sous categorie 2-5-4

Sous Sous categorie 2-5-5

Etc...

Que je voudrais tranformer en une suite d'éléments finaux:

Categorie 1 Sous categorie 1-1

Categorie 1 Sous categorie 1-2

Categorie 1 Sous categorie 1-3

Categorie 1 Sous categorie 1-4

Categorie 1 Sous categorie 1-5

Categorie 1 Sous categorie 1-6

Categorie 1 Sous categorie 1-7

Categorie 1 Sous categorie 1-8

Categorie 1 Sous categorie 1-9

Categorie 1 Sous categorie 1-10

Categorie 2 Sous categorie 2-1

Categorie 2 Sous categorie 2-2

Categorie 2 Sous categorie 2-3

Categorie 2 Sous categorie 2-4

Categorie 2 Sous categorie 2-5 Sous Sous categorie 2-5-1

Categorie 2 Sous categorie 2-5 Sous Sous categorie 2-5-2

Categorie 2 Sous categorie 2-5 Sous Sous categorie 2-5-3

Categorie 2 Sous categorie 2-5 Sous Sous categorie 2-5-4

Categorie 2 Sous categorie 2-5 Sous Sous categorie 2-5-5

Categorie 2 Sous categorie 2-6

Categorie 2 Sous categorie 2-7

Mais je n'arrive pas à le faire...

Quelqu'un saurait-il m'indiquer comment procéder?

Cet algorithme rentre dans un autre algorithme qui fait plein de traitements mais je bloque sur celui ci...

Ci joint le fichier avec deux onglets l'onglet de départ et celui d'arrivée!

Je vous remercie pour votre aide précieuse!

E

68transformation.xlsx (12.02 Ko)

Bonsoir,

un essai qui fonctionne...

A vous de regarder comment ça marche

Ceci dit, comme toujours il y a certainement plus simple....

@ bientôt

LouReeD

Bonjour,

et un autre...

eric

PS: ben si elle est simple LouReed

51transformation.xlsm (22.18 Ko)

Bonsoir Messieurs,

Merci beaucoup!

J'ai oublié de préciser qu'il peut y avoir plus de trois colonnes bien entendu... disons quinze sous catégories!

Si vous pouviez commenter et expliquer votre code.. les trucs récursifs je ne les comprend pas trop..

En tout cas j'essaie de comprendre et vous remercie mille fois!

Bonsoir eriiic,

je crois que définitivement que je n'arriverai à "pondre" un code comme le votre !

En le voyant ça fait pro, j'en ai marre d'être incapable de faire mieux que mes codes alambiqués !!!

Aller bonne fin de soirée à vous et @ bientôt

LouReeD


Sur le mien il suffit dans la boucle for next de mettre le nombre de colonne -1 et de rajouter fin au niveau de la dernière ligne +1 en colonne A.

Après si la colonne max doit être une variable il se peut qu'avec un UsedRange... ou un truc comme cela.....

@ bientôt

LouReeD


Les commentaires :

Sub allonsy()
    Dim ligne As Long ' numéro de la ligne en cours de test
    Dim ligne_a_sup As Long ' numéro de la ligne à supprimer
    Dim mem As Boolean ' y a t il une ligne à supprimer en mémoire vrai faux
    For colonne = 1 To 2 ' de la colonne 1 à la colonne X-1
        ligne_a_sup = 0 ' pas de ligne à supprimer
        ligne = 1 ' on commence le test en ligne 1
        Do ' on commence une boucle indéterminée
            If Cells(ligne, 1).Value = "fin" Then Exit Do ' si on arrive à la ligne où le mot fin est inscrit alors on quite la boucle
            If Cells(ligne, colonne).Value = "" Then ' si la cellule testée est vide
                If mem = False Then ' s'il n'y a pas de ligne à supprimmer
                    mem = True ' alors il y en a une
                    ligne_a_sup = ligne - 1 ' la ligne à supprimer est celle d'avant car sur la ligne actuelle la cellule est vide
                End If
                Cells(ligne, colonne).Value = Cells(ligne - 1, colonne).Value ' on remplie la cellule vide avec la valeur de la cellule d'avant
            Else ' si la cellule testée n'est pas vide
                If ligne_a_sup > 0 Then ' s'il y a une ligne à supprimer
                    Cells(ligne_a_sup, colonne).EntireRow.Delete ' on supprime
                    mem = False ' on a supprimer du coup on a plus de ligne à supprimer en mémoire
                    ligne_a_sup = 0 ' on initialise le numéro de ligne à supprimer
                    ligne = ligne - 1 ' comme on a supprimer une ligne on recommence le teste une ligne au dessus car suite à la suppression toutes les lignes sont remontées
                End If
            End If
            ligne = ligne + 1 ' on teste la ligne suivante
        Loop ' on boucle
    Next colonne ' on teste la colonne suivante
End Sub

Bonne soirée

@ bientôt

LouReeD

Merci Lou, je comprends mieux.. En testant, le code ne marche que pour trois colonnes... je vais essayer de l'adapter, en tout cas il marche pour l'exemple!

Pour ce qui est du code d'Eric, il ne marche pas puisqu'il avale la catégorie 6.. et de plus je n'y comprends pas grand chose..

Je cherche toujours quelque chose qui marcherait pour toutes configurations et autant de sous catégories que l'on veut.. le but étant de construire un tableau dans lequel j'aurais tous mes "Dernières catégories" (fin d'arbres) pour ensuite créer un word et remplir uniquement les sous cqtégories qui existent.

Bonjour,

M'y étant penché, je livre ma version... !

Bien qu'ayant l'air différente de celle de LouReed (Hello !) le principe utilisé est le même il me semble.

Cordialement.


Oh ! foule de messages qui m'étaient passés sous le nez...

Qu'est ce que ce pessimisme LouReed ? Il se tient très bien ton code !

La variabilité du nombre de colonnes, il valait mieux l'indiquer avant !

Je regarde si je peux l'adapter...

23transformation.xlsm (24.02 Ko)

Bonsoir MFerrand,

Merci pour ta solution qui est très bien!

Je vais essayer de m'inspirer de vos trois codes pour en construire un qui puisse marcher pour tout nombre de colonnes et pour toute structure!

Je vous suis très reconnaissant de vous y être penché !

Si vous veniez à avoir d'autres idées je suis prenneur, sinon j'essaierais de faire un post plus précis, je n'avais pas pensé que ma question n'était pas claire !

Bonne nuit à vous,

E

Re,

Assez simple à adapter finalement...

A+

C'est exactement ce que je voulais!

Il ne me reste plus qu'à déchifrer!

n,i,k,h des variables tellement parlantes hahaha

Merci beaucoup!

Si l'envie d'y glisser quelques commentaires te vient je suis prenneur!

Bien à toi,

E

Bon, ben le mien encore en retard

Ca va sans dire mais c'est mieux en le disant : la plage des cat doit être entourée de cellules vides.

Finalement ça l'a simplifié ce nombre de colonnes variables.

eric

25transformation.xlsm (23.47 Ko)

Re,

J'ai en effet l'habitude de zapper les commentaires ! Si l'on veut expliquer, ça prend souvent plus de temps que l'écriture du code, et les commentaires repères, sauf exceptions ne me suffisent jamais pour m'y retrouver rapidement dans un code que j'ai produit auparavant, donc j'en mets rarement pour moi.

Pour les variables, plus le nom est court, moins cela prend de temps à écrire... Je n'utilise donc pas la "méthode pro" de préfixage des noms pour reconnaître d'emblée le type de variable, etc. Je compense par des habitudes de nommage qui me permettent de m'y retrouver sans recherche particulière.

Pour déroger, j'espère que les commentaires suivants te seront utiles pour suivre le cheminement de la macro...

Si des commandes que tu penses ne pas interpréter exactement, n'hésite pas à demander...

Sub Transformation()
    'variables: n et col = dimensionnement lignes et colonnes utilisées (integer)
    ' i et k = var. compteurs (integer) ou à utilisation temporaire
    ' h variable (variant) destinée à recueillir numéros lignes à supprimer
    Dim n%, i%, k%, col%, h
    With ActiveSheet
    'Dimensionnement lignes et colonnes
    ' on utilise la fonction Excel NBVAL pour savoir si la col. suivante contient des valeur
    ' si oui, on incrémente col et on recherche dernière ligne utilisée dans la colonne
    ' on l'affecte à n si elle supérieure à la même valeur pour les col? précédentes
    ' si non, le dimensionnement est terminé, on sort de la boucle Do... Loop
        Do
            If Application.CountA(.Columns(col + 1)) > 0 Then
                col = col + 1
                k = .Cells(.Rows.Count, col).End(xlUp).Row
                If k > n Then n = k
            Else
                Exit Do
            End If
        Loop
        ' Si le tableau était vide on interrompt [NB: col aurait également la valeur 0]
        If n = 0 Then Exit Sub
    'Ajout des valeurs manquantes
        'Dans chaque colonne, de l'avant-dernière à la première (boucle)
        For k = col - 1 To 1 Step -1
            ' on parcourt toutes les lignes (boucle imbriquée)
            For i = 1 To n
                'Si la cellule est vide
                If .Cells(i, k) = "" Then
                    'alors que celle de la colonne suivante ne l'est pas
                    If .Cells(i, k + 1) <> "" Then
                        'on lui affecte la valeur de la ligne précédente dans la même colonne
                        .Cells(i, k) = .Cells(i - 1, k)
                        'Si dans cette ligne précédente la cellule de la colonne suivante était vide
                        ' on enregistre son numéro de ligne pour suppression ultérieure
                        ' en le concaténant dans h, suivi d'un séparateur
                        If .Cells(i - 1, k + 1) = "" Then h = h & i - 1 & ";"
                    End If
                End If
            Next i
        Next k
    'Traitement des lignes à supprimer
        'On transforme la suite des numéros de lignes à supprimer (dans h) en tableau
        ' la chaîne enregistrée dans h contenant un séparateur final, le tableau contiendra
        ' un élément final de plus (vide) que le nombre de lignes à supprimer
        h = Split(h, ";")
        'On trie ce tableau pour mettre les numéros de lignes dans l'ordre croissant
        ' (le tableau étant un tableau de chaînes, la comparaison se fait sur les valeurs
        ' converties en nombres), l'élément supplémentaire du tableau sert aux substitutions
        For i = LBound(h) To UBound(h) - 2
            For k = i + 1 To UBound(h) - 1
                If CInt(h(k)) < CInt(h(i)) Then
                    h(UBound(h)) = h(k)
                    h(k) = h(i)
                    h(i) = h(UBound(h))
                End If
            Next k
        Next i
        'On parcourt le tableau trié de l'avant-dernier élément (le dernier n'étant pas un
        ' numéro de ligne à supprimer) au premier, en supprimant les lignes correspondantes
        For i = UBound(h) - 1 To LBound(h) Step -1
            .Rows(h(i)).Delete
        Next i
    End With
End Sub

Cordialement.

Bonjour MFerrand,

Merci BEAUCOUP c'est très bien commenté!

Je m'étais mis des debugs prints pour le comprendre et je viens de voir ton message.

En language naturel l'algo est de la sorte:

On commence par l'avant derniere colonne jusqu'à la première

Pour chaque ligne,

Si la case est vide et que celle d'a coté ne l'est pas,

Je remplis la case précédente

Si dans la cellule précédente de la colonne suivante la case était vide je stocke le numero de la ligne.

Je trie mon tableau et vire les ligne stockées.

Très malin!

Je me galérais en essayant de partir de la première colonne et en disant:

Tant que je ne suis pas arrivé à la dernière ligne, si la cellule d'en bas et vide et celle d'en bas à gauche je ne l'ai pas je construir cellule & "," & cellule en bas à droite, et en faisant des goto avec des select cases.. vraiment sâle.

Je l'ai adapté à mon traitement qui ne commence pas en ligne 1 ni col 1 et dont je ne peux pas toucher la structure de la feuille en copiant les données de départ dans un onglet tampon et en balayant depuis le tampon avant de virer l'onglet après avoir remonté en tableaux.

Dans une démarche d'amélioration je vais essayer de le faire directement depuis des tableaux!

@Eric, maintenant le code marche parfaitement, il est très optimisé et très imprésionnant, je vais le passer au crible pour le comprendre! Merci mille fois!

Merci infiniment.

E

Bonjour,

un peu le principe que tu as décris.

Sur chaque ligne, par colonne, je sauvegarde les cat et ss-cat en cours. Puis je regarde en-dessous et en-dessous à gauche. Si une est remplie c'est qu'il y une nouvelle ligne à créer.

eric

Rechercher des sujets similaires à "transformation donnees arbre tableau complet"