Home > Artikel > Ausgabe 10/2013 > Das TreeView-Steuerelement: Verknüpfte Daten, Teil II

Das TreeView-Steuerelement: Verknüpfte Daten, Teil II

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Mit dem TreeView-Steuerelement zeigen Sie nicht nur die Daten aus mehreren hierarchisch verknüpften Tabellen an, sondern auch solche aus Tabellen mit reflexiver Verknüpfung. Das gängige Beispiel hierfür sind Vorgesetzte und ihre Mitarbeiter. Dieser Artikel zeigt die notwendigen Tabellen sowie die Funktion, mit der Sie ein TreeView-Steuerelement mit den gewünschten Daten füllen können.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1310_TreeView.mdb.

Mitarbeiterhierarchie im TreeView-Steuerelement

Ziel dieses Artikels ist es, die Mitarbeiter einer Mitarbeiter-Tabelle hierarchisch in einem TreeView-Steuerelement anzuzeigen. Das Ergebnis sieht beispielsweise wie in Bild 1 aus.

TreeView-Steuerelement zur Abbildung der Mitarbeiter-Hierarchie

Bild 1: TreeView-Steuerelement zur Abbildung der Mitarbeiter-Hierarchie

Formular erstellen

Wir benötigen wieder ein Formular mit einem TreeView-Steuerelement namens ctlTreeView. Das Formular finden Sie in der Beispieldatenbank unter dem Namen frmTreeViewMitarbeiter. Für das Formular stellen Sie die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen und Bildlaufleisten sowie Trennlinien auf Nein, die Eigenschaft Automatisch zentrieren auf Ja ein. Außerdem legen Sie für die Eigenschaft Rahmenart des TreeView-Steuerelements den Wert Durchgezogen fest (siehe Bild 2).

Basis für das zu füllende Formular mit TreeView-Steuerelement

Bild 2: Basis für das zu füllende Formular mit TreeView-Steuerelement

Die übrigen Eigenschaften des TreeView-Steuerelements definieren wir wie gewohnt über die entsprechenden VBA-Eigenschaften, die in der Ereignisprozedur Form_Load eingestellt werden (siehe Listing 1). Dabei deklarieren wir zunächst eine Objektvariable zum Referenzieren des TreeView-Steuerelements:

Private Sub Form_Load()

     With objTreeView

         .Appearance = ccFlat

         .BorderStyle = ccNone

         .LineStyle = tvwRootLines

         .Style = tvwTreelinesPlusMinusText

         .Font.Name = "Calibri"

         .Font.Size = 9

     End With

     TreeViewFuellen

End Sub

Listing 1: Einstellen der Eigenschaften des TreeView-Steuerelements beim Laden des Formulars und Aufrufen der Funktion zum Füllen.

Dim WithEvents m_Treeview As MSComctlLib.TreeView

Um diese Variable zu füllen und darauf zuzugreifen, legen wir eine Property Get-Prozedur an. Diese prüft, ob die Variable m_TreeView bereits mit einem Verweis gefüllt ist und füllt diesen gegebenenfalls. Der Inhalt von m_Treeview wird dann mit objTreeView zurückgegeben (siehe Listing 2).

Private Property Get objTreeView() As MSComctlLib.TreeView

     If m_Treeview Is Nothing Then

         Set m_Treeview = Me!ctlTreeView.Object

     End If

     Set objTreeView = m_Treeview

End Property

Listing 2: Die Property-Prozedur objTreeView liefert immer einen aktuellen Verweis auf das TreeView-Steuerelement.

Reflexive Tabellen als Datenherkunft

Schauen wir uns nun zunächst die Datenherkunft für das TreeView-Steuerelement an. Diese besteht in unserem Fall aus ein oder zwei Tabellen – je nachdem, ob Sie das Feld zur Verknüpfung eines Mitarbeiter-Datensatzes mit einem anderen Mitarbeiter-Datensatz zur Mitarbeiter-Tabelle oder zu einer weiteren Tabelle hinzugefügt haben.

