Anzeige kumulativer Notenhäufigkeiten ◦ ?

Das folgende Beispiel zeigt (ähnlich wie Formatierung von Zuordnungslösungen), dass sich die prozedurale Vorgehensweise manchmal besser eignet als die rein deklarative.

### Benutzersicht

Die Trennung zwischen genügenden und ungenügenden Testleistungen fällt leichter, wenn die Verteilung der kumulierten Notenhäufigkeiten bekannt ist:

### Entwurf

Die folgende Ereignisprozedur reagiert auf die Schaltfläche Kumulierte Noten des Formulars FrmNotenverteilung und erstellt als Datensatzherkunft die Tabelle TmpKUMULATIVE_NOTENHÄUFIGKEITEN für ein bereits definiertes Access-Balkendiagramms. Der folgende Entwurfscode besteht aus der Ereignisprozedur und einer Hilfsroutine:

>     Ereignisprozedur BtnKumulativeProzentualeNotenhäufigkeiten
>       Ermittle für den laufenden Test die Notenzahl
>       Ermittle für alle Noten absolute_Häufigkeiten
>       Ermittle_kumulative_prozentuale_Häufigkeiten(Notenzahl, absolute_Häufigkeiten)
>       Öffne das Access-Balkendiagramm

>     Ermittle_kumulative_prozentuale_Häufigkeiten(Notenzahl, absolute_Häufigkeiten)
>       Kumulierte_absolute_Häufigkeit = 0
>       Für alle einfachen absoluten Häufigkeiten
>         Kumulierte_absolute_Häufigkeit = Kumulierte_absolute_Häufigkeit + absolute_Häufigkeit
>         Kumulative_prozentuale_Häufigkeit = Kumulierte_absolute_Häufigkeit / Notenzahl
>         Füge Note und deren kumulative_prozentuale_Häufigkeit zu TmpKUMULATIVE_NOTENHÄUFIGKEITEN

### Implementation

Der Entwurfscode beschränkt sich auf die Verarbeitungslogik. Unter VBA und dem Objektmodell DAO kommen syntaktische und semantische Details hinzu, die das Verständnis erschweren.

>     '~~~ Datensatzherkunft TmpKUMULATIVE_NOTENHÄUFIGKEITEN des Balkendiagramms DrgNote erstellen
>     Private Sub BtnKumulativeProzentualeNotenhäufigkeiten_Click()
>       '-- Recordset zur Zählung aller Noten des laufenden Tests
>       Dim rstQryPteMCZOEssayLfTest_ohneNamen As Recordset
>       Dim Notenzahl As Integer
>       '-- Recordset der einfachen absoluten Notenhäufigkeiten des laufenden Tests
>       Dim rstQryNotenhäufigkeiten As Recordset
>       '-- Temporäre Tabelle der kumulierten prozentualen Notenhäufigkeiten (Datensatzherkunft von DgrNote)
>       Dim tdf As TableDef
>       Dim tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN As TableDef
>       Dim rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN As Recordset
>       Dim KumulierteAbsoluteHäufigkeit As Integer
>       '-- QueryDef-Objekt zur leichteren Verarbeitung geschachtelter Abfragen mit Parametern
>       Dim qdf As QueryDef

>       With CurrentDb

>         'Ermittle für den laufenden Test die Notenzahl
>         '---------------------------------------------
>         Set qdf = .QueryDefs("QryPteMCZOEssayLfTest_ohneNamen")
>         qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]
>         Set rstQryPteMCZOEssayLfTest_ohneNamen = qdf.OpenRecordset(dbReadOnly)
>         '-- Balkendiagramm nur anzeigen, falls für den laufenden Test mindestens eine Note existiert
>         If Not rstQryPteMCZOEssayLfTest_ohneNamen.EOF Then
>           rstQryPteMCZOEssayLfTest_ohneNamen.MoveLast  'damit der folgende Befehl funktioniert
>           Notenzahl = rstQryPteMCZOEssayLfTest_ohneNamen.RecordCount

>           'Ermittle für alle Noten absolute_Häufigkeiten
>           '---------------------------------------------
>           Set qdf = .QueryDefs("QryNotenhäufigkeiten")
>           'Der folgende Parameter nimmt zur  L a u f z e i t  den Testschlüssel auf
>           qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]
>           Set rstQryNotenhäufigkeiten = qdf.OpenRecordset(dbOpenForwardOnly, dbReadOnly)

>           'Ermittle für alle Noten kumulative prozentuale Häufigkeiten
>           '-----------------------------------------------------------
>           '-- Leere Tabelle und leerer Recordset für die kumulativen prozentualen Notenhäufigkeiten
>           .TableDefs.Delete ("TmpKUMULATIVE_NOTENHÄUFIGKEITEN") 'falls vom letzten Aufruf her vorhanden
>           Set tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN = .CreateTableDef("TmpKUMULATIVE_NOTENHÄUFIGKEITEN")
>           With tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN
>             .Fields.Append .CreateField("Note", dbSingle)
>             .Fields.Append .CreateField("KumulativeProzentualeHäufigkeit", dbSingle)
>           End With
>           .TableDefs.Append tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN
>           Set rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN = .OpenRecordset("TmpKUMULATIVE_NOTENHÄUFIGKEITEN", dbOpenTable)

>           '-- Prozentuale kumulative Notenhäufigkeiten satzweise aus den absoluten Häufigkeiten ermitteln
>           With rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN
>             KumulierteAbsoluteHäufigkeit = 0
>             Do Until rstQryNotenhäufigkeiten.EOF
>               KumulierteAbsoluteHäufigkeit = KumulierteAbsoluteHäufigkeit + rstQryNotenhäufigkeiten!Notenhäufigkeit
>               'Füge Note und deren kumulative prozentuale Häufigkeit an TmpKUMULATIVE_NOTENHÄUFIGKEITEN
>               .AddNew
>                 !Note = rstQryNotenhäufigkeiten!Note
>                 !KumulativeProzentualeHäufigkeit = KumulierteAbsoluteHäufigkeit / Notenzahl
>               .Update
>               rstQryNotenhäufigkeiten.MoveNext
>             Loop
>             .Close  'Recordset als TmpKUMULATIVE_NOTENHÄUFIGKEITEN speichern
>           End With
>           Set rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN = Nothing
>           rstQryNotenhäufigkeiten.Close
>           Set rstQryNotenhäufigkeiten = Nothing

>           '-- Öffne das Access-Balkendiagramm
>           DoCmd.OpenForm "FrmDrgKumulativeNotenhäufigkeiten"
>         Else
>           MsgBox "Ohne Noten kann kein Häufigkeitsdiagramm gezeichnet werden", vbOKOnly + vbExclamation, "Daten fehlen"
>         End If
>       End With 'CurrentDb
>     End Sub

### Abfrageobjekte

Das Objekt QueryDef unterscheidet den obigen Code von den anderen Beispielen zur Satzverarbeitung. Die Themen DAO, Einzelsatzverarbeitung und Navigation durch Recordsets erstellen einen Recordset, indem sie dem DAO-Befehl

OpenRecordset den Namen einer QBE-Abfrage oder den Wortlaut einer SQL-Anweisung übergeben:

> Set Datensätze = laufendeDatenbank.OpenRecordset(<Abfrage>)

Die obige Ereignisprozedur BtnKumulativeProzentualeNotenhäufigkeiten_Click vereinbart hingegen eine Objektvariable qdf und weist ihr eine QBE-Abfrage zu:

> Dim qdf As QueryDef
> Set qdf = CurrentDb.QueryDefs("QryPteMCZOEssayLfTest_ohneNamen")

Auf das erzeugte Abfrageobjekt kann mit Eigenschaften und Methoden zugegriffen werden. Wenn die Abfrage zum Beispiel von einem zur Entwicklungszeit unbekannten Parameter abhängt, dann kann ihm das Programm zur Laufzeit einen Wert zuweisen:

> qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]

Oder die Abfrage kann zur Datensatzherkunft eines Recordset werden:

> Set Datensätze = qdf.OpenRecordset(dbOpenForwardOnly, dbReadOnly)

Code, der auf explizite Abfrageobjekte verzichtet (grau markiert), ist zwar verständlicher, QueryDef-Objekte erleichtern aber die Verwaltung von Parametern und beschleunigen durch eine Kompilieren die Ausführung der Abfrage.