Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 5/2016.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Rechnungsbericht

Die Ausgabe von Rechnungen dürfte einer der beliebtesten Anwendungszwecke für die Erstellung von Berichten sein. Gleichzeitig sind Rechnungsberichte aber auch eine der anspruchsvollsten Aufgaben – zumindest, wenn man sämtlichen Schnickschnack wie Zwischensumme und Übertrag, vernünftige Aufteilung der Positionen bei mehrseitigen Berichten, keine letzte Seite ohne wesentliche Informationen et cetera berücksichtigen will. Und wenn Sie dann noch mehrere Rechnungen in einem Bericht abbilden wollen, haben Sie das Ziel erreicht.

Datenherkunft für den Bericht

Als Grundlage verwenden wir die Bestelldaten aus der Suedsturm-Datenbank. We­lche Tabellen Sie für die dem Bericht zugrunde liegende Abfrage benötigen, lässt sich mit einem Blick auf eine herkömmliche Rechnung herausfinden. Für die Anschrift des Kun­den benötigen Sie die tblKunden-Tabelle, den Rest erledigen die in einer m:n-Beziehung ste­henden Tabellen tblBestellungen, tblBestelldetails und tblArtikel. Damit der Kunde weiß, an wen er sich bei Fragen wenden kann, nehmen Sie noch die Tabelle tblPersonal hinzu, die ebenfalls mit der Tabelle tblBestellungen verknüpft ist. Die als Datensatzquelle verwendete Abfrage sieht schließ­lich wie in Bild 1 aus.

 Datensatzquelle für den Rechnungsbericht (qryRechnungsbericht)

Bild 1: Datensatzquelle für den Rechnungsbericht (qryRechnungsbericht)

Den aktuellen Steuergesetzen entsprechend wurde der Tabelle Bestellung noch ein Feld namens Rechnungsnummer hinzugefügt. Das Feld hat den Datentyp Text, um auch Zeichen wie Bindestriche oder Schrägstriche zu ermöglichen. Wie Sie die Rechnungsnummer ermitteln, bleibt Ihnen überlassen. Eine Rechnungs­num­mer muss aber auf jeden Fall eindeutig sein.

Manch einer verwendet eine bei 1 startende Nummerierung in Zusammenhang mit der Jahreszahl (zum Beispiel 2016-01); andere lassen die Kundennummer in die Rech­nungs­nummer einfließen. Wer wichtig wirken möchte, verwendet eine Rechnungs­nummer wie 950 752 0642.

In der Beispieltabelle tblBestellungen ist die ?Rechnungsnummer schlicht eine Kom­bi­nation aus dem Datum der Rechnungstellung und dem Primärschlüssel der Tabelle (etwa 20161009-11077). So können Sie auch einmal nur einfach in den Ordner mit Rechnungen schauen, wenn ein Kunde (oder der Steuerprüfer) dazu eine Frage hat – voraus­gesetzt dort liegen die Rechnungen in chronologischer Reihenfolge vor ...

Mehrwertsteuersätze

Außerdem wurde die Tabelle Artikel um ein Feld namens ?Mehrwertsteuersatz erweitert (s. Bild 2), das zu Testzwecken nicht durchgängig den Wert 7% enthält, wie es für Lebensmittel üblich ist, sondern dem wir hier und da auch mal den Wert 19% hinzugefügt haben. Die Tabelle tblBestelldetails enthält das gleiche Feld, in das bei einer Bestellung der gültige Mehrwertsteuersatz übertragen werden soll – auf diese Weise kann man die Mehrwertsteuersätze für die Tabelle tblArtikel ändern, ohne dass sich dies auf bereits erstellte Datensätze in der Tabelle tblBestellpositionen auswirkt. Wir wollen ja gegebenenfalls auch einmal eine Rechnungskopie drucken können, ohne dass dort wegen geänderter Mehrwertsteuersätze plötzlich neue Rechnungsbeträge herauskommen.

Das neue Feld Mehrwertsteuersatz in der Tabelle tblArtikel

Bild 2: Das neue Feld Mehrwertsteuersatz in der Tabelle tblArtikel

Das Feld Mehrwertsteuersatz haben wir mit dem Datentyp Währung versehen. Auf diese Weise erhalten wir die gewünschte Genauigkeit. Außerdem haben wir das Format auf Prozentzahl eingestellt und die Anzeige der Dezimalstellen auf 0 – sollten einmal Mehrwertsteuersätze wie 19,5% auftauchen, kann man dies nachträglich ändern.

Auf die gleiche Weise haben wir auch die Felder Mehrwertsteuersatz und Rabatt in der Tabelle tblBestelldetails angepasst.

Berechnete Felder

Die Abfrage selbst wurde um ein berechnetes Feld namens Bruttopreis ergänzt, das den Bruttopreis einer jeden Position enthält (siehe Auflistung). Außerdem gibt es noch zwei weitere berechnete Felder namens Netto und MwStBetrag. Sie verwenden in diesem Bericht folgende Felder:

  • Tabelle tblArtikel: ArtikelID, Artikelname, Liefereinheit
  • Tabelle tblBestelldetails: Einzelpreis, Menge, Rabatt, Mehrwertsteuer
  • Tabelle tblBestellungen: BestellungID, KundeID, Bestelldatum, Versanddatum, VersandUeber, Fracht­kosten, Empfaenger, Strasse, Ort, PLZ, Bestimmungsland, Rechnungsnummer
  • Tabelle tblKunden: Firma, Kontaktperson, Strasse, Ort, PLZ, Land
  • Tabelle tblPersonal: Nachname, Vorname, Anrede, DurchwahlBuero
  • Berechnetes Feld ?Bruttopreis: [tblBestelldetails].[Einzelpreis]*[tblBestelldetails].[Menge]* ([tblBestelldetails].[Rabatt]+1)*([tblArtikel].[Mehrwertsteuer]+1)
  • Berechnetes Feld ?Netto: [tblBestelldetails.Einzelpreis]*[Menge]*(1+[Rabatt])
  • Berechnetes Feld MwStBetrag: [tblBestelldetails.Einzelpreis]*[Menge]*(1+[Rabatt])*[Mehr­wertsteuer]

Die letzten beiden Felder werden nicht in der Auflistung der Positionen angezeigt, sondern dienen nur der Ermittlung der Summe der Nettopreise und der Mehrwertsteuer am Ende der Rechnung.

Wenn Sie mit früheren Versionen der Suedsturm-Datenbank experimentiert haben, ist Ihnen vielleicht auch aufgefallen, dass wir den Namen des Feldes Anzahl in der Tabelle tblBestelldetails durch Menge ersetzt haben. Der Grund ist einfach: In der deutschen Version von Access ist Anzahl ein reserviertes Wort, was hier und da zu Problemen führen könnte. Daher haben wir es durch die Bezeichnung Menge ersetzt.

Konzept für die Erstellung des Berichts

Bevor Sie sich an die Erstellung eines Berichts machen, sollten Sie die Daten in Gedanken (oder auch auf dem Papier) kurz auf die einzelnen Bereiche eines Berichts aufteilen und sich überlegen, welche Daten etwa nur auf der ersten Seite angezeigt werden, was passiert, wenn so viele Datensätze vorhanden sind, dass der Bericht über mehrere Seiten geht, und so weiter.

Im vorliegenden Fall haben Sie es mit einem ziemlich großen Berichtskopf zu tun: Dieser enthält den kompletten Briefkopf, die Anschrift des Kunden, Lieferdaten und so weiter. Moment: Ist das wirklich so? Wenn der Berichtskopf bereits kundenspezifische und damit rechnungsspezifische Daten enthält, dann können Sie nur eine Rechnung je Bericht ausgeben. Warum? Weil der Berichtskopf nur einmal je Bericht angezeigt wird. Wenn Sie aber mal einen ganzen Schwung Rechnungen ausdrucken möchten, haben Sie ein Problem: Sie müssen dann schon den gleichen Bericht mehrere Male aufrufen. Natürlich geht das auch, aber in diesem Fall sollen Sie einen Bericht erstellen, der mehrere Rechnungen auf einen Rutsch anfertigen kann.

Also benötigen Sie eine Gruppierung über die einzelnen Bestellungen – als Gruppierungsfeld bietet sich das Feld BestellungID an. Im Gruppenkopf bringen Sie nun alles unter, was Sie sonst in den Berichtskopf packen wollten – Briefkopf, Anschrift, Bestelldaten wie Bestellnummer und so weiter.

