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
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
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...
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
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
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