Es gibt einige Darstellungen, die sich mit Access-Bordmitteln nicht oder nur mit sehr hohem Aufwand realisieren lassen. Dazu gehören beispielsweise alle Konstellationen aus 1:n-Beziehungen mit Unterformularen, bei denen man gern mehr als einen Datensatz im Hauptformular anzeigen würde. Zum Glück erlaubt Access einen Blick über den Tellerrand, und mit dem Webbrowser-Steuerelement und HTML erreichen Sie wohl alle denkbaren Darstellungen – in diesem Fall die Endlosanzeige von 1:n-Beziehungen.
Im vorliegenden Fall sollen alle Abteilungen einer Firma samt den dazugehörigen Mitarbeitern dargestellt werden, und zwar inklusive eines Kontrollkästchens je Abteilung und Mitarbeiter, mit dem man komplette Abteilungen oder einzelne Mitarbeiter aus- und abwählen kann. Das Beispielformular aus Bild 1 gehört zu der Lösung aus dem Beitrag Fehlzeiten verwalten (www.access-im-unternehmen.de/850).
Bild 1: 1:n-Beziehung im Webbrowser-Steuerelement
Das Formular soll die Daten der beiden Tabellen tblAbteilungen und tblMitarbeiter anzeigen, die per 1:n-Beziehung über das Fremdschlüsselfeld AbteilungID der Tabelle tblMitarbeiter miteinander verknüpft sind (s. Bild 3 aussieht. Das Webbrowser-Steuerelement erhält den Namen ctlWebbrowser.
Bild 2: Tabellen der Beispielanwendung
Bild 3: Das Beispielformular in der Entwurfsansicht
Um ein HTML-Dokument mit den Methoden der MSHTML-Bibliothek zu bestücken, benötigen Sie zunächst einen Verweis auf diese Bibliothek. Diesen legen Sie im Verweise-Dialog (Menüeintrag Optionen|Verweise im VBA-Editor) fest (s. Bild 4). Danach können Sie bereits loslegen. Die Prozedur, die durch das Ereignis Beim Laden des Formulars ausgelöst wird, ruft wiederum die Prozedur MitarbeiterAnzeigen auf:
Bild 4: Verweis auf die MSHTML-Bibliothek
Private Sub Form_Load() MitarbeiterAnzeigen End Sub
Der weitere Aufbau wird von der Prozedur MitarbeiterAnzeigen gesteuert (s. Listing 1). Die Prozedur legt zunächst mit der Funktion DokumentAnlegen (s. Listing 2) ein Dokument im Webbrowser-Steuerelement an und speichert einen Verweis darauf in der Variablen objDocument.
Listing 1: Mitarbeiter im Webbrowser-Steuerelement anzeigen
Private Sub MitarbeiterAnzeigen() Dim db As DAO.Database Dim rstAbteilungen As DAO.Recordset Dim rstMitarbeiter As DAO.Recordset Dim objDocument As MSHTML.HTMLDocument Dim objTable As MSHTML.HTMLTable Dim objInnerRow As MSHTML.HTMLTableRow Dim objInnerCell As MSHTML.HTMLTableCell Dim objCheckbox As MSHTML.HTMLInputElement Set colCheckboxes_Mitarbeiter = New Collection Set colCheckboxes_Abteilungen = New Collection Set objDocument = DokumentHolen Set objTable = objDocument.createElement("Table") objDocument.Body.appendChild objTable objDocument.Body.Style.fontFamily = "calibri" objDocument.Body.Style.FontSize = "8px" objTable.Style.borderCollapse = "collapse" Set db = CurrentDb Set rstAbteilungen = db.OpenRecordset("SELECT * FROM qryAbteilungenMitMitarbeitern", dbOpenDynaset) Do While Not rstAbteilungen.EOF Set objInnerRow = ZeileZelleTabelleAnlegen(objDocument, objTable) Set objInnerCell = objInnerRow.insertCell objInnerCell.appendChild CheckboxAbteilungErstellen(objDocument, rstAbteilungen!AbteilungID) Set objInnerCell = objInnerRow.insertCell objInnerCell.innerText = rstAbteilungen!Abteilung Set rstMitarbeiter = db.OpenRecordset("SELECT * FROM qryMitarbeiterauswahl " _ & "WHERE AbteilungID " & rstAbteilungen!AbteilungID, dbOpenDynaset) Do While Not rstMitarbeiter.EOF Set objInnerRow = ZeileZelleTabelleAnlegen(objDocument, objTable) Set objInnerCell = objInnerRow.insertCell objInnerCell.Width = "30px" Set objInnerCell = objInnerRow.insertCell Set objCheckbox = CheckboxMitarbeiterErstellen(objDocument, _ rstMitarbeiter!MitarbeiterID) objInnerCell.appendChild objCheckbox objCheckbox.Checked = Not IsNull(rstMitarbeiter!MitarbeiterAnzeigenID) Set objInnerCell = objInnerRow.insertCell With objInnerCell .innerText = rstMitarbeiter!Bezeichnung .Style.fontFamily = "calibri" .Style.FontSize = "12px" End With rstMitarbeiter.MoveNext Loop rstAbteilungen.MoveNext Loop Set db = Nothing End Sub
Listing 2: Browser mit leerem Dokument füllen
Private Function DokumentHolen() As MSHTML.HTMLDocument Dim objWebbrowser As SHDocVw.WebBrowser Dim objDocument As MSHTML.HTMLDocument Set objWebbrowser = GetWebbrowser DoEvents objWebbrowser.Navigate "about:blank" Do DoEvents Loop Until objWebbrowser.ReadyState = READYSTATE_COMPLETE Set objDocument = objWebbrowser.Document Set DokumentHolen = objDocument End Function
Außerdem erstellt die Prozedur zwei Collection-Objekte, welche später Verweise auf Wrapper-Klassen für die Checkbox-Steuerelemente zum Auswählen der Abteilungen und der Mitarbeiter aufnehmen – dazu später mehr. Wichtig ist erstmal, dass die Collection-Elemente wie folgt im Kopf des Klassenmoduls des Formulars deklariert werden:
Dim colCheckboxes_Mitarbeiter As Collection Dim colCheckboxes_Abteilungen As Collection
Auch die Wrapper-Klassen werden im Kopf des Moduls deklariert:
Dim objCheckboxWrapper_Mitarbeiter As clsCheckboxWrapper_Mitarbeiter Dim objCheckboxWrapper_Abteilung As clsCheckboxWrapper_Abteilung
Nun geht erstmal der Aufbau der Tabellenstruktur im HTML-Dokument weiter. Die Prozedur erstellt ein HTMLTable-Objekt und hängt es als Kind-Element an das HTMLDocument-Element an. Einige Einstellungen bezüglich der Schriftart sorgen später für ein einheitliches Bild.
Danach kommt auch schon die Datenbank mit ihren Tabellen tblAbteilungen und tblMitarbeiter ins Spiel. Genau genommen öffnet die Prozedur zunächst eine Datensatzgruppe auf Basis der Abfrage qryAbteilungenMitMitarbeitern (s. Bild 5). Diese liefert alle Datensätze der Tabelle tblAbteilungen, denen mindestens ein Mitarbeiter angehört. Diese Abteilungen werden in einer Do While-Schleife durchlaufen. Dabei erstellt die Prozedur MitarbeiterAnzeigen zunächst innerhalb einer Funktion namens ZeileZelleTabelleAnlegen einige Elemente im HTMLTable-Objekt, und zwar zunächst ein HTMLRow-Element, darin ein HTMLCell-Element, darin ein HTMLTable-Element und schließlich noch ein HTMLRow-Element (s. Listing 3).
Listing 3: Unabhängige Zeilen anlegen
Public Function ZeileZelleTabelleAnlegen(objDocument As MSHTML.HTMLDocument, _ objTable As MSHTML.HTMLTable) As MSHTML.HTMLTableRow Dim objRow As MSHTML.HTMLTableRow Dim objCell As MSHTML.HTMLTableCell Dim objInnerTable As MSHTML.HTMLTable Dim objInnerRow As MSHTML.HTMLTableRow Set objRow = objTable.insertRow objRow.Style.verticalAlign = "top" Set objCell = objRow.insertCell Set objInnerTable = objDocument.createElement("Table") objInnerTable.Style.borderCollapse = "collapse" objCell.appendChild objInnerTable Set objInnerRow = objInnerTable.insertRow Set ZeileZelleTabelleAnlegen = objInnerRow End Function
Bild 5: Datenherkunft für die äußere Schleife