Home > Artikel > Ausgabe 9/2016 > Nährwertdatenbank

Nährwertdatenbank

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).

Es gibt eine ganze Menge Objekte auf der Welt, die sich abseits der üblichen Adress- und Kundendaten in einer Datenbank verwalten lassen. Auf der Suche nach weniger trivialen Inhalten stießen wir auf die Daten von Lebensmitteln und deren Nährwerten – in Zeiten zunehmender Verunsicherung in Sachen Ernährung möglicherweise ein interessantes Thema. Herausgekommen ist eine Anwendung mit einer zusätzlichen Rezepteverwaltung und einem Kalorienrechner.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1609_Naehrwerte.accdb

Lebensmittel und Nährwerte

Im Netz lassen sich zahlreiche Datensammlungen zu Lebensmitteln und deren Nährwerten finden. Die Qualität dieser Daten ist allerdings sehr inhomogen. Im einen Fall ist der Umfang zu gering, im anderen stimmen die Inhalte teilweise nicht. Größer ist allerdings das Problem mit den Datenformaten. Man findet die Tabellen im Text- oder CSV-Format, als Excel-Files oder gar als SQL-Postgres-Dump. Derlei zieht eine Konvertierung zu Access nach sich, die meist mit Nachbearbeitungen verbunden ist. Doch selbst dann, wenn Sie eine originäre Access-Datenbank zum Download finden, stehen Sie häufig vor Problemen.

Ein gutes Beispiel ist die regelmäßig aktualisierte Datenbank des US-Landwirtschaftsministeriums (Link), die unter anderem auch im ACCDB-Format vorliegt. An Vollständigkeit lässt diese Datenbank mit ihren etwa 9.000 Datensätzen nichts zu wünschen übrig. Indessen ist ihre Nomenklatur komplett englisch und weiter das Datenmodell mit den 13 Tabellen so verzweigt, dass sich ihre Verwendung für eine simple Nährwertdatenbank praktisch ausschließt.

Lange Rede, kurzer Sinn: Unsere Nährwerttabelle leitet sich aus mehreren Quellen ab, die schließlich über Konvertierungen und Anfüge- wie Aktualisierungsabfragen erhalten wurde. Wir sehen davon ab, hier das erfolgte Procedere zu beschreiben. Ergebnis ist ein Datenpool mit circa 12.000 Datensätzen, die jeweils 48 Kennzahlen enthalten. Die hohe Zahl ist dem Umstand geschuldet, dass nicht nur elementare Lebensmittel verzeichnet sind, sondern auch zusammengesetzte Produkte, wie etwa der Allgäuer Käsesuppentopf oder die Schweinezunge mit Weißweinsoße, also Imgrunde fertige Rezepturen.

Datenmodell

Einfacher geht's nicht: Die Nährwertdaten befinden sich alle in nur einer Tabelle tblNaehrwerte, die sich rechts in Bild 1 findet. Die ID als Autowert stellt den Primärschlüssel der Tabelle, das Feld Nahrungsmittel seine Bezeichnung. Es ist ebenfalls mit einem eindeutigen Index versehen, um Doppelungen auszuschließen. Darauf folgen 48 Felder zu allen möglichen Kennzahlen, wie der Gehalt an Calcium, Fett, oder Aminosäuren. Diese Zahlenfelder sind allesamt als Double definiert. Den Entwurf der Tabelle zeigt Bild 2. Verbunden mit der Nährwerttabelle sind tblRezepte und tblRezepteZutaten. In der ersten werden die angelegten Rezepte namentlich verzeichnet, wobei im Rezept zusätzlich die gedachte Portionen-Menge spezifiziert ist. Die zweite verknüpft Rezepte und Nahrungsmittel n:m. Ein Rezept kann demnach mehrere Nahrungsmittel enthalten, deren Menge in der Verknüpfungstabelle als Double-Zahl für das Gewicht in Gramm aufgeführt ist.

tblNaehrwerte im Entwurf

Bild 1: tblNaehrwerte im Entwurf

