HTML-Kreuztabelle 2: Werte bearbeiten

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

HTML-Kreuztabelle 2: Werte bearbeiten

Im Beitrag »Kreuztabelle per HTML« 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 im bereits genannten Beitrag HTML-Kreuztabelle 1: Basics (www.access-im-unternehmen.de/1161) genannte Ansicht aus Bild 1. Hier wollen wir nun folgende Erweiterungen hinzufügen:

Diese Ansicht soll um Bearbeitungsfunktionen erweitert werden.

Bild 1: Diese Ansicht soll um Bearbeitungsfunktionen erweitert werden.

  • Wenn der Benutzer auf einen der Einträge für die Zahlenwerte klickt, soll er den angezeigten Wert bearbeiten können. Das Verlassen der Zelle soll den Wert in der zugrunde liegenden Tabelle speichern.
  • 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.
  • Die leeren Zellen wollen wir auf irgendeine Weise anklickbar machen, damit der Benutzer dort auch Werte eintragen kann.
  • Ein Doppelklick auf einen der Werte soll den entsprechenden Datensatz der Tabelle tblMaterialpreise in einem eigenen Formular öffnen.

Tabellenelemente mit ID und der Eigenschaft contentEditable versehen

Um die erste Aufgabe zu erfüllen, müssen wir die unter den Spaltenüberschriften und rechts von den Zeilenüberschriften befindlichen Zellen, die bereits Werte anzeigen, mit eindeutigen Markierungen versehen. Da jeder Datensatz einen Wert der Tabelle tblMaterialpreise repräsentiert, können wir hier mit dem Primärschlüsselwert der entsprechenden Datensätze arbeiten. Dieser landet dann in Form des Attributs id in einem div-Element, welches im td-Element steckt und den eigentlichen Zahlenwert einschließt. Außerdem wollen wir hier die Grundlage für die Bearbeitbarkeit der Elemente legen, indem wir für das gleiche div-Element das Attribut contentEditable auf den Wert true einstellen:

<table>
   <tbody>
     <tr>
       <td class="columnHeader rowHeader"></td>
       <td class="columnHeader">700</td>
       <td class="columnHeader">800</td>
       ...
     </tr>
     <tr>
       <td class="rowHeader">800</td>
       <td>
          <div id="10" contenteditable="true">12</div>
       </td>
       <td>
          <div id="7" contenteditable="true">64</div>
       </td>
       <td>
          <div id="6" contenteditable="true">72</div>
       </td>
       ...
     </tr>
     ...
   </tbody>
</table>

Diese Änderungen erreichen wir leicht, indem wir die Prozedur KreuztabelleErstellen, welche das HTML-Dokument aus objDocument mit dem HTML-Inhalt füllt. Allerdings führen wir gleich noch ein paar weitere Schritte durch, welche die Funktion zum Bearbeiten der Inhalte vervollständigen.

Änderung der Prozedur KreuztabelleErstellen

Die neue Version der Prozedur KreuztabellenErstellen finden Sie in Listing 1.

Private Sub KreuztabelleErstellen()
     ...
     Dim objDivWrapper As clsDivWrapper
     Dim objDiv As MSHTML.HTMLDivElement
     Set colDivs = New Collection
     ...
     Set rstZeilen = db.OpenRecordset("SELECT DISTINCT Breite FROM tblMaterialpreise ORDER BY Breite", dbOpenDynaset)
     Do While Not rstZeilen.EOF
         Set objRow = objTable.insertRow
         rstSpaltenkoepfe.MoveFirst
         Set objCell = objRow.insertCell
         objCell.innerText = rstZeilen!Breite
         objCell.className = "rowHeader"
         Set rstWerte = db.OpenRecordset("SELECT MaterialpreisID, Preis, Hoehe FROM tblMaterialpreise WHERE Breite = " _
             & rstZeilen!Breite & " ORDER BY Hoehe", dbOpenDynaset)
         Do While Not rstWerte.EOF
             If rstSpaltenkoepfe!Hoehe = rstWerte!Hoehe Then
                 Set objCell = objRow.insertCell
                 Set objDiv = objDocument.createElement("Div")
                 objDiv.id = rstWerte!MaterialpreisID
                 objDiv.contentEditable = "true"
                 objCell.appendChild objDiv
                 objDiv.innerText = rstWerte!Preis
                 Set objDivWrapper = New clsDivWrapper
                 Set objDivWrapper.Div = objDiv
                 colDivs.Add objDivWrapper
                 rstWerte.MoveNext
             Else
                 Set objCell = objRow.insertCell
             End If
             rstSpaltenkoepfe.MoveNext
         Loop
         rstZeilen.MoveNext
     Loop