Die einzelnen Positionen gehören – ganz klar – in den Detailbereich. Darüber benötigen Sie Feldüberschriften: Diese können Sie auf der ersten Seite direkt im Gruppenkopf unterbringen, auf den folgenden Seiten im Seitenkopf. Dieser darf dann wiederum nicht auf der ersten Seite angezeigt werden – dazu später mehr. Nach der letzten Rechnungsposition folgt noch die Rechnungssumme. Dafür bietet sich der Berichtsfuß an. Auf der Seite mit dem Berichtsfuß soll wiederum kein Seitenfußbereich angezeigt werden.

Wenn Sie dem Kunden ein wenig mehr Komfort bieten möchten, sorgen Sie auch noch für eine Zwischensumme und einen Übertrag. Die Zwischensumme gehört mit in den Seitenfuß, der Übertrag in den Seitenkopf – dieser erscheint aber nur auf den Seiten, die keinen Gruppierungskopf anzeigen. Sie sehen – eine Rechnung ist nicht gerade der trivialste Bericht, der sich mit Access erstellen lässt, und er enthält noch nicht einmal Gruppierungen.

Briefkopf im Berichtskopf oder Gruppenkopf?

Normalerweise würden wir den Briefkopf im Bereich Berichtskopf eines Berichts anlegen. Eigentlich logisch – der erscheint schließlich maximal einmal, und zwar auf der ersten Seite.

Allerdings wollen wir dabei nicht vergessen, dass wir nicht nur eine Rechnung, sondern gegebenenfalls auch mehrere Rechnungen in einem Bericht ausgeben wollen. Das heißt also, dass wir die Daten des Briefkopfs in den Gruppenkopf für die einzelnen Rechnungen packen müssen. So benötigen wir also eine Gruppierung für den Bericht, der die Daten unserer Datenherkunft nach den Datensätzen der Tabelle tblBestellungen gruppiert. Diesen richten Sie wie in Bild 3 ein. Hier wählen Sie außerdem die Eigenschaftswerte mit Kopfzeilenbereich, mit Fußzeilenbereich und Kopfzeile und ersten Datensatz auf einer Seite zusammenhalten aus.

Einrichtung der Gruppierung für den Rechnungsbericht

Bild 3: Einrichtung der Gruppierung für den Rechnungsbericht

Erstellen des ?Gruppenkopfs

Die Erstellung des Gruppenkopfs einer Rechnung ist im Wesentlichen Design-Arbeit und weniger Denksport. Hier bringen Sie den Briefkopf unter, den Block mit der Emp­fän­geradresse und den Block mit den allgemeinen Rechnungsdaten (s. Bild 4).

Einrichtung des Gruppenkopfes für die Rechnung

Bild 4: Einrichtung des Gruppenkopfes für die Rechnung

Hier gibt es folgende Besonderheiten: Das Feld txtPLZUndOrt fasst die Felder PLZ und Ort der Tabelle Kunden zusammen. Wichtig ist hier wie bei anderen Steuerelementen, dass Sie Tabellennamen und Feldnamen von in mehreren Tabellen vorkommenden Feldern durch Punkt getrennt schreiben und in eckige Klammern einfassen. Dies geschieht noch einmal im Gruppenkopf, und zwar im Textfeld txtAnsprechpartner. Dessen Inhalt lautet:

=[Personal.Anrede] & " " & [Personal.Vorname] & " " & [Personal.Nachname]

Die Feldüberschriften werden Sie normalerweise erst im folgenden Schritt beim Füllen des Detailbereichs anlegen, in der Abbildung sehen Sie aber bereits ihre Anordnung.

Anlegen des ?Detailbereichs

Der Detailbereich ist reine Fleißarbeit – abgesehen von einem Feature, das aber erst später hinzukommt, und der Angabe der Rechnungspositionen. Der Detailbereich enthält die Felder Artikelname, Liefereinheit, Bruttopreis, Einzelpreis, Menge, Rabatt, Mehrwertsteuersatz und Bruttopreis, wobei Letzteres das berechnete Feld ist, das Sie der Abfrage weiter oben hinzugefügt haben. Es fehlt noch das ganz linke Feld in der Entwurfsansicht (s. Bild 5). Es heißt txtPosition und besitzt als Steuerelementinhalt den Wert =1. Damit dieses Feld die Position des Artikels für die aktuelle Rechnung, also innerhalb der aktuellen Gruppierung, anzeigt, stellen Sie die Eigenschaft Laufende Summe dieses Feldes auf Über Gruppe ein.

Einrichtung des Detailbereichs

Bild 5: Einrichtung des Detailbereichs

Außerdem fügen Sie das Feld Bruttopreis erneut hinzu (siehe das markierte Feld in der Abbildung). Für dieses stellen Sie die Eigenschaft Sichtbar auf Nein ein sowie Laufende Summe auf Über Gruppe. Geben Sie diesem Feld außerdem die Bezeichnung txtLaufendeSumme. Wir benötigen es später für die Zwischensumme und den Übertrag.

Berechnungen in Berichten oder ?Berechnungen in Formularen

Möglicherweise fragen Sie sich, ob man die Berechnung des Bruttopreises und der anderen berechneten Felder in der Abfrage nicht auch innerhalb des Berichts hätte durchführen können. Die Frage ist berechtigt, da das sogar funktionieren würde. Das Problem ist nur, dass Sie keine datensatzübergreifenden Berechnungen über den Bezug auf das Feld mit dem Berechnungsergebnis durchführen könnten. Ein in der Abfrage berechnetes Feld behandelt Access im Bericht aber wie ein normales Tabellenfeld; hier sind Berechnungen wie etwa das Bilden der Summe über alle Datensätze einer Gruppierung möglich.

Streng genommen würde man im Bericht auch ohne das in der Abfrage berechnete Feld auskommen, aber dann müsste man im Feld zur Berechnung der Summe über mehrere Datensätze Bezug auf die Berechnungsformel nehmen und nicht auf das Feld mit dem Berechnungsergebnis.

Summenbildung im Fußbereich der ?Gruppierung

Im Fußbereich der Gruppierung heißt es: Abrechnen! Hier wird die Summe über die Felder Netto, MwStBetrag und Bruttopreis des Detailbereichs gebildet und schließlich noch der Frachtkostenanteil hinzuaddiert (s. Bild 6).

Steuerelemente für den Fußbereich

Bild 6: Steuerelemente für den Fußbereich

Dazu fügen Sie für die Eigenschaft Steuerelement einfach den Feldnamen ein und fügen die Summe()-Funktion hinzu, sodass beispielsweise =Summe([Netto]) daraus wird.

Achtung: Interessanterweise müssen wir für die Eigenschaft Laufende Summe für die Summentextfelder nicht etwa den Wert Über Gruppe auswählen, sondern den Wert Nein beibehalten (s. Bild 7).

Einstellung der Eigenschaft LaufendeSumme für die Summenfelder

Bild 7: Einstellung der Eigenschaft LaufendeSumme für die Summenfelder

Unterhalb der Rechnungssumme ist ein guter Ort, um die Bankverbindung unterzubringen.

Diese könnte man zwar auch auf der ersten Seite zu den allgemeinen Rechnungsdaten hinzufügen, aber der Rechnungsempfänger wird sich freuen, wenn er zum Begleichen der Rechnung per Online-Banking bei mehrseitigen Rechnungen nicht noch hin- und herblättern muss.

Der Fußbereich greift auf zwei Felder zurück, die sich zwar in der Abfrage, aber nicht im Detailbereich des Berichts befinden: Netto und MwStBetrag. Diese werden aus Gründen der Übersicht nicht in jedem Datensatz angezeigt, sondern nur aufsummiert am Ende der Rechnung.

Feinheiten: ?Zwischensumme und ?Übertrag

Ist abzusehen, dass sich einige Rechnungen über mehrere Seiten erstrecken, macht die Angabe von Zwischensumme und Übertrag Sinn. Die Zwischensumme platzieren Sie im Bereich Seitenfuß des Berichts (s. Bild 8). Zur Ermittlung der laufenden Summe müssen Sie zunächst ein zusätzliches unsichtbares Feld im Detailbereich anlegen. Dieses erhält den Namen txtLaufendeSumme und hat als Steuer­elementinhalt den Wert =BruttoPreis. Damit die laufende Summe nur im Rahmen der aktuellen Rechnung ermittelt wird, stellen Sie die Eigenschaft Laufende Summe auf Über Gruppe ein.

Entwurfsansicht des Seitenfußes mit der laufenden Summe

Bild 8: Entwurfsansicht des Seitenfußes mit der laufenden Summe