Das ziemlich überschaubare Datenmodell der Nährwertdatenbank

Bild 2: Das ziemlich überschaubare Datenmodell der Nährwertdatenbank

Zur Laufzeit sieht die Nährwerttabelle als Datenblatt aus, wie in Bild 3. Sie können sie schon hier über die Filterpfeile der Spaltenköpfe gemäß Ihrer Kriterien filtern und sortieren. Sortieren Sie etwa absteigend nach Eiweiß, um die Lebensmittel mit dem höchsten Eiweißgehalt zu ermitteln.

So präsentiert sich ein Teil der 50 Felder der Haupttabelle tblNaehrwerte in der Datenblattansicht

Bild 3: So präsentiert sich ein Teil der 50 Felder der Haupttabelle tblNaehrwerte in der Datenblattansicht

Sehr unpraktisch sind indessen die vielen Felder, die ein horizontales Scrollen erfordern, sodass die Daten eines Lebensmittels auch auf einem großen Monitor nie auf einen Blick zu sehen sind. Hier muss ein Formular mit Detailfeldern her!

Nährwerteformular

Bei 12.000 Datensätzen ist das Auffinden eines Lebensmittels eigentlich nur über eine Suchfunktion praktikabel. Deshalb statten wir unser Formular auch mit einer solchen aus. Bild 4 zeigt den Aufbau. Rechts oben befindet sich das Textfeld zur Eingabe eines Suchbegriffs. Unmittelbar nach jedem Tastendruck soll sich dabei die Liste der Nahrungsmittel links im Unterformular sfrmList kontinuierlich aktualisieren. Bei diesem Unterformular auf Basis des Formulars sfrmNahrungsmittel handelt es sich um ein schlichtes Formular in Datenblattansicht, welches aus der Tabelle tblNaehrwerte nur die Lebensmittelbezeichnungen über diese Abfrage auflistet:

Das Nahrungsmittelformular im Entwurf enthält zwei Unterformulare

Bild 4: Das Nahrungsmittelformular im Entwurf enthält zwei Unterformulare

SELECT ID, Nahrungsmittel

FROM tblNaehrwerte

ORDER BY Nahrungsmittel;

Wird in dieser Liste ein Lebensmittel angeklickt, so sollen im Unterformular sfrmDetail rechts dessen Daten erscheinen. Das hier verwendete Formular sfrmNahrungsmittel_E ist direkt an die Tabelle tblNaehrwerte gebunden und sieht im Entwurf aus, wie in Bild 5. Das Hauptformular selbst ist, wohlgemerkt, an gar keine Datenherkunft gebunden! Damit entfallen auch etwaige Feldverknüpfungen zwischen Haupt- und Unterformularen.

Das Detailunterformular sfrmNahrungsmittel_E im Entwurf

Bild 5: Das Detailunterformular sfrmNahrungsmittel_E im Entwurf

Aufgabe der VBA-Routinen des Formulars also ist es, einerseits die Filterung des Datenbestands über das Suchfeld zu erreichen, andererseits eine aktive Verbindung zwischen Listenunterformular links und Detailunterformular rechts herzustellen. Im Betrieb präsentiert es sich etwa wie in Bild 6. Als Suchbegriff wurde hier Weizenbr eingegeben. Wie an der Liste links zu erkennen, filtert die Datenbank nicht nach dem Anfang des Begriffs, sondern nach dem Inhalt, also LIKE. Folglich tauchen auch die Knäckebrot-Weizenbrote im Ergebnis auf. Markiert aber wurde das Weißbrot-Weizenbrot, dessen Detaildaten darum rechts im Formular erscheinen.

So sieht das Nahrungsmittelformular schließlich in Aktion aus

Bild 6: So sieht das Nahrungsmittelformular schließlich in Aktion aus

Dort sind von den 48 Feldern tatsächlich nur 32 untergebracht. Es handelt sich dabei um die relevantesten Kennwerte. Die restlichen sind eher akademischer Natur und aus Platzgründen außen vor gelassen. Tragen Sie diese selbst nach, wenn Sie möchten.

