Flexible Bestellungen: Formulare

Die flexible Handhabung von Bestellungen, Lieferungen und Rechnungen basiert auf einem ausgefeilten Datenmodell. Genauso wichtig ist die Bereitstellung einer Benutzeroberfläche, die alle Möglichkeiten des Datenmodells ausschöpft. In diesem Beitrag lernen Sie die Formulare kennen, die das Aufnehmen von Bestellungen nach Kunde und Kostenstelle, die Erfassung von Lieferungen und die flexible Erstellung von Rechnungen erlauben.

Im Beitrag Flexible Bestellungen: Datenmodell (www.access-im-unternehmen.de/882)haben wir das Datenmodell einer einfachen Bestellverwaltung, nämlich der Südsturm-Datenbank, so erweitert, dass Sie damit neben den eigentlichen Bestelldaten einige weitere Daten erfassen können:

  • Alle Kostenstellen eines Kunden
  • Kostenstelle für jede Bestellposition
  • Lieferungen
  • Lieferpositionen
  • Rechnungen
  • Rechnungspositionen

Diese Daten werden so in Tabellen abgelegt, dass Lieferungen und Rechnungen recht flexibel verarbeitet werden können. Wenn Sie das Datenmodell aufgestellt haben, steht das Fundament – es liegt jedoch noch einige Arbeit vor Ihnen. Wir gehen einmal davon aus, dass wir ein herkömmliches Formular zur Erfassung der Bestellungen verwenden. Dieses wollen wir an dieser Stelle nicht näher beschreiben, sondern uns gleich auf die übrigen Formulare stürzen, mit denen Sie die Lieferungen und die Rechnungsstellung organisieren.

Der Optimalfall

Im besten Fall liegen immer alle bestellbaren Artikel in ausreichender Anzahl vor. Wenn Sie eine Anwendung programmieren, die diesen Fall abdecken soll, sind Sie quasi bereits fertig – Sie können die Lieferscheine und die Rechnungen direkt aus den Bestelldaten füllen und verarbeiten. Nun kommen einige von Ihnen und sagen: “Diesen Optimalfall kann es nicht geben! Niemand kann voraussehen, ob nicht irgendein Wahnsinniger auf einmal Tausende von Exemplaren eines bestimmten, schlecht lagerbaren Artikels bestellt!€ – “Doch, das geht! Haben Sie mal mit Downloadartikeln wie eBooks oder Software gehandelt€

Sie sehen: Nichts ist unmöglich. Wir wollen uns aber nicht auf diesen (nicht mehr allzu seltenen) Fall reduzieren, sondern etwas schaffen, mit dem auch die übrigen Menschen etwas anfangen können.

Wenn das Regal leer ist

In diesem Fall kommt früher oder später eine Bestellung, die nicht sofort komplett beliefert werden kann, weil Artikel nicht mehr in ausreichender Zahl vorrätig sind. Dies kann man auch durch eine sorgfältige Pflege der verfügbaren Artikel nicht gewährleisten. Mittlerweile hängen so viele Abnehmer wie Onlineshop, Telefonverkauf, eBay et cetera an einer Warenwirtschaft, dass es sich kaum verhindern lässt, dass ein Artikel einmal mehr verkauft wird als er vorhanden ist.

Doch das soll kein Problem sein: Zwar ist es für einen Kunden ärgerlich, wenn er den gewünschten Artikel nicht in der angegebenen Zeit erhält, aber besser etwas später als gar nicht.

Also sehen wir in der Anwendung die Möglichkeit vor, dass eine Bestellung nicht vollständig geliefert werden kann. Gleichzeitig sollten wir den Fall abfangen, dass ein Kunde zwei oder mehr Bestellungen aufgibt, die in einer einzigen Lieferung durchgeführt werden können.

Beim Zusammenstellen der Lieferungen betrachten wir also nicht die Bestellung eines Kunden, sondern alle bestellten und offenen Bestellungen dieses Kunden. Dabei kann es natürlich auch sein, dass ein Kunde an einem Tag eine Bestellung durchführt, die bis auf eine Position auch versendet wird. Am nächsten Tag bestellt er erneut etwas. Praktischerweise soll der fehlende Artikel vom Vortag direkt mit dieser Sendung verschickt werden.

Von der Bestellposition zur Lieferposition

Um dies zu erledigen, brauchen wir ein Formular, das alle offenen Bestellpositionen eines Kunden anzeigt und diese zur Übernahme in einer Lieferung anbietet. Dazu benötigen wir zumindest eine Liste aller offenen Bestellpositionen. Wie verarbeiten wir diese dann weiter Es wären beispielsweise folgende Optionen denkbar:

  • Die Positionen werden in einem Unterformular in der Datenblattansicht aufgelistet und mit einem zusätzlichen Steuerelement versehen, mit dem die zu liefernden Positionen markiert werden können.
  • Wir verwenden zwei Listenfelder, wobei die Einträge der Tabelle tblBestellpositionen in einer Liste angezeigt werden und die zu liefernden Positionen in die andere Liste gezogen werden.
  • Man könnte auch zwei Unterformulare (oben für die bestellten Artikel, unten für die zu liefernden Artikel) verwenden, wobei die Einträge des oberen per Doppelklick zum unteren Unterformular hinzugefügt werden.

Weiter hinten schauen wir uns an, wie die dritte Lösung umgesetzt wird. Sie erlaubt es gleichzeitig, die Anzahl der bestellten und der zu liefernden Artikel anzuzeigen und per bedingter Formatierung Fehlmengen farbig hervorzuheben.

Rechnungen erstellen

Schließlich sollen noch die Rechnungen erstellt werden. Dies erfolgt auf Basis der gelieferten Artikel. Diese werden ja komplett in der Tabelle tblLieferpositionen gespeichert, die über die Tabelle tblLieferungen weitere Informationen über den Lieferzeitpunkt referenziert.

Ein Formular soll nun alle noch nicht bezahlten Lieferpositionen eines Kunden anzeigen und deren Auswahl für die Zusammenstellung der Rechnungspositionen erlauben. Auch dieses Formular sehen wir uns weiter unten im Detail an.

Formular zum Zusammenstellen von Lieferungen

Das Formular frmLieferungen zeigt die einzelnen Lieferungsdatensätze an und enthält zwei Unterformulare. Das erste Unterformular heißt frmBestellpositionenOffen und soll alle Einträge der Tabelle tblPositionen anzeigen, die noch nicht oder noch nicht vollständig geliefert wurden. Das bedeutet, dass wir alle Datensätze der Tabelle tblLieferpositionen heranziehen müssen, deren Feld PositionID die jeweilige Bestellposition referenziert, und deren Mengen vergleichen. Ist die Menge der gelieferten Artikel geringer als die bestellte, soll das Formular den Eintrag der Tabelle tblPositionen anzeigen.

Das zweite Unterformular heißt frmLieferpositionen und zeigt alle zur aktuellen Lieferung gehörenden Datensätze an. Der Aufbau des Formulars soll zunächst wie in Bild 1 aussehen, um die betroffenen Daten überhaupt darzustellen. Später legen wir Steuerelemente an, mit denen die Bestellpositionen leicht in die Lieferpositionen übertragen werden können.

pic007.png

Bild 1: Erster Entwurf des Formulars frmLieferungen mit den zu liefernden und den in der aktuellen Lieferung enthaltenen Datensätzen

Das Hauptformular frmLieferungen

Das Hauptformular frmLieferungen ist an die Tabelle tblLieferungen gebunden und zeigt alle Felder dieser Tabelle im oberen Abschnitt des Detailbereichs an. Das Formular dient zum Anlegen neuer Lieferungen, kann aber auch zum Ansehen und Bearbeiten vorhandener Lieferungen dienen.

Das Unterformular sfmBestellpositionenOffen

Das oberste Unterformular des Hauptformulars frmLieferungen soll alle offenen Bestellpositionen für den im Hauptformular ausgewählten Kunden anzeigen. Die Hauptaufgabe besteht nun darin, eine geeignete Datenherkunft für das Formular zu ermitteln.

Diese soll alle Datensätze der Tabelle tblPositionen liefern, die noch nicht durch entsprechende Datensätze in der Tabelle tblLieferpositionen als vollständig ausgeliefert gekennzeichnet sind.

Dazu eine kurze Erläuterung des Datenmodells: Dort gibt es neben der üblichen Tabelle zur Erfassung der Bestellpositionen, tblPositionen, eine ähnliche Tabelle zur Eingabe der Lieferpositionen einer Lieferung (tblLieferpositionen).

Diese referenziert direkt Bestellpositionen in der Tabelle tblPositionen und gibt an, wie viele der dort aufgeführten Mengen die Lieferung enthält. Es kann also mehrere Lieferpositionen zu einer Bestellposition geben. Erst wenn die Summe der in jeder Lieferposition angegebenen Menge von Artikeln gleich der Menge der bestellten Artikel ist, soll die Bestellposition nicht mehr im oberen Unterformular angezeigt werden.

Die benötigte Abfrage muss also die Summe der Menge der Artikel aller Lieferpositionen zusammenfassen, die sich auf eine Bestellposition beziehen, und prüfen, ob deren Menge noch kleiner als die bestellte Menge ist.

Dazu verwenden wir eine Abfrage mit einer Gruppierung. Diese sieht im Entwurf wie in Bild 2 aus und enthält die drei Tabellen tblBestellungen, tblPositionen und tblLieferpositionen. Aus der Tabelle tblBestellungen bezieht die Abfrage das Bestelldatum sowie das Feld KundeID. Über dieses wollen wir später alle Datensätze zu einem bestimmten Kunden ermitteln. Die Tabelle tblPositionen liefert die Felder PositionID, ArtikelID und Menge. Aus tblLieferpositionen stammt schließlich das Feld Menge.

pic008.png

Bild 2: Formular zur Ermittlung der Summen der gelieferten Artikel zu einer Bestellposition

Nun kann es sein, dass die Tabelle tblLieferpositionen keinen, einen oder mehrere Datensätze zu den in der Tabelle tblPositionen enthaltenen Bestellpositionen enthält.

Wenn keine Lieferposition vorliegt, geschieht ohne weitere Vorkehrungen Folgendes: Die Abfrage liefert keinen Datensatz zurück, da sie nur solche Daten anzeigt, für die in allen als Datenherkunft dienenden Tabellen Daten enthalten sind. Damit fielen aber gerade solche Bestellpositionen weg, die noch nicht geliefert wurden – was nicht gerade das Ziel dieser Abfrage ist.

Damit es keine Rolle spielt, ob es bereits Lieferungen zu einer Bestellposition gibt oder nicht, passen wir also wie in der Abbildung die Verknüpfungseigenschaften für die Beziehung zwischen den Tabellen tblPositionen und tblBestellpositionen an. Auf diese Weise bleibt das Feld GelieferteMenge der Abfrage schlicht leer, wenn kein passender Datensatz in der Tabelle tblLieferpositionen vorliegt.

Der zweite Fall ist, dass es genau eine Lieferung für eine Bestellposition gibt. Das ist der Optimalfall: Bei der Lieferung wurde die gewünschte Menge Artikel berücksichtigt, das Feld Menge enthält in beiden Tabellen den gleichen Wert.

Dummerweise erfolgen Lieferungen auch einzelner Bestellpositionen in mehreren Rutschen, sodass wir die Menge aller zu einer Bestellposition gehörenden Lieferpositionen summieren müssen. Und damit kommen wir zum Sinn einer Gruppierung in der Abfrage. Richten Sie diese ein, beispielsweise mit dem Eintrag Summen des Kontextmenüs des Abfrage-Entwurfsrasters, und legen Sie für das Feld GelieferteMenge in der Zeile Funktion den Wert Summe und in allen anderen Feldern den Wert Gruppierung fest.

Angenommen, die Tabelle tblLieferpositionen enthält einige manuell hinzugefügte Datensätze wie in Bild 3 (analog haben wir zuvor einen passenden Datensatz in der Tabelle tblLieferungen angelegt). Dort wird mit dem Feld BestellpositionID die Bestellposition referenziert, auf die sich die unter Menge angegebene Anzahl gelieferter Artikel bezieht.

pic001.png

Bild 3: Beispieldaten für die Tabelle tblLieferpositionen

In der Abfrage qrySfmBestellpositionenOffenBase sollten dann die Anzahlen der bestellten und der gelieferten Artikel gegenübergestellt werden. Und genau so funktioniert es, wie Bild 4 zeigt. Dort erscheint genau für die drei Artikel, deren Lieferung wir manuell in die Tabelle tblLieferpositionen eingetragen haben, je ein Datensatz.

pic002.png

Bild 4: Anzeige der bestellten und der gelieferten Menge Artikel in der Datenherkunft eines Unterformulars

Abfrage der Abfrage

Das entspricht allerdings noch nicht vollständig dem gewünschten Ergebnis: Wir wollten ja nur diejenigen Bestellpositionen erhalten, deren Lieferung noch nicht vollständig ausgeführt wurde.

Also fügen wir zum Feld BestellteMenge noch ein Kriterium hinzu, das in der bereits mit GROUP BY versehenen Abfrage als HAVING-Bedingung integriert wird:

>Nz(Summe([tblLieferpositionen].[Menge]);0)

Damit erhalten wir das gewünschte Ergebnis – die oberen beiden Datensätze der Abbildung verschwinden.

Unterformular zur Anzeige der aktuellen Lieferpositionen

Das Unterformular sfmLieferpositionen soll alle bereits zur im Hauptformular angezeigten Lieferung gelieferten Artikel auflisten. Die Datenherkunft des Formulars soll die LieferpositionID, das Bestelldatum, den Artikel und die gelieferte Menge als anzuzeigende Werte zurückgeben. Außerdem benötigen wir im Unterformular noch das Feld LieferungID, um nur die Lieferpositionen zur aktuellen Lieferung des Hauptformulars herauszufiltern. Die Abfrage enthält die drei verknüpften Tabellen tblBestellungen (für das Bestelldatum), tblBestellpositionen und tblLieferpositionen (s. Bild 5).

pic003.png

Bild 5: Datenherkunft des Unterformulars zur Anzeige der erledigten Lieferpositionen einer Lieferung

In den Detailbereich des Unterformulars nehmen Sie die Felder wie in Bild 6 auf und schließen das Unterformular.

pic004.png

Bild 6: Unterformular zur Anzeige der erledigten Lieferpositionen

Haupt- und Unterformulare zusammenführen

Folgt der interessanteste Schritt: Das Einfügen der Unterformulare in das Hauptformular. Öffnen Sie das Hauptformular frmLieferungen in der Entwurfsansicht und ziehen Sie die beiden Unterformulare sfmLieferpositionenOffen und sfmLieferpositionen untereinander in den Detailbereich des Formulars.

Ein Wechsel in die Formularansicht zeigt, dass das Unterformular sfmLieferpositionenOffen noch nicht mit dem Hauptformular synchronisiert wird – normalerweise füllt Access die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements automatisch, wenn es eine Beziehung zwischen den Daten aus Haupt- und Unterformular erkennt.

Dies ist in diesem Fall nicht möglich – es gibt keine gemeinsamen Felder.

Das Unterformular soll alle anstehenden Lieferpositionen für den Kunden der Lieferung im Hauptformular anzeigen. Also stellen Sie die entsprechenden Eigenschaften wie in Bild 7 jeweils auf das Feld KundeID ein.

pic009.png

Bild 7: Herstellen der Synchronisierung zwischen Haupt- und Unterformular

Beim Hinzufügen des Unterformulars sfmLieferpositionen hat es Access einfacher: Die Daten des Unterformulars sind über das Feld LieferungID mit dem gleichnamigen Feld des Hauptformulars verknüpft, also wird dieses automatisch für die Verknüpfungseigenschaften festgelegt.

Ein Wechseln in die Formularansicht zeigt anhand der wenigen Beispieldatensätze in den Tabellen tblLieferungen und tblLieferpositionen, dass beide Formulare die gewünschten Daten anzeigen (s. Bild 8). Im oberen Formular erscheinen alle bestellten, aber noch nicht vollständig gelieferten Positionen – und das gefiltert nach den Bestellungen des aktuellen Kunden. Das untere Formular zeigt alle bereits vollständig gelieferten Positionen an. Teilweise gelieferte Positionen erscheinen in beiden Listen, wobei oben die gesamte Bestellmenge und die bereits gelieferte Menge angezeigt werden.

pic005.png

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar