Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.
In den ersten beiden Teilen der Beitragsreihe haben wir gezeigt, wie Sie die Daten einer Tabelle in Form einer Kreuztabelle ausgeben können. Das ist natürlich auch per Kreuztabellenabfrage möglich, aber wir haben in diesem Fall das Webbrowser-Steuerelement mit einer entsprechenden HTML-Seite verwendet. Der Hintergrund ist, dass wir so Funktionen zum direkten Bearbeiten der Einträge hinzufügen können – vorausgesetzt, dass die Kreuztabelle nur die Werte einer Kombination anzeigt und nicht etwa Domänenfunktionen wie Summen oder Mittelwerte. Wir wollen also die bereits vorhandene Darstellung noch um Funktionen zum Bearbeiten sowie zum Hinzufügen neuer Spalten oder Zeilen erweitern.
Ausgangspunkt ist die in den bereits genannten Beiträgen HTML-Kreuztabelle 1: Basics (www.access-im-unternehmen.de/1161) und HTML-Kreuztabelle 2: Werte bearbeiten (www.access-im-unternehmen.de/1162) erarbeitete Lösung. Hier wollen wir nun folgende Erweiterungen hinzufügen:
- In der oberen Zeile mit den Spaltenköpfen wollen wir rechts ein Plus-Zeichen anzeigen, mit dem der Benutzer eine neue Spalte hinzufügen kann.
- In der linken Zeile mit den Zeilenköpfen wollen wir unten ebenfalls ein Plus-Zeichen unterbringen, das per Mausklick die Möglichkeit zum Anlegen einer neuen Zeile ermöglicht.
- Ein Doppelklick auf einen der Werte soll den entsprechenden Datensatz der Tabelle tblMaterialpreise in einem eigenen Formular öffnen.
Neue Zeilen und Spalten anlegen
Für das Anlegen neuer Zeilen und Spalten haben wir uns weiter oben vorgenommen, rechts neben den Spaltenüberschriften und unter den Zeilenüberschriften jeweils ein Plus-Zeichen anzuzeigen, über das wir eine neue Zeile oder Spalte hinzufügen können. Wir könnten dann, wenn der Benutzer auf eines der beiden Plus-Zeichen klickt, einfach die neue Zeile hinzufügen. Aber geht das wirklich so einfach Nein: Denn unser Algorithmus aus der Prozedur KreuztabelleAnlegen fügt nur Spalten und Zeilen an für Höhen- oder Breitenangaben, zu denen es auch bereits mindestens eine Preisangabe gibt. Dementsprechend haben wir auch gar keine Möglichkeit, Daten so in der Tabelle tblMaterialpreise zu speichern, dass diese allein in der Anzeige einer neuen Zeile oder Spalte münden, ohne selbst einen Preis für die Kombination aus Höhe und Breite zu enthalten.
Also müssen wir uns einen alternativen Weg ausdenken, der wie folgt aussieht könnte: Wenn der Benutzer einen Preis für eine Kombination aus Höhe und Breite angeben möchte, von denen entweder die Höhe oder die Breite oder auch beides noch nicht vorhanden ist, muss er eben einen neuen Datensatz in der Tabelle tblMaterialpreise einfügen, der die gewünschten Werte für Höhe und Breite enthält.
Letztlich wäre es aber intuitiver, wenn der Benutzer einfach auf ein Plus-Zeichen zum Erstellen einer neuen Zeile oder Spalte klickt und dann durch einen Klick auf die entstehenden Zellen mit dem Minus-Zeichen den neuen Preis eingibt.
Was aber benötigen wir, um dies zu realisieren Richtig, wir müssten die verfügbaren Werte für die Höhen und Breiten in jeweils einer weiteren Tabelle vorhalten. In der aktuellen Konstellation ist das auch möglich, denn wir gehen ja erstmal von einem einzigen Material aus. In der Praxis ist unser Ansatz aber natürlich zu kurz gedacht – wir werden auch verschiedene Materialien berücksichtigen müssen, die wir in einer weiteren Tabelle speichern, die etwa tblMaterialien heißt. Auf diese Tabelle verweisen wir dann von der Tabelle tblMaterialpreise aus per Fremdschlüsselfeld. Ebenso können wir auf diese Tabelle dann von den beiden Tabellen zum Speichern von Höhen und Breiten verweisen. Also legen wir diese Tabellen an. Auf das Hinzufügen neuer Zeilen und Spalten kommen wir später zurück – vorher sind noch einige Vorbereitungen und Erweiterungen zu erledigen.
Tabelle zum Speichern der Materialien
Die Tabelle tblMaterialien soll die verschiedenen Materialien aufnehmen, damit wir die Materialpreise nicht nur in Abhängigkeit der Kombinationen von Höhe und Breite, sondern auch in Abhängigkeit von verschiedenen Materialien erfassen können, also etwa 17 mm und 19 mm dicke Spanplatten. Die Tabelle enthält zwei Felder: Das Feld MaterialID ist das Primärschlüsselfeld, das Feld Bezeichnung legt den Namen des Materials fest. Für dieses Feld legen wir einen eindeutigen Index fest, damit jede Bezeichnung nur einmal eingegeben werden kann (siehe Bild 1).
Bild 1: Die Tabelle tblMaterialien
Tabellen zum Speichern von Höhen und Breiten
Die Tabelle zum Speichern der Höhen heißt tblHoehen. Sie enthält ein Primärschlüsselfeld namens HoeheID, das Feld Hoehe zum Angeben der Höhe und das Fremdschlüsselfeld MaterialID, über das die Höhe einem Datensatz der Tabelle tblMaterialien zugeordnet wird. Für die beiden Felder Hoehe und MaterialID legen wir einen eindeutigen, zusammengesetzten Schlüssel fest. So verhindern wir, dass für ein Material die gleiche Höhe doppelt angelegt wird (siehe Bild 2).
Bild 2: Die Tabelle tblHoehen
Die Tabelle tblBreiten bauen wir analog zur Tabelle tblHoehen auf.
Materialpreis nach Material
Schließlich wollen wir der Tabelle tblMaterialpreise noch ein Fremdschlüsselfeld namens MaterialID hinzufügen, mit dem wir den entsprechenden Eintrag der Tabelle tblMaterialien auswählen. Auch hier müssen wir das neue Feld Material-ID in den eindeutigen Index integrieren. Die neue Version der Tabelle sieht nun wie in Bild 3 aus.
Bild 3: Die angepasste Tabelle tblMaterialpreise
Das Datenmodell enthält nun vier Tabellen, die wie in Bild 4 miteinander verknüpft sind.
Bild 4: Aktueller Stand des Datenmodells
Material anlegen
Nun fügen wir einige Einträge zur Tabelle tblMaterialien hinzu, zum Beispiel Spanplatte 17 mm und Spanplatte 19 mm. Anschließend verbinden wir alle Datensätze der Tabelle tblMaterialpreise, die wir bisher angelegt haben, über das Feld MaterialID mit dem ersten der beiden neu angelegten Datensätze der Tabelle tblMaterialien. Das Ergebnis sieht in der Tabelle tblMaterialpreise dann etwa wie in Bild 5 aus.
Bild 5: Inhalt der Tabelle tblMaterialpreise
Außerdem fügen wir in den beiden Tabellen tblHoehen und tblBreiten die Werte ein, die bereits in der Tabelle tblMaterialpreise vorliegen.
Höhen und Breiten verknüpfen
An dieser Stelle fragen wir uns auch: Sollten wir nicht die Felder Hoehe und Breite der Tabelle tblMaterialpreise mit den entsprechenden Datensätzen der Tabelle tblHoehen und tblBreiten verknüpfen Und würde es dann nicht sogar Sinn machen, hier einmal auf einen Autowert in den Primärschlüsselfeldern der beiden Tabellen tblHoehen und tblBreiten zu verzichten und direkt die Werte der Höhen und Breiten in das Primärschlüsselfeld einzutragen Dann hätten wir die für uns interessanten Werte direkt in den gebundenen Spalten der Fremdschlüsselfelder und müssten gar keine Lookup-Abfragen tätigen, um auf die Werte der Tabellen tblHoehen und tblBreiten zugreifen – diese würden dann lediglich zur Beschränkung der möglichen Werte dienen, die in den Fremdschlüsselfeldern Hoehe und Breite eingegeben beziehungsweise ausgewählt werden können.
Das erledigen wir schließlich, indem wir die Beziehungen wie in Bild 6 hinzufügen. Vorher haben wir die Primärschlüsselfelder HoeheID und BreiteID aus den Tabellen tblHoehen und tblBreiten entfernt und die Felder Hoehe und Breite in Primärschlüsselfelder ohne Autowert umgewandelt.
Bild 6: Neue Verknüpfungen im Datenmodell
Werte für neues Material hinzufügen
Damit wir neue Daten zum Spielen haben, fügen wir der Tabelle tblMaterialien einen zweiten Datensatz hinzu (siehe Bild 7).
Bild 7: Neuer Datensatz in der Tabelle tblMaterialien
Außerdem fügen wir in den beiden Tabellen tblHoehen und tblBreiten einige neue Datensätze mit Werten für die neue Materialart ein. Zur Unterscheidung von den Datensätzen für die bereits vorhandene Materialart nutzen wir hier kleinere Werte (100 bis 300) – siehe Bild 8.
Bild 8: Neue Werte für Höhe und Breite für das zuletzt hinzugefügte Material
Schließlich legen wir einige neue Datensätze in der Tabelle tblMaterialpreise für das neue Material an (siehe Bild 9).
Bild 9: Materialpreise für neues Material
Wenn wir nun das Formular mit der Kreuztabelle öffnen, sieht dieses wie in Bild 10 aus. Hier werden nun alle Maße und alle Preise angezeigt – sowohl für die 17 mm als auch für die 19 mm dicken Spanplatten. Leider kann man diese aktuell nur dadurch auseinanderhalten, dass wir für die eine Spanplatte die kleineren Höhen und Breiten und für die andere die größeren festgelegt haben.
Bild 10: Kreuztabelle mit neuen Daten
Damit nur die Werte für eines der Materialien angezeigt werden, fügen wir dem Formular nun ein Kombinationsfeld hinzu, mit dem der Benutzer das Material auswählen kann. Das neue Kombinationsfeld nennen wir cboMaterial-ID. Für seine Eigenschaft Datensatzherkunft legen wir die folgende Abfrage fest:
SELECT MaterialID, Bezeichnung FROM tblMaterialien ORDER BY Bezeichnung;
Damit nur das Feld Bezeichnung im Kombinationsfeld angezeigt wird und nicht das Primärschlüsselfeld Material-ID, stellen wir die Eigenschaft Spaltenanzahl auf 2 und Spaltenbreiten auf 0cm ein.
Nun benötigen wir noch eine Ereignisprozedur, die nach der Auswahl eines neuen Eintrags im Kombinationsfeld die Kreuztabelle neu füllt. Der dazu aufgerufenen Prozedur KreuztabelleErstellen müssen wir auch noch an irgendeiner Stelle die Information mitgeben, für welches Material das Webbrowser-Steuerelement die Preise anzeigen soll.
Die Ereignisprozedur implementieren wir wie folgt:
Private Sub cboMaterialID_AfterUpdate() KreuztabelleErstellen Me!cboMaterialID End Sub
Hier haben wir bereits vorgegriffen, auf welche Art wir das betroffene Material übergeben – nämlich als Parameter der Prozedur KreuztabelleErstellen. Diese erweitern wir um den entsprechenden Parameter. Außerdem fügen wir der Abfrage, welche die anzuzeigenden Daten für die Kreuztabelle in der Prozedur KreuztabelleErstellen ermittelt, ein WHERE-Kriterium mit dem Wert des Parameters hinzu. Das sieht dann gekürzt wie folgt aus:
Private Sub KreuztabelleErstellen(lngMaterialID As Long) ... Set rstSpaltenkoepfe = db.OpenRecordset( _ "SELECT DISTINCT Hoehe FROM tblMaterialpreise WHERE MaterialID = " _ & lngMaterialID & " ORDER BY Hoehe", dbOpenDynaset) ... Set rstZeilen = db.OpenRecordset( _ "SELECT DISTINCT Breite FROM tblMaterialpreise WHERE MaterialID = " _ & lngMaterialID & " ORDER BY Breite", dbOpenDynaset) Do While Not rstZeilen.EOF ... Set rstWerte = db.OpenRecordset( _ "SELECT MaterialpreisID, Preis, Hoehe FROM tblMaterialpreise WHERE MaterialID = " _ & lngMaterialID & " AND Breite = " & rstZeilen!Breite & " ORDER BY Hoehe", dbOpenDynaset) ... Loop End Sub
Außerdem müssen wir noch die Prozedur anpassen, die beim öffnen des Formulars das Webbrowser-Steuerelement füllt und dazu die Prozedur KreuztabelleErstellen aufruft:
Private Sub Form_Timer() ... Me!cboMaterialID = Me!cboMaterialID.ItemData(0) KreuztabelleErstellen Me!cboMaterialID End Sub
Damit sorgen wir nun dafür, dass erstens beim Anzeigen des Formulars, was auch das Ereignis Form_Timer auslöst (siehe erster Teil der Beitragsreihe) der erste Eintrag des Kombinationsfeldes eingestellt wird und zweitens dafür, dass die Prozedur KreuztabelleErstellen mit dem Primärschlüsselwert des gewählten Eintrags aufgerufen wird. Dies führt dann beispielsweise zu einer Ansicht wie in Bild 11.
Bild 11: Preise nur für die gewählte Materialart
Wenn wir nun mit dem Kombinationsfeld den zweiten Eintrag auswählen, geschieht allerdings etwas Unerwartetes – siehe Bild 12. Die Kreuztabelle für die neu ausgewählte Materialart wird unten angefügt! Dies können wir allerdings leicht ändern. Dazu fügen wir vor der Anweisung, mit der wir das neue Tabellenelement anlegen, einen Befehl ein, der die Eigenschaft innerHTML des body-Elements auf eine leere Zeichenkette einstellt:
Bild 12: Zwei Kreuztabellen untereinander
Private Sub KreuztabelleErstellen(lngMaterialID As Long) ... objDocument.body.innerHTML = "" Set objTable = objDocument.createElement("Table") ...
Damit können wir dann über das Kombinationsfeld leicht zwischen den Materialarten wechseln.
Prozedur anpassen, damit auch nicht verwendete Werte in der Kreuztabelle erscheinen
Nun folgt ein weiterer wichtiger Schritt: Wir haben ja bereits die Tabellen tblHoehen und tblBreiten angelegt, damit wir auch schon Höhen und Breiten eingeben können, für die der Benutzer vielleicht noch gar keine Preise festgelegt hat. Dementsprechend werden die Höhen und Breiten auch beim Anzeigen der Spalten und Zeilen in der Kreuztabelle noch nicht berücksichtigt – dort berücksichtigen wir nur die Werte, die bereits in der Tabelle tblMaterialpreise enthalten sind.
Das wollen wir aber nun ändern, damit auch die noch nicht mit Preisen versehenen Kombinationen aus Höhe und Breite bereits angezeigt und dann vom Benutzer in der Kreuztabelle bearbeitet werden können.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
Testzugang
eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel
diesen und alle anderen Artikel mit dem Jahresabo