Excel et VBA Boucle pour alimenter un TreeView

Résolu
loonasia41 Messages postés 3 Date d'inscription samedi 26 avril 2008 Statut Membre Dernière intervention 15 février 2011 - 9 févr. 2011 à 18:32
loonasia41 Messages postés 3 Date d'inscription samedi 26 avril 2008 Statut Membre Dernière intervention 15 février 2011 - 12 févr. 2011 à 16:01
Bonjour à tous,

Je travaille actuellement sur une appli sur Excel & VBA.
J'ai crée dans un fichier Excel une userform permettant d'ouvrir et de lire des fichiers texte.
Mon fichier texte a toujours la même structure :
ID Valeur
001 Valeur1
002 Valeur2
003 Valeur3
004 Valeur4
005 Valeur5
005 Valeur6
001 Valeur7
002 Valeur8
003 Valeur9
004 Valeur10
005 Valeur11

En premier, j'ouvre et je lis mon fichier texte puis j'alimente une ListView avec toutes les valeurs du fichier.
En second, je liste dans un TreeView toutes les valeurs correspondant à un ID égal à 002.
En dernier, je souhaite alimenter un second treeview par rapport à la valeur sélectionnée dans le TreeView1.

Exemple mon fichier texte :

001 Valeur1
002 Valeur2
003 Valeur3
004 Valeur4
005 Valeur5
005 Valeur6
001 Valeur7
002 Valeur8
003 Valeur9
004 Valeur10
005 Valeur11

Alimentation du TreeView1, j'affiche :
Valeur2
Valeur8

Alimentation du TreeView2, je souhaite afficher:
au click sur Valeur2:
Valeur1
Valeur3
Valeur4
Valeur5
Valeur6
au click sur Valeur8:
Valeur7
Valeur8
Valeur9
Valeur10
Valeur11

Je bloque sur la construction d'une boucle pour alimenter ce deuxième TreeView.


Pour le moment, j'affiche toutes les informations peu importe l'élément sélectionné dans le 1er TreeView:
Private Sub TreeView1_Click()
'*********************************************************************************
'                   Alimentation du TreeView2
'*********************************************************************************
Dim e As Long, j As Long

TreeView2.Nodes.Clear


For e = 1 To ListView2.ListItems.Count
For j = 1 To ListView2.ColumnHeaders.Count - 1

Select Case ListView2.ListItems(e)

Case Is = "001"
TreeView2.Nodes.Add , , , ("Libellé2 : " & ListView2.ListItems(e).ListSubItems(j))

Case Is = "003"
TreeView2.Nodes.Add , , , ("Libellé3 : " & ListView2.ListItems(e).ListSubItems(j))

Case Is = "004"
TreeView2.Nodes.Add , , , ("Libellé4 : " & ListView2.ListItems(e).ListSubItems(j))

Case Is = "005"
TreeView2.Nodes.Add , , , ("Libellé5 : " & ListView2.ListItems(e).ListSubItems(j))

End Select

Next j
Next e

End Sub


Je n'arrive pas à construire une boucle pour obtenir le résultat souhaité...
Quelqu'un aurait il une idée ???
Merci

4 réponses

cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
10 févr. 2011 à 00:01
Ok
Donc, tu pars de ta ListView dans laquelle tu as filtré les données intéressantes.
Ensuite, tu veux pouvoir extraire une fiche complète parmi ces données pour les insérer dans un TreeView, à cette image :
+ S002
  + S001
  + S003
  + S004
  + S005
  + S006
  + S007
    + S007 n°1
    + S007 n°2
    + S007 n°x
Est-ce que cela représente ce que tu veux faire ?

De toute façon, il faudra scruter les items de ta ListView.
Donc, comme tu le disais au début, en choisissant S002, il te faut ressortir S001, puis S003 et suivants jusqu'au xième S007.
Ce xième S007 se trouve avant un S001 ou bien à la fin de la liste.

Il te suffit de faire des boucles Do-Loop :
    Dim mNode       As Node
    Dim mChildNode  As Node
    Dim IndexDépart As Long
    Dim sTemp       As String
    Dim r           As Long
    
    IndexDépart = ListView1.SelectedItem.Index ' un seul item sélectionnable
    If IndexDépart < 1 Then
        MsgBox "Pas possible"
        Exit Sub
    ElseIf ListView1.ListItems.Count < (IndexDépart + 5) Then
        MsgBox "Pas assez de données à suivre"
        Exit Sub
    End If
    
    With TreeView1
        .Nodes.Clear
        ' S002 : Node principal
        sTemp = ListView1.ListItems(IndexDépart).Text
        Set mNode = .Nodes.Add(, , "S002", sTemp)
        ' S001 : avant
        sTemp = ListView1.ListItems(IndexDépart - 1).Text
        Set mChildNode = .Nodes.Add(mNode, tvwChild, "S003", sTemp)
        ' S003 à S006, donc +1 à +4
        r = 1
        sTemp = ListView1.ListItems(IndexDépart + r).Text
        ' Jusqu'à ce que la donnée soit S007
        Do While sTemp <> "S007"
            Set mChildNode = .Nodes.Add(mNode, tvwChild, "S00" & CStr(IndexDépart + r), sTemp)
            r = r + 1
            sTemp = ListView1.ListItems(IndexDépart + r).Text
            DoEvents
        Loop
        ' S007 : Liste des téléphones : On change de Node principal
        Set mNode = .Nodes.Add(mNode, tvwChild, "S007", "Téléphone")
        ' Réinit les variables
        IndexDépart = IndexDépart + r
        ' Insère la donnée lue
        Set mChildNode = .Nodes.Add(mNode, tvwChild, "S007-" & CStr(r), sTemp)
        r = 1
        ' Donnée suivante
        sTemp = ListView1.ListItems(IndexDépart + r).Text
        ' Jusqu'à ce que la donnée ne soit pas S007
        Do While sTemp = "S007"
            Set mChildNode = .Nodes.Add(mNode, tvwChild, "S007-" & CStr(IndexDépart + r), sTemp)
            r = r + 1
            sTemp = ListView1.ListItems(IndexDépart + r).Text
            DoEvents
        Loop
    End With

