10/08 2004 - Original udgave
16/08 2004 - Uddybende forklaringer
18/08 2004 - Små rettelser med hjælp fra Mugs :)
Baggrund
Et TreeView kan præsentere data fra flere en til mange relationer på en overskuelig måde. Mange gange ses formulare med 3 eller flere indlejrede underformulare, hvilket kan virke uoverskueligt.
Løsningen er et TreeView, som er opbygget ligesom Windows Stifinder. Brugeren kan folde træet ind og ud ved at klikke på de enkelte elementer kaldet noder. TreeViewet, der findes i Access er desværre ikke dataafhængigt - vi skal selv sørge for at træet er opdateret med de rigtige data fra vores tabeller/forespørgsler.
Mit eksempel er lidt tænkt, men viser principperne for hvordan træet loades med de korrekte data. Mit eksempel skitserer et eller flere firmaer med hver flere afdelinger der igen har flere ansatte med en masse telefoner.
Vi starter med tabellerne:
TabelStruktur
Følgende tabeller oprettes
tAfdeling: afdId, firmaId, afdNavn
tMedarbejdere: medArbId, afdId, medArbNavn
tTelfon: tlfId, medArbId, tlfNr, art
Felterne siger sig selv på nær art, der kan anvendes til at angive om det er privat, mobil e.a.
Det er en fordel at reltionerne sættes rigtigt, ellers vil koden fejle når f.eks en tAnsat ikke er relateret til en tAfdeling.
Det vil være en god ide at indsætte nogle test data, så vi kan se resultatet af vores anstrengelser senere.
Formularen
Der oprettes en formular med:
-liste (Den almindelige fra værktøjskassen)
-et treeview værktøjslinje: værktøjskasse - flere kontrolementer - Micosoft treeView Control
De navngives i egenskabsarket med hhv. lstTlf og ctlTree
I lstTlf sættes 'AntalKolloner' = 4 og
'KolloneBredde = 0cm;3cm;2cm;3cm
Koden
Så kommer det sjove ;o)
Først slettes noderne i træet - dvs. de data der måtte være slettes
Så åbner vi den første tabel som et recordset og løber alle posterne igennem
For hver post oprettes en rodNode med navnet på firmaet som text og firmaId som key. Firmaid'et sættes sammen med ordet "firma" så vi senere ved at noder med ordet "firma" i deres key kommer fra tabellen firma.
Derefter åbnes tabellen tAfdeling og på samme måde som gennemløbes tabellen og for hver post operttes en childNode. Anvendes afdNavnet som nodens text og afdId som key OG den relateres til den Node i træet der har en key med værdien "firma" & firmaId.
På formens VedIndlæsning lægges følgende kode ind:
Private Sub Form_Load()
'Alle noder i træet fjernes
ctlTree.Nodes.Clear
Dim rs As New ADODB.Recordset
' åbner tabellen tFirma og tilføjer en rodNode for hver
' nodens key sættes = "firma" & firmaId for senere at
' bruge den når der vælges en node i træet samt lave
' child noder
rs.Open "tfirma", CurrentProject.Connection
Do While Not rs.EOF
ctlTree.Nodes.Add , , "firma" & rs!FirmaId, rs!firmanavn
rs.MoveNext
Loop
rs.Close
' vi fortsætter med at åbne medarbejdertabellen og
' tiføje en afdeling med reference til rodnodens
' key værdi = firma id
rs.Open "tAfdeling", CurrentProject.Connection
Do While Not rs.EOF
ctlTree.Nodes.Add "firma" & rs!FirmaId, tvwChild, "afd" & rs!AfdID, rs!afdnavn
rs.MoveNext
Loop
rs.Close
rs.Open "tMedarbejdere", CurrentProject.Connection
Do While Not rs.EOF
ctlTree.Nodes.Add "afd" & rs!AfdID, tvwChild, "medArb" & rs!medArbId, rs!medArbNavn
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
End Sub
Det var det nu tegnes træet rigtigt når formen åbnes :o)
Herefter skal listboxen fyldes med telefonnumre fra de firmaer, afdelinger eller ansatte brugeren klikker på.
Der oprettes en SQL sætning (evt cuttet fra forespørgsels designeren) som vi kan arbejde videre på.
Herefter tjekkes om nodens keyValue indeholder ordet firma, afd eller medarb.
Hvis f.eks key indeholder ordet "afd" så barberes de første 3 tegn væk of tilbage står afdId som sættes ind i SQL'en som en where del.
Så er det bare at opdatere lstboxen med den nye SQL
'Hændelsen node_Click indeholder den node der klikkes på
'vi trækker værdien key ud og opdatere listboxen
Private Sub ctlTree_NodeClick(ByVal Node As Object)
'dynamisk foresp til lstboxen
ssql = "SELECT tlfId, MedarbNavn, tlfArt, tlfNr " & _
"FROM (tAfdeling INNER JOIN tMedarbejdere ON tAfdeling.afdId = tMedarbejdere.afdId) INNER JOIN tTelfon ON tMedarbejdere.medarbId = tTelfon.medArbId "
'Hvis key indeholder: "firma" & nr
'ved jeg det er id fra tabellen tFirma.
'"afd" & nr fra tAfdelng osv
If InStr(Node.Key, "firma") Then
ssql = ssql & "where firmaid = " & Mid(Node.Key, 6)
ElseIf InStr(Node.Key, "afd") Then
ssql = ssql & "where tAfdeling!afdId = " & Mid(Node.Key, 4)
ElseIf InStr(Node.Key, "medArb") Then
ssql = ssql & "where tMedarbejdere!medArbId = " & Mid(Node.Key, 7)
Else
ssql = ""
End If
'lstboxen opdateres:
Me.lstTlf.RowSource = ssql
Me.lstTlf.Requery
End Sub
Jeg håber koden er kommenteret godt nok og i kan bruge dette lille eksempel til noget.
Jeg vil i næste udgave vise hvorledes man med en rekursiv procedure kan bygge et træ vha. en tabel
tNode:NodeId, ParrentId, Navn
Niels
Konstruktive kommentare er velkomne
- så kan jeg forhåbentlig forbedre min skrive færdigheder.