End Sub

Listing 1: Ausschnitt aus der Prozedur KreuztabelleErstellen

Hier verwenden wir ein Collection-Objekt, das wir im allgemeinen Teil des Klassenmoduls des Formulars deklarieren wollen:

Dim colDivs As Collection

Die Prozedur Kreuztabellen deklariert dann auch ein paar neue Elemente. Das erste ist ein Objekt des Typs clsDivWrapper. Was das ist, erläutern wir gleich weiter unten:

Dim objDivWrapper As clsDivWrapper

Außerdem deklarieren wir eine Variable des Typs HTML­Div­Element namens objDiv:

Dim objDiv As MSHTML.HTMLDivElement

Damit das Collection-Objekt einsatzbereit ist, füllen wir es mit einer neuen Collection:

Set colDivs = New Collection

Die folgenden Abschnitte sind unverändert, daher haben wir sie im Listing nicht abgebildet. Die Magie bereiten wir in der inneren der beiden verschachtelten Do While-Schleifen vor. Hier erstellen wir mit der createElement-Methode von objDocument zunächst ein neues Objekt des Typs HTMLDivElement und referenzieren es mit der Variablen objDiv. Dann stellen wir dessen Attribut id auf den Primärschlüsselwert des aktuellen Datensatzes des Recordsets rstWerte ein sowie das Attribut contentEditable auf den Wert true.

Außerdem hängen wir das frisch erstellte Element mit der appendChild-Methode an das Objekt objDiv an.

Set objDiv = objDocument.createElement("Div")
objDiv.id = rstWerte!MaterialpreisID
objDiv.contentEditable = "true"
objCell.appendChild objDiv

Was dann geschieht, erklärt sich erst später vollständig, wenn wir die Klasse clsDivWrapper erläutern, die einen Großteil der Arbeit erledigt: Wir erstellen ein neues Objekt auf Basis der Klasse clsDivWrapper und weisen dessen Eigenschaft Div das HTMLDivElement-Objekt aus objDiv zu. Danach hängen wir das Objekt objDivWrapper an die Auflistung colDivs an:

objDiv.innerText = rstWerte!Preis
Set objDivWrapper = New clsDivWrapper
Set objDivWrapper.Div = objDiv
colDivs.Add objDivWrapper

Damit kommen wir zum Inhalt und der Funktion der Klasse clsDivWrapper.

In der Prozedur KreuztabelleErstellen haben wir die Vorbereitung erschaffen und zu jedem Div-Element mit einem Wert des Feldes Preis der Tabelle tblMaterialpreise eine Instanz der Klasse clsDivWrapper erstellt und diese in der global deklarierten Variablen colDivs gespeichert. Diese Klasse nun soll die fehlende Aufgabe übernehmen, nämlich das Speichern geänderter Werte in der Kreuztabelle.

Dazu legen Sie ein neues Klassenmodul namens clsDivWrapper an, dem Sie zunächst zwei Deklarationen hinzufügen:

Private WithEvents m_Div As MSHTML.HTMLDivElement
Private strText As String

Die Variable strText soll den aktuell in der Zelle der Kreuztabelle befindlichen Text speichern, die Variable m_Div nimmt den von der Prozedur KreuztabelleErstellen übergebenen Verweis auf das Objekt des Typs HTMLDivElement auf. Die Deklaration haben wir um das Schlüsselwort WithEvents ergänzt, da wir für dieses Objekt ein oder mehrere Ereignisprozeduren implementieren wollen.

Damit wir der Klasse wie in der KreuztabelleErstellen programmiert den Verweis auf objDiv übergeben können, definieren wir eine Property Set-Prozedur, die wie folgt aussieht:

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.