A affiner en fonction de tes données.
Faut que tu comprennes comment fonctionnent les Nodes dans un TreeView.
3
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
9 févr. 2011 à 19:36
Salut

Pas clair malgré tes belles explications.

[i]au click sur Valeur2:
Valeur1
Valeur3
Valeur4
Valeur5
Valeur6/i
Quelle est la logique permettant de retrouver cette liste ?
C'est l'item -1, plus les 4 items suivants ?
Quel rapport avec l'ID ?

S'il y a plusieurs Id 002 dans ton fichier et que tu veuilles les regrouper dans un TreeView, il faudra :
- Rechercher le Node représentant l'Id 002
- S'il n'existe pas, le créer
- Puis, à partir de ce Node, créer un Child

Exemple basique :
    Dim mNode       As Node
    Dim mChildNode  As Node
    With TreeView1
        Set mNode = .Nodes.Add(, , "Id002", "Node 002")
        Set mChildNode = .Nodes.Add(mNode, tvwChild, "Id002001", "Node 002 001")
        Set mChildNode = .Nodes.Add(mNode, tvwChild, "Id002002", "Node 002 002")
        Set mChildNode = .Nodes.Add(mNode, tvwChild, "Id002003", "Node 002 003")
        mNode.Expanded = True
    End With
A noter : La référence Key permet d'identifier, donc de retrouver facilement un Node, mais deux restrictions majeures :
- Ils doivent être uniques
- Ils doivent commencer par une lettre (pas de chiffres seuls)

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
loonasia41 Messages postés 3 Date d'inscription samedi 26 avril 2008 Statut Membre Dernière intervention 15 février 2011
9 févr. 2011 à 20:53
Merci pour ton aide
Je vais essayer de reformuler mon explication avec un exemple...
Admettons que mon fichier texte liste des informations relatives à des personnes
Dans toutes les informations listées, seules quelques unes m'intéressent pour remplir mon treeview.
Je recherche les informations qui m'intéressent grace au code qui précède l'information.
La dernière information qui m'intéresse peut exister x fois sous la personne.
Exemple :
S000 InformationInutile
S001 ReferencePersonne1
S001001 InformationInutile
S002002 InformationInutile
S002 NomPersonne1
S003 PrenomPersonne1
S003001 InformationInutile
S004 AdressePersonne1
S005 CPPersonne1
S006 VillePersonne1
S007 TelephonePersonne1
S007 TelephonePersonne1
...
S015
...
S052
...
S001 ReferencePersonne2
S001001 InformationInutile
S002002 InformationInutile
S002 NomPersonne2
S003 PrenomPersonne2
S003001 InformationInutile
S004 AdressePersonne2
S005 CPPersonne2
S006 VillePersonne2
S007 TelephonePersonne2
S007 TelephonePersonne2
S007 TelephonePersonne2

Quand je boucle sur toutes les lignes de ma listview avec uniquement les informations qui m'intéressent, j'arrive à obtenir la structure suivante :
S001 ReferencePersonne1
S002 NomPersonne1
S003 PrenomPersonne1
S004 AdressePersonne1
S005 CPPersonne1
S006 VillePersonne1
S007 TelephonePersonne1
S007 TelephonePersonne1
S001 ReferencePersonne2
S002 NomPersonne2
S003 PrenomPersonne2
S004 AdressePersonne2
S005 CPPersonne2
S006 VillePersonne2
S007 TelephonePersonne2
S007 TelephonePersonne2
S007 TelephonePersonne2

Pour la dernière valeur (Téléphone) dans l'exemple, je peux avoir 1 comme 20 valeurs sous la même personne.
La logique serait : pour la valeur S001 ReferencePersonne1, j'extrais les valeurs suivantes S002, S003, jusqu'à S007 tant que je n'ai pas trouvé une nouvelle valeur pour S001 (ReferencePersonne2) et ainsi de suite

J'avais effectivement pensé aux index mais comme j'ai des valeurs qui ne me servent pas et que je ne peux pas determiné à l'avance combien j'aurais de valeurs pour S007 sous la même personne, les informations souhaitées dans mes fichiers ne sont jamais à la même ligne...

J'avais également pensé à une sortie de boucle anticipé Exit for et Exit sub dès lors qu'une seconde valeur S001 est trouvée mais je n'arrive pas à construire ma boucle

J'espère avoir été un peu plus claire, c'est vrai que ce n'est pas évident
0
loonasia41 Messages postés 3 Date d'inscription samedi 26 avril 2008 Statut Membre Dernière intervention 15 février 2011
12 févr. 2011 à 16:01
Bonjour Jack,

je viens de me pencher sur ton code, j'ai réadapté quelques petites choses pour que cela fonctionne dans mon code, ça marche impeccable!
Un grand merci
0
Rejoignez-nous