Datentechnisch sind die drei verbundenen Formulare also alles andere als komplex. Legen wir unser Augenmerk deshalb auf deren VBA-Steuerung. Beim Laden des Hauptformulars tritt bereits eine Filterung ein, die dafür sorgen soll, dass beide Unterformulare leer erscheinen:

Private Sub Form_Load()

   Me!sfrmList.Form.Filter = _

       "Nahrungsmittel='_Lebensmittel'"

   Me!sfrmList.Form.FilterOn = True

   Me!txtSuche.SetFocus

End Sub

Hier wird für das Listenunterformular sfrmList ein Filter gesetzt, der die Datensätze auf genau einen begrenzt, nämlich auf jenen mit der Bezeichnung Lebensmittel. Das ist ein spezieller Dummy-Datensatz in tblNaehrwerte, dessen Feldinhalte bis auf die Bezeichnung alle leer gelassen wurden. Ergo findet sich im Listenunterformular lediglich der Eintrag Lebensmittel. Das Detailunterformular sfrmDetail zeigt ebenfalls diesen Datensatz an. Wie das, wo dieses doch in der Load-Prozedur des Hauptformulars gar keiner Behandlung unterzogen wird?

Der Trick liegt in einer Prozedur des Listenformulars. Im Ereignis Beim Anzeigen läuft die Routine in Listing 1 ab. Hier wird über Me.Parent auf sein Elternformular Bezug genommen. Das enthält wiederum das Unterformular sfrmDetail als Steuerelement.

Private Sub Form_Current()

     On Error Resume Next

     Me.Parent!sfrmDetail.Form.Filter = "ID=" & Me!ID.Value

     If Err.Number = 0 Then

         Me.Parent!sfrmDetail.Visible = True

         Me.Parent!sfrmDetail.Form.FilterOn = True

     End If

End Sub

Listing 1: In der Current-Prozedur des Listenformulars wird das Detailformular sfrmDetail des Haupt- und Elternformulars angesprochen und gefiltert

Seine Filtereigenschaft wird auf dieselbe Datensatz-ID gesetzt, die im Listenunterformular aktuell markiert ist – und das wäre, gesteuert über das Hauptformular und dessen Load-Prozedur, nun mal der Datensatz Lebensmittel. Ist die Filterung von Erfolg gekrönt, was die Fehlerbehandlung der Routine durch die Fehlernummer 0 quittiert, so wird das Detailformular auf Sichtbar (Visible) geschaltet und sein Filter aktiviert.

Das Anzeigen des korrekten Datensatzes im Detailunterformular übernimmt also grundsätzlich nicht sein Hauptformular, sondern das Listenunterformular. Dieses Beispiel demonstriert anschaulich den Bezug zwischen Haupt- und Unterformularen über einerseits die Parent-Eigenschaft, und andererseits das Unterformularsteuerelement plus dessen Form-Eigenschaft über VBA.

Formulare filtern

Für das Suchfeld des Hauptformulars, eine Textbox namens txtSuche, ist in der Ereigniseigenschaft Bei Taste Auf (KeyUp) eine Routine angegeben, die das Listenunterformular bei jedem Tastenanschlag entsprechend filtert. Listing 2 bildet sie ab.

Private Sub txtSuche_KeyUp(KeyCode As Integer, Shift As Integer)

     Dim S As String

     

     Select Case KeyCode

     Case Is > 64, Is < 123

         S = Nz(Me!txtSuche.Text)

     End Select

     

     Select Case Len(S)

     Case 0

         Me!sfrmList.Form.Filter = "ID=0"

         Me!sfrmDetail.Visible = False

     Case Is < 4

         Me!sfrmList.Form.Filter = "Nahrungsmittel LIKE '" & S & "*'"

     Case Else

         Me!sfrmList.Form.Filter = "Nahrungsmittel LIKE '*" & S & "*'"

     End Select

     Me!sfrmList.Form.FilterOn = True

End Sub

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!