Im ersten Fall enthält die Tabelle tblMitarbeiter gleich das Feld VorgesetzterID, mit dem der Vorgesetzte des aktuellen Mitarbeiters festgelegt wird (siehe Bild 3). Für die Darstellung der Daten aus dieser Tabelle sind keine weiteren Vorarbeiten nötig.

Die reflexiven Daten kommen aus einer einzigen Tabelle.

Bild 3: Die reflexiven Daten kommen aus einer einzigen Tabelle.

Es kann aber auch sein, dass Sie – was sinnvoller ist – die Informationen über die Beziehung zwischen den Mitarbeitern in einer weiteren Tabelle speichern. In der Beispieldatenbank heißt die Mitarbeitertabelle für diesen Fall tblMitarbeiterOhne. Die Tabelle tblVorgesetzteUntergebene enthält die beiden Felder VorgesetzterID und UntergebenerID, welche die Kombinationen aus Vorgesetztem und Untergebenem definieren. Dies sieht dann beispielsweise wie in Bild 4 aus.

Die Beziehung kann aber auch über eine Verknüpfungstabelle hergestellt werden.

Bild 4: Die Beziehung kann aber auch über eine Verknüpfungstabelle hergestellt werden.

Um die Daten so zusammenzuführen, dass diese wie in der einzelnen Tabelle tblMitarbeiter dargestellt weden, verwenden wir eine Abfrage wie in Bild 5. Diese enthält die Daten der Tabelle tblMitarbeiterOhne und fügt aus der Tabelle tblVorgesetzteUntergebene das Feld VorgesetzterID hinzu.

Im Falle der Verknüpfung führen wir die notwendigen Daten in einer Abfrage zusammen.

Bild 5: Im Falle der Verknüpfung führen wir die notwendigen Daten in einer Abfrage zusammen.

Wichtig ist, dass in der Abfrage allein die Beziehung zwischen dem Feld MitarbeiterID der Tabelle tblMitarbeiterOhne und das Feld UntergebenerID der Tabelle tblVorgesetzteUntergebene definiert ist.

Die Eigenschaften dieser Beziehung stellen Sie so ein, dass die Abfrage alle Datensätze der Tabelle tblMitarbeiterOhne liefert – unabhängig davon, ob es für diesen Mitarbeiter einen über die Tabelle tblVorgesetzteUntergebene festgelegten Vorgesetzten gibt. Ist kein solcher vorhanden, bleibt das Feld VorgesetzterID schlicht leer. Das ist hilfreich, wenn wir gleich die Mitarbeiter der obersten Ebene ermitteln wollen, also solche, für die kein Vorgesetzter festgelegt wurden.

TreeView füllen

Kommen wir zum Füllen des TreeView-Steuerelements mit den Mitarbeiter-Elementen. Dazu ruft die Prozedur Form_Load die Routine TreeViewFuellen auf (siehe Listing 3). Die Routine erstellt ein Recordset auf Basis der Abfrage qryMitarbeiterVorgesetzte, wobei allerdings nur diejenigen Datensätze berücksichtigt werden, deren Feld VorgesetzterID den Wert NULL enthält. Dies entspricht den Mitarbeitern, die keinen Vorgesetzten haben und somit der ersten Hierarchieebene angehören.

Public Sub TreeViewFuellen()

     Dim db As DAO.Database

     Dim rst As DAO.Recordset

     Dim objNode As MSComctlLib.Node

     Set db = CurrentDb

     Set rst = db.OpenRecordset("SELECT * FROM qryMitarbeiterVorgesetzte WHERE VorgesetzterID IS NULL", dbOpenDynaset)

     Do While Not rst.EOF

         Set objNode = objTreeView.Nodes.Add(, , "m" & rst!MitarbeiterID, rst!Mitarbeiter)

         objNode.Expanded = True

         TreeViewFuellen_Rekursiv db, rst!MitarbeiterID

         rst.MoveNext

     Loop

End Sub

Listing 3: Die Prozedur TreeViewFuellen füllt die erste Ebene des TreeView-Steuerelements.

Diese durchläuft die Routine in einer Do While-Schleife. Innerhalb der Schleife fügt sie mit der Add-Methode der Nodes-Auflistung des TreeView-Steuerelements jeweils ein neues Element zum TreeView hinzu und referenziert dieses mit der Objektvariablen objNode.

Die beiden Parameter Key und Text dieser Methode nehmen einen aus dem Buchstaben m und dem Primärschlüsselwert des Mitarbeiters und den Namen des Mitarbeiters entgegen. Damit die auch die untergeordneten Elemente angezeigt werden, stellt die Prozedur noch die Eigenschaft Expanded auf den Wert True ein. Bevor die Do While-Schleife sich um den nächsten Datensatz kümmert, ruft die Prozedur noch die rekursiv definierte Prozedur TreeViewFuellen_Rekursiv auf. Diese erwartet zwei Parameter:

  • den in der Variablen db gespeicherten Verweis auf das aktuelle Database-Objekt und
  • den Primärschlüsselwert für den soeben bearbeiteten Mitarbeiter.

Der Verweis auf das Database-Objekt wird übergeben, damit dieses nicht bei jedem rekursiven Aufruf neu ermittelt werden muss. Und der Mitarbeiter mit dem übergebenen Primärschlüsselwert entspricht dem Vorgesetzten für den beim aktuellen Aufruf der rekursiven Prozedur zu ermittelnden Mitarbeiter.

Die rekursive Prozedur TreeView­Fuellen_Rekursiv ist prinzipiell genauso aufgebaut wie die Funktion TreeView­Fuellen – mit dem Unterschied, dass diese beim Erstellen der TreeView-Einträge noch angeben muss, unter welchem vorhandenen Mitarbeiter der untergebene Mitarbeiter angelegt werden soll (siehe Listing 4). Dies sind die beiden ersten Parameter der Add-Methode:

Public Sub TreeViewFuellen_Rekursiv(db As DAO.Database, lngVorgesetzterID As Long)

     Dim rst As DAO.Recordset

     Dim objNode As MSComctlLib.Node

     Set rst = db.OpenRecordset("SELECT * FROM qryMitarbeiterVorgesetzte WHERE VorgesetzterID = " & lngVorgesetzterID, dbOpenDynaset)

     Do While Not rst.EOF

         Set objNode = objTreeView.Nodes.Add("m" & lngVorgesetzterID, tvwChild, "m" & rst!MitarbeiterID, rst!Mitarbeiter)

         objNode.Expanded = True

         TreeViewFuellen_Rekursiv db, rst!MitarbeiterID

         rst.MoveNext

     Loop

End Sub

Listing 4: Die Prozedur TreeViewFuellen_Rekursive füllt jeweils eine weitere Ebene des TreeView-Steuerelements.

Der Parameter Relative erwartet den Key-Wert des übergeordneten Elements, das in diesem Fall aus dem Buchstaben m und dem mit lngVorgesetzterID übergebenen Zahlenwert zusammengesetzt wird. Der zweite Parameter heißt Relationship und nimmt eine Konstante entgegen, die das Verwandtschaftsverhältnis angibt – in diesem Fall tvwChild für ein untergeordnetes Element.

Markierten Mitarbeiter im Unterformular anzeigen

Ein solches TreeView mit der Mitarbeiter-Hierarchie allein bringt noch keinen großen Nutzen. Also fügen wir diesem noch ein Unterformular hinzu, mit dem Sie die Detaildaten zum aktuell ausgewählten Mitarbeiter anzeigen können.

Dieses heißt sfmTreeViewMitarbeiter und die Daten der Tabelle tblMitarbeiter anzeigen (was in unserem Fall nur drei Felder sind). Fügen Sie diesem Formular also alle Felder der Datenherkunft hinzu, schließen Sie es und ziehen Sie es in den Entwurf des Hauptformulars sfmTreeViewMitarbeiter. Das Ergebnis sollte etwa wie in Bild 6 aussehen.

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!