Dieses Feld enthält jeweils den Inhalt des gleichen Feldes aus dem vorherigen Datensatz zuzüglich des Inhalts des Feldes Bruttopreis des aktuellen Datensatzes. Das Feld txtZwischensumme im Seitenfuß des Berichts enthält den Inhalt des Feldes txtLaufendeSumme, welcher am Seitenende dem Wert des untersten angezeigten Datensatzes entspricht.

Überschriften für Folgeseiten und Rechnungsübertrag

Fehlen noch die Feldüberschriften für die Folgeseiten in Rechnungen, die über mehr als eine Seite gehen.

Diese platzieren Sie genau wie das Feld zur Anzeige des Rechnungsübertrags im Seitenkopf des Berichts (s. Bild 9). Das Feld zur Anzeige des Übertrags heißt txtUebertrag und ist ungebunden.

Der Seitenkopf in der Entwurfsansicht

Bild 9: Der Seitenkopf in der Entwurfsansicht

Damit es immer den Wert anzeigt, den das Feld txtZwischensumme auf der vorherigen Seite hatte, setzen Sie eine Ereigniseigenschaft ein, die direkt nach der Ermittlung der Zwischensumme ausgelöst wird und das Feld txtUebertrag mit dem aktuellen Wert des Feldes txtZwischensumme füllt. Die entsprechende Routine sieht folgendermaßen aus:

Private Sub Seitenfußbereich_Print(Cancel As Integer, _
     PrintCount As Integer)
     Me!txtUebertrag = Me!txtZwischensumme
End Sub

Rechnungsentwurf im Zusammenhang und Restarbeiten

Wenn Sie den Rechnungsbericht, dessen Entwurf Sie in Bild 10 im Überblick sehen, nun öffnen, werden Sie noch kleinere Schönheitsfehler entdecken.

Entwurf des Rechnungsberichts im Überblick

Bild 10: Entwurf des Rechnungsberichts im Überblick

Es beginnt nicht jede Rechnung auf einer neuen Seite, der Seitenkopfbereich erscheint auch auf der ersten Seite einer Bestellung mit dem Gruppenkopf und der Seitenfuß erscheint auch auf der letzten Seite, wo er eigentlich nicht sichtbar sein sollte. Außerdem werden manche Bereiche mit einem grauen Hintergrund ausgestattet (s. Bild 11). Diese Ungereimtheiten räumen Sie jetzt nacheinander aus.

Der Rechnungsbericht sieht noch nicht perfekt aus.

Bild 11: Der Rechnungsbericht sieht noch nicht perfekt aus.

Aus Grau mach Weiß

Die grauen Bereiche erklären sich durch die Eigenschaft Alternative Hintergrundfarbe von Bereichen, die sich wiederholen können – also Gruppenkopf, Gruppenfuß und Detailbereich. Der Übersicht halber sollen diese standardmäßig mit wechselnder Hintergrundfarbe hinterlegt werden. In unserem Fall ist das eher hinderlich, also stellen wir diese Eigenschaft für alle betroffenen Bereiche auf den gleichen Farbwert ein, den wir auch in der Eigenschaft Hintergrundfarbe vorfinden – unter neueren Access-Versionen etwa Hintergrund 1 statt Hintergrund 1, Dunkler 5% (s. Bild 12).

Deaktivieren der alternierenden Hintergrundfarbe

Bild 12: Deaktivieren der alternierenden Hintergrundfarbe

?Bereiche auf neuer Seite anzeigen

In der aktuellen Fassung beginnt nicht jede Rechnung auf einer neuen Seite, die Rechnungen werden einfach nacheinander weggedruckt. Um die Anzeige jeder Rech­nung auf einer neuen Seite zu erreichen, ist nur eine kleine Änderung vonnöten: Stellen Sie die Eigenschaft Neue Seite des Kopfbereichs der Gruppierung BestellungID auf den Wert Vor Bereich ein. Dadurch wird vor jedem Gruppenkopf ein Seitenumbruch eingefügt.

Seitenkopf und ?Seitenfuß nur auf bestimmten Seiten anzeigen

Nun wenden Sie sich dem Seitenkopf und dem Seitenfuß zu. Der Seitenkopf erscheint dummerweise auch auf der ersten Seite über dem Briefkopf und der Seitenfuß soll nicht auf Seiten angezeigt werden, die den Gruppenfuß enthalten. Würden Sie hier die weiter oben angesprochene Variante des Rechnungsberichts verwenden, bei der jede Rechnung in einem einzelnen Bericht angezeigt wird und sich der Briefkopf mit den allgemeinen Rechnungsdaten im Berichtskopf statt im hier verwendeten Gruppenkopf befindet, wäre das Problem leicht zu lösen: Sie würden dann einfach die Eigenschaft Seitenkopf des Berichts auf den Wert Außer Berichtskopf einstellen (s. Bild 13).

Seitenkopf nicht mit dem Berichtskopf auf einer Seite anzeigen

Bild 13: Seitenkopf nicht mit dem Berichtskopf auf einer Seite anzeigen

Nachdem Sie nun wissen, wie dies normalerweise funktionieren würde, kommen Sie nun zur anspruchsvolleren Variante: Und da ist schon ein wenig Gehirnschmalz notwendig.

Die wichtigste Information, die Sie zum Ein- beziehungsweise Ausblenden von Be­richts­be­reichen haben müssen, ist folgende: Es funktioniert nicht zuverlässig, wenn Sie den Be­reich mit der ?Visible-Eigenschaft sichtbar oder unsichtbar machen.

Auf der sicheren Sei­te sind Sie, wenn Sie die ?Cancel-Eigenschaft der Beim Formatieren-Eigenschaft des je­wei­ligen Bereichs auf True setzen, um die Anzeige des Bereichs zu unterbinden.

Ob einer der beiden Bereiche Seitenkopf oder Seitenfuß angezeigt werden soll, entscheidet sich freilich nicht in der jeweiligen Beim Formatieren-Eigenschaft, sondern in anderen Ereignisprozeduren.

Nun der Reihe nach: Listing 1 enthält das komplette Klassenmodul des Berichts. Die Ereignisprozeduren sind nach der Reihenfolge ihres Auftretens geordnet, wobei das ?Beim Öffnen-Ereignis des Berichts nur einmal ausgelöst wird. Um festzulegen, ob die Anzeige von Seitenfuss oder Seitenkopf unterbunden werden soll, verwenden Sie zwei Boolean-Variablen namens bolCancelSeitenfuss und bolCancelSeitenkopf, die wir im Kopfbereich des Moduls definieren.

Dim bolCancelSeitenfuss As Boolean
Dim bolCancelSeitenkopf As Boolean
Private Sub Report_Open(Cancel As Integer)
     'auf erster Seite wird auf jeden Fall der Gruppenkopf sichtbar, 
     'also Seitenkopf ausblenden
     bolCancelSeitenkopf = True
End Sub
Private Sub Gruppenkopf0_Print(Cancel As Integer, PrintCount As Integer)
     'Seitenfuß soll erstmal nicht ausgeblendet werden...
     bolCancelSeitenfuss = False
End Sub
Private Sub Gruppenfuß1_Print(Cancel As Integer, PrintCount As Integer)
     '... außer, der Gruppenfuß wird angezeigt. 
     'Dann gibt es keinen Seitenfuß.
     bolCancelSeitenfuss = True
     'Und wenn der Gruppenfuß angezeigt wird, erscheint auf der nächsten Seite 
     'eine neue Rechnung, also soll auch der Seitenkopf nicht angezeigt 
     'werden.
     bolCancelSeitenkopf = True
End Sub
Private Sub Seitenfußbereich_Format(Cancel As Integer, _
         FormatCount As Integer)
     'Abbrechen, wenn bolCancelSeitenfuss True ist
     Cancel = bolCancelSeitenfuss
     Me!txtUebertrag = Me!txtZwischensumme
End Sub
Private Sub Seitenfußbereich_Print(Cancel As Integer, _
         PrintCount As Integer)
     'Wenn Seitenfuß, dann auf jeden Fall Seitenkopf auf nächster Seite
     'anzeigen
     bolCancelSeitenkopf = False
End Sub
Private Sub Seitenkopfbereich_Format(Cancel As Integer, _
         FormatCount As Integer)
     'Abbrechen, wenn bolCancelSeitenkopf True ist
     Cancel = bolCancelSeitenkopf
End Sub

Listing 1: Inhalt des Klassenmoduls des Berichts rptRechnungen

Beim Öffnen des Berichts wird das Ereignis Beim Öffnen ausgelöst. Die erste Seite des Berichts enthält logischerweise die erste Seite einer Rechnung. Daher wird hier auf jeden Fall der Gruppenkopf der Rechnung angezeigt; der Seitenkopf soll dann nicht erscheinen – die Variable bolCancelSeitenkopf wird auf True eingestellt:

bolCancelSeitenkopf = True

Vor dem Anzeigen des Gruppenkopfs wird dessen Beim Drucken-Ereignis ausgelöst. Hier wird die Variable bolCancelSeitenfuss prophylaktisch auf False eingestellt:

bolCancelSeitenfuss = False 

Das kann sich allerdings schnell ändern, wenn die Gruppierung so wenige Datensätze enthält, dass der Gruppenkopf noch auf der gleichen Seite angezeigt wird. Das dann ausgelöste Ereignis ?Beim Drucken des Gruppenfußes stellt die Variable bolCancelSeitenfuss dann auf True ein:

bolCancelSeitenfuss = True

Damit steht auch fest, dass auf der nächsten Seite eine neue Rechnung beginnt – der Seitenkopf soll also wieder dem Gruppenkopf weichen: Dazu erhält die Variable bolCancelSeitenkopf ebenfalls den Wert True:

bolCancelSeitenkopf = True 

Geht es dann an das Formatieren des Seitenfußes, prüft das Ereignis Beim Formatieren den Wert bolCancelSeitenfuss und weist diesen dem Cancel-Parameter zu. Ist dieser True, wird der Bereich nicht angezeigt.

Cancel = bolCancelSeitenfuss

In dieser Prozedur befindet sich ja auch die Anweisung, die den Wert des Feldes txtUebertrag auf den Wert des Feldes txtZwischensumme einstellt und die wir bereits weiter oben besprochen haben:

Me!txtUebertrag = Me!txtZwischensumme

Soll der Bereich doch angezeigt werden, wird nach dem Beim Formatieren-Ereignis auch noch das Beim Drucken-Ereignis ausgelöst. In diesem stellen Sie dann direkt die Variable bol­CancelSeitenkopf auf den Wert False ein, denn wenn noch nicht die letzte Seite der Rech­nung erreicht ist, soll auf der Folgeseite auf jeden Fall der Seitenkopf angezeigt werden:

bolCancelSeitenkopf = False

Schließlich kommen wir noch zum Ereignis Beim Formatieren des Seitenkopfes. Dieser soll ja nur eingeblendet werden, wenn es sich um eine Folgeseite handelt – also wenn bolCancelSeitenkopf gleich False ist. Anderenfalls wirkt sich die Einstellung von Cancel auf bolCancelSeitenkopf so aus, dass die Anzeige des Seitenkopfes unterbunden wird:

Cancel = bolCancelSeitenkopf

Es ist etwas Aufwand, aber auf diese Weise zeigt der Bericht jede Rechnung auf einer einzelnen Seite an (s. Bild 14).

Jede Rechnung auf einer eigenen Seite anzeigen

Bild 14: Jede Rechnung auf einer eigenen Seite anzeigen

Mehrseitige Rechnungen?

Nun fehlt allerdings noch die Feuerprobe, denn das Beispiel aus dem vorherigen Screenshot zeigt ja nur eine einfache Rechnung, die auf eine Seite passt. Was geschieht, wenn wir eine Bestellung zusammenstellen, deren Positionen auf der Rechnung gerade eben auf die erste Seite passen – an welcher Stelle wird dann der Bericht umgebrochen?

Dazu fügen wir zu einer Bestellung in der Tabelle tblBestellpositionen einige Einträge hinzu und schauen zwischendurch immer mal wieder, was geschieht. Leider kann man den geöffneten Bericht nicht aktualisieren, aber Sie bekommen das Wechseln in eine andere Ansicht und zurück schnell mit der Tastenkombination Strg + Komma, Strg + Punkt hin.

Wenn wir also nun genügend Rechnungspositionen angelegt haben, um so einen Seitenumbruch zu erhalten, zeigt sich die Ansicht aus Bild 15. Das ist nicht das erhoffte Ergebnis, denn die Berichtssummen sollen nicht allein auf der letzten Seite der Rechnung stehen.

Der Seitenumbruch erfolgt nicht an der erhofften Stelle, sondern genau nach der letzten Bestellposition.

Bild 15: Der Seitenumbruch erfolgt nicht an der erhofften Stelle, sondern genau nach der letzten Bestellposition.

Zumindest ein Datensatz der Tabelle tblBestellpositionen sollte noch auf diese Seite rutschen, allein damit die Spaltenüberschriften nicht so allein dastehen. Zum Glück haben wir in diesem Bericht eine feste Höhe für jeden Detailbereich, sodass wir zählen können, wieviele Datensätze auf die erste Seite passen. Sobald die entsprechende Anzahl erreicht ist, wollen wir dann zur neuen Seite wechseln.

Aber wie soll das funktionieren? Ganz einfach: Wir fügen unten im Detailbereich ein Steuerelement des Typs Seitenumbruch ein und nennen es ctlSeitenumbruch.

Dann legen wir für das Ereignis Beim Formatieren des Detailbereichs die folgende Prozedur an:

Private Sub Detailbereich_Format(Cancel As Integer, _
         FormatCount As Integer)
     Me!ctlSeitenumbruch.Visible = False
     Select Case Me!txtPosition
         Case 23, 66, 109
             Me!ctlSeitenumbruch.Visible = True
     End Select
End Sub

Wir haben direkt auch noch experimentell ermittelt, dass auch beim 66. und beim 109. Datensatz ein Seitenumbruch eingefügt werden soll, wenn die Rechnung so viele Datensätze enthalten sollte.

Dies funktioniert nun – der letzte Datensatz rutscht mit auf die nächste Seite. Allerdings haben wir nun immer einen unschönen Leerraum unten auf der ersten Seite zwischen dem letzten Datensatz der Seite und dem Seitenfuß (s. Bild 16). Leider schließt sich der Seitenfuß nicht immer direkt an den letzten Datensatz an, wie es beim Berichtsfuß der Fall ist. Aber auch dafür wird sich eine Lösung finden.

Nun gelangt der letzte Artikel auf die Seite mit der Rechnungssumme.

Bild 16: Nun gelangt der letzte Artikel auf die Seite mit der Rechnungssumme.

Seitenfußbereich direkt unter letzter Rechnungsposition

Welche Möglichkeit haben wir also, um den Seitenfußbereich etwas näher an den letzten Datensatz auf der Seite heranzubekommen?

Mit ein wenig Experimentierfreude gelingt auch das. Es stellt sich heraus, dass man den Seitenfuß-Inhalt durchaus nach oben verschieben kann, wenn man die Höhe des Seitenfußes vergrößert. Dies erledigen wir ebenfalls in der Ereignisprozedur Detailbereich_Format, und zwar, indem wir den Wert der Height-Eigenschaft für diesen Bereich auf 3000 einstellen:

Private Sub Detailbereich_Format(Cancel As _
         Integer, FormatCount As Integer)
     Me!ctlSeitenumbruch.Visible = False
     Select Case Me!txtPosition
         Case 23, 66, 109
             Me!ctlSeitenumbruch.Visible = True
             Me.Seitenfußbereich.Height = 3000
     End Select
End Sub

Das Ergebnis aus Bild 17 sieht überzeugend aus. Allerdings lässt sich diese Lücke nicht wieder verkleinern. Wenn Sie nun eine Rechnung ausgeben, die mehr als zwei Seiten füllt, erhalten Sie unten den gleichen Abstand wie zuvor – allerdings wird der Seitenfuß gleichzeitig wieder ganz unten gedruckt.

Das Verschieben des Seitenfußes gelingt.

Bild 17: Das Verschieben des Seitenfußes gelingt.

An dieser Stelle machen wir daher einen Schritt zurück und geben uns mit dem kleinen Leerraum zufrieden.

Rechnungen stellen ist mehr als Berichte drucken …

Zum Schluss darf der Hinweis nicht fehlen, dass Sie Rechnungen unbedingt dokumen­tie­ren sollten – am besten, indem Sie Rechnungen und die enthaltenen Positionen in se­paraten Tabellen sichern.

Das ist unumgänglich, wenn Sie die Rechnung später noch ein­mal ausdrucken möchten – ansonsten laufen Sie Gefahr, dass die Rechnung einen völ­lig anderen Betrag enthält, weil sich beispielsweise in der Zwischenzeit die Mehr­wert­steuer erhöht hat.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Download

Download

Die .zip-Datei enthält folgende Dateien:

Rechnungsbericht.accdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.