Bericht im RTF-Format weitergeben

Problem

Ich muss regelmäßig Berichte im Word- Format (DOC oder RTF) auf einem Netzwerklaufwerk ablegen. Die Erstellung des Berichtes und der Export ins Netzwerk sollen über ein Makro ausgelöst werden. Wie gehe ich dazu genau vor? Antwort: Dazu nutzen Sie in einem Makro die Aktion „AusgabeIn“ (VBA: Out putTo). Unter „Objekttyp“ stellen Sie „Bericht“ ein, unter „Objektname“ geben Sie den Namen des Berichtes ein. „Ausgabeformat“ wäre „RichText Format“ (Word-Dokument gibt es nicht) und unter „Ausgabedatei“ legen Sie Laufwerk/Pfad/ Dateiname (z. B. „F:\Exporte\Bericht.rtf“) fest. Die beiden letzen Parameter ignorieren Sie, sie sind in diesem Zusammenhang ohne Bedeutung.

Antwort:

Dazu nutzen Sie in einem Makro die Aktion „AusgabeIn“ (VBA: Out putTo). Unter „Objekttyp“ stellen Sie „Bericht“ ein, unter „Objektname“ geben Sie den Namen des Berichtes ein. „Ausgabeformat“ wäre „RichText Format“ (Word-Dokument gibt es nicht) und unter „Ausgabedatei“ legen Sie Laufwerk/Pfad/ Dateiname (z. B. „F:\Exporte\Bericht.rtf“) fest. Die beiden letzen Parameter ignorieren Sie, sie sind in diesem Zusammenhang ohne Bedeutung.

Zeitpläne als Diagramm drucken

Die grafische Umsetzung von Zeit- und Projektplänen gehört leider nicht zur Standard- Ausstattung von Access. Zwar lassen sich viele Diagrammvarianten für unterschiedlichste Aufgaben einsetzen, aber wenn Sie eine Projekt- oder Urlaubs-Planung als Zeitlinie in einem Bericht ausgeben wollen, findet sich keine passende Lösung. Mithilfe der Standard-Steuerelemente, und zwar insbesondere des Rechtecks aus der Zeichenfunktion, lässt sich Access aber leicht austricksen.

So funktioniert die Lösung

Dem Bericht liegen zwei einfache Tabellen zugrunde: „Projekte“ und „Projektdetails“. „Projekte beinhaltet lediglich ein Feld „ProjektName“ und dient zur Verknüpfung von einzelnen Tätigkeiten mit einem Projekt. In „Projektdetails“ finden sich diese Tätigkeiten zusammen mit einem Start- und einem Abschluss-Datum. Diese Daten sollen pro Projekt als Zeitlinien in einem Bericht ausgegeben werden. Dazu erfolgt im Bericht eine Gruppierung nach „Projektname“. Im Detailbereich sind dann die einzelnen Tätigkeiten sortiert nach Start-Datum aufgeführt.

Wichtig ist, dass für den Gruppenkopf „ProjektName“ die Eigenschaft „Neue Seite“ auf „Vor Bereich“ eingestellt ist – in der Ereignisprozedur „Beim Formatieren“ des Gruppenkopfes werden pro Projekt wichtige Basisdaten berechnet, ohne die im Detailbereich keine korrekte Darstellung erfolgen kann:

Listing 1

Set db = CurrentDb()
strSQL = „select Min([StartDatum]) as tmpStartDatum from Projektdetails where [ProjektName]= ‚“ & Me.ProjektName & „‚;“
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
If rs.RecordCount > 0 Then datVonDatum = rs(„tmpStartDatum“)
strSQL = „select Max(IIf(IsDate([AbschlussDatum]),CDate([AbschlussDatum]),Null)) as tmpAbschlDatum from Projektdetails where [ProjektName]= ‚“ & Me.ProjektName & „‚“
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
If rs.RecordCount > 0 Then datBisDatum = rs(„tmpAbschlDatum“)
rs.Close

intTagesDifferenz = DateDiff(„d“, datVonDatum, datBisDatum)

Im ersten Schritt ermitteln wir hier das erste und das letzte Datum der verschiedenen Tätigkeiten des jeweiligen Projektes, um daraus die Anzahl Tage als Anhaltspunkt für einen pro Tätigkeit anzuzeigenden Balken zu errechnen. Diese Werte halten wir in den globalen Variablen „datVonDatum“, „datBisDatum“ und „intTagesDifferenz“ für spätere, im Detailbereich stattfindende Berechnungen fest.

Me.lblZeitlinieGesamt.Caption = CStr(intTagesDifferenz) & “ Tage“
Me.txtVonDatum.Caption = Format(datVonDatum, „dd.mm.yyyy“)
Me.txtBisDatum.Caption = Format(datBisDatum, „dd.mm.yyyy“)

Anschließend setzt die Prozedur verschiedene Bezeichnungsfelder für die Anzeige des ersten und des letzten Tätigkeitsdatums sowie der Anzahl der Tage insgesamt.

Me.ScaleMode = 1 ‚Einheit= „Twips“…
sngFaktor = Me.recGanzesProjekt.Width / intTagesDifferenz
intOfs = Me.recGanzesProjekt.Left

End Sub

Zum Schluss errechnet die Prozedur einen Faktor für die Skalierung eines pro Tätigkeit anzuzeigenden Balkens, basierend auf der Anzahl ermittelter Lauftage für das Projekt. Das Rechteck „recGanzes- Projekt“ stellt einen Zeitbalken im Gruppenkopf dar, an dem später die darunter befindlichen Balken der einzelnen Tätigkeiten von links nach rechts ausgerichtet werden. Die globale Variable „intOfs“ hält dazu den linken Rand des „Hauptbalkens“ fest, von dem aus gerechnet die Balken pro Tätigkeit abhängig von ihrem Starttag positioniert werden.

Die eigentliche Berechnung der Balken pro Tätigkeit sowie deren Beschriftung erfolgt in der Ereignisprozedur „Beim Formatieren“ im Detailbereich. Der Balken pro Tätigkeit wird nur angezeigt, wenn sowohl ein Start- als auch ein Abschlussdatum vorhanden sind:

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim intErsterTag As Integer, intTageTätigkeit As Integer

If Not IsNull(Me.StartDatum) And Not IsNull(Me.AbschlussDatum) Then
intErsterTag = DateDiff(„d“, datVonDatum, Me.StartDatum) + 1
intTageTätigkeit = DateDiff(„d“, Me.StartDatum, Me.AbschlussDatum) + 1
If intErsterTag <= 0 Then intErsterTag = 1

Hier ermitteln wir zunächst den ersten Tag der einzelnen Tätigkeit und damit die linke Position, an der der Balken unter dem „Hauptbalken“ zu positionieren ist. Dann ermitteln wir die Dauer dieser Tätigkeit in Tagen für die Länge des Balkens.

Me.recBalken.Width = 1
Me.recBalken.Left = intOfs + ((intErsterTag – 1) * sngFaktor)
On Error Resume Next
Me.recBalken.Width = ((intTageTätigkeit – 1) * sngFaktor)
If Err Then Me.recBalken.Width = 20

Hier erfolgt die Einstellung für die linke Position und die Länge der einzelnen Balken. Access meldet einen Laufzeitfehler, wenn das für die Darstellung verwendete Rechteck „recBalken“ zu breit für den Detailbereich ist.

Deswegen setzen wir die Breite zunächst auf „1“, positionieren dann links entsprechend des ersten Tages der Tätigkeit unter dem „Hauptbalken“ und setzen erst dann die Breite gemäß der Dauer der Tätigkeit. Kommt es dabei zu einem Fehler, wird die Breite des Balkens kurzerhand auf „20“ gesetzt, um zumindest eine farbliche Hervorhebung zu gewährleisten.

Me.lblTageGesamt.Left = Me.recBalken.Left
Me.lblTageGesamt.Caption = CStr(intTageTätigkeit) + “ Tag(e)“
Me.recBalken.Visible = True
Me.lblTageGesamt.Visible = True

Abschließend setzen wir das Bezeichnungsfeld „lblTageGesamt“ auf die Dauer der jeweiligen Tätigkeit, positionieren es über dem Balken und zeigen dann Balken und Bezeichnungsfeld an.

Else
Me.recBalken.Visible = False
Me.lblTageGesamt.Visible = False
End If
End Sub

Wenn weder Start- noch Abschluss-Datum gelesen werden konnten, also eine Tätigkeit noch nicht komplett erfasst ist, blenden wir im Else-Zweig Balken und Bezeichnungsfeld aus.

Nutzen Sie das Zeitplan-Diagramm in Ihren Datenbanken

Um die Lösung in eigenen Datenbanken einzusetzen, muss eine Gruppierung nach dem Projektnamen möglich und pro Tätigkeit oder Aktivität ein Start- und ein Abschluss-Datum vorhanden sein.

Die Lösung benötigt also die Felder „ProjektName“, „Tätigkeit“, „StartDatum“ und „AbschlussDatum“, die Sie aus vorhandenen Daten recht einfach über eine Abfrage zur Verfügung stellen können.

Wenn dort das Feld mit dem Projektnamen beispielsweise „ProjektBezeichnung“ heißt, geben Sie in der Abfrage zum Beispiel „ProjektName: ProjektBezeichnung“ ein und generieren so quasi ein „Feldmapping“ für den Bericht.

Zum Beispiel: In Ihrer Datenbank tragen die Tabellen die Namen „ProjektBasis“ und „ProjektAktivitäten“ und beinhalten die Felder „ProjektBezeichnung“, „Aktivität“, „DatumStart“ und „DatumEnde“.

In der Abfrage nehmen Sie ein Mapping wie unten gezeigt vor und weisen diese Abfrage dem Bericht „Projektübersicht“ zu. Dabei können Sie selbstverständlich weitere Felder wie beispielsweise „Projektleiter“ oder „Kostenstelle“ aufnehmen und diese im Gruppenkopf oder Detailbereich des Berichtes nach Belieben hinzufügen.

Die gesamten Programmierungen:

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim intErsterTag As Integer, intTageTätigkeit As Integer

If Not IsNull(Me.StartDatum) And Not IsNull(Me.AbschlussDatum) Then
intErsterTag = DateDiff(„d“, datVonDatum, Me.StartDatum) + 1
intTageTätigkeit = DateDiff(„d“, Me.StartDatum, Me.AbschlussDatum) + 1
If intErsterTag <= 0 Then intErsterTag = 1
Me.recBalken.Width = 1
Me.recBalken.Left = intOfs + ((intErsterTag – 1) * sngFaktor)
On Error Resume Next
Me.recBalken.Width = ((intTageTätigkeit – 1) * sngFaktor)
If Err Then Me.recBalken.Width = (Me.Left + Me.Width) – Me.recBalken.Left
Me.lblTageGesamt.Left = Me.recBalken.Left
Me.lblTageGesamt.Caption = CStr(intTageTätigkeit) + “ Tag(e)“
Me.recBalken.Visible = True
Me.lblTageGesamt.Visible = True
Else
Me.recBalken.Visible = False
Me.lblTageGesamt.Visible = False
End If
End Sub


Private Sub Gruppenkopf0_Format(Cancel As Integer, FormatCount As Integer)
Dim db As Database, rs As Recordset, strSQL As String

Set db = CurrentDb()
strSQL = „select Min([StartDatum]) as tmpStartDatum from Projektdetails where [ProjektName]= ‚“ & Me.ProjektName & „‚;“
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
If rs.RecordCount > 0 Then datVonDatum = rs(„tmpStartDatum“)
strSQL = „select Max(IIf(IsDate([AbschlussDatum]),CDate([AbschlussDatum]),Null)) as tmpAbschlDatum from Projektdetails where [ProjektName]= ‚“ & Me.ProjektName & „‚“
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
If rs.RecordCount > 0 Then datBisDatum = rs(„tmpAbschlDatum“)
rs.Close

intTagesDifferenz = DateDiff(„d“, datVonDatum, datBisDatum)
Me.lblZeitlinieGesamt.Caption = CStr(intTagesDifferenz) & “ Tage“
Me.txtVonDatum.Caption = Format(datVonDatum, „dd.mm.yyyy“)
Me.txtBisDatum.Caption = Format(datBisDatum, „dd.mm.yyyy“)
Me.ScaleMode = 1 ‚Einheit= „Twips“…
sngFaktor = Me.recGanzesProjekt.Width / intTagesDifferenz
intOfs = Me.recGanzesProjekt.Left

End Sub

Öffnen eines Berichtes

DoCmd.OpenReport „Sales Report“, acViewNormal

(druckt den Bericht gleich aus)


DoCmd.OpenReport „Sales Report“, acViewDesign

(öffnet den Bericht im Entwurfmodus)


DoCmd.OpenReport „Sales Report“, acViewPreview

(öffnet den Bericht in Seitenansicht)

Mehrseitige Berichte effektiver nutzen

Die Ausgabe von Rechnungen mithilfe von Access-Berichten ist grundsätzlich kein Problem – zumindest solange Ihre Rechnung nur eine Seite umfasst. Bei mehrseitigen Berichten kommen Zwischensummen und Überträge ins Spiel, die Access nicht ohne Weiteres unterstützt. Anhand eines praktischen Beispiels möchten wir Ihnen zeigen, wie Sie mit einigen Tricks und Kniffen dennoch zum Ziel kommen.

Damit Sie am Ende einer Seite eine Zwischensumme und im Kopf der Folgeseite einen Übertrag ausgeben können, müssen zunächst alle Werte des Feldes summiert werden, für das Zwischensumme und Übertrag erforderlich sind. Access stellt dazu die Eigenschaft „Laufende Summe“ für Textfelder zur Verfügung. Ist diese Eigenschaft auf „Über alles“ eingestellt, addiert Access für jeden Datensatz den Inhalt des betreffenden Feldes zu einer im Hintergrund verwalteten Gesamtsumme hinzu und zeigt diese anstelle des Einzelwertes des Datensatzes im Textfeld an.

Hier liegt die Idee nahe, einfach ein Textfeld in den Seitenfuß zu setzen, es an das Feld zu binden, für das eine Zwischensumme benötigt wird, und dessen Eigenschaft „Laufende Summe“ auf „Über alles“ einzustellen. Leider funktioniert dieser Trick nicht, da im Seitenfuß kein direkter Zugriff auf Datenfelder des Detailbereichs möglich ist.

Während der direkte Zugriff auf Datenfelder im Detailbereich nicht möglich ist, hat Access nichts dagegen, wenn ein Textfeld adressiert wird, das zwar den gleichen Steuerelementeinhalt wie ein Datenfeld im Detailbereich hat, aber einen anderen Namen trägt. Anhand des Berichtes „Rechnung“ aus der Beispieldatenbank „Nordwind“ können Sie das ganz einfach nachvollziehen. In diesem „Rechnungs“- Bericht gibt es das Feld „Endpreis“, das die Summe aus Bestellmenge und Einzelpreis abzüglich Rabatt beinhaltet. Die Summe dieses Feldes ergibt den Rechnungsbetrag. Für dieses Feld möchten Sie nun eine Zwischensumme am Ende einer Seite ausgeben. Gehen Sie dazu folgendermaßen vor:

1. Öffnen Sie den Rechnungsbericht im Entwurfsmodus.

2. Markieren Sie das Feld, für das eine Zwischensumme ausgegeben werden soll, kopieren Sie es per Strg+C und fügen Sie es im Detailbereich per Strg+V wieder ein. In unserem Beispiel ist das das Feld „Endpreis“.

3. Ändern Sie den Namen des Feldes auf „txtLaufendeSumme“.

4. Stellen Sie die Eigenschaft „Sichtbar“ auf „Nein“.

5. Markieren Sie in der Zeile Eigenschaft „Laufende Summe“ den Eintrag „Über alles“.

Dieses Textfeld summiert nun für alle auf einer Seite ausgegebenen Datensätze den Inhalt des Feldes „Endpreis“.

Um diese Summe nun im Seitenfuß als Zwischensumme auszugeben, gehen Sie wie folgt vor:

1. Legen Sie im Seitenfuß ein ungebundenes Textfeld an und löschen Sie dessen Bezeichnungsfeld.

2. Setzen Sie den Namen des Feldes auf „txtZwischensumme“.

3. Geben Sie in der Eigenschaft „Steuerelementeinhalt“ die folgende Formel ein:

=“Zwischensumme: “ & Format$([txtLaufendeSumme];“#. ##0,00 €“)

Diese Formel überträgt bei der Ausgabe des Berichtes den aktuellen Inhalt des Feldes „txtLaufendeSumme“ aus dem Detailbereich in das Feld „txtZwischensumme“ im Seitenfuß und gibt so die jeweilige Zwischensumme aus.

Dabei erfolgt eine Formatierung als Währung über die Funktion „Format$“.

Wenn Sie den Bericht nun einmal anzeigen lassen, sehen Sie im Seitenfuß die gewünschte Zwischensumme der bis dahin addierten Rechnungspositionen.

Nachdem es gelungen ist, eine Zwischensumme im Seitenfuß auszugeben, ist das nächste Problem zu lösen: Eine Zwischensumme darf in Rechnungen nur dann ausgegeben werden, wenn die Rechnung mehr als eine Seite umfasst, und sie darf nicht auf der letzten Seite ausgegeben werden.

Um das zu erreichen, ergänzen Sie die Formel in der Eigenschaft „Steuerelementeinhalt“ des Textfeldes „txtZwischensumme“ im Seitenfuß wie folgt:

=Wenn([Seiten]>1 Und [Seite] <>[Seiten];“Zwischensumme: “ & Format$([txtLaufendeSumme];“#.##0,00 €“);““)

Diese Formel prüft, ob die Rechnung mehr als eine Seite umfasst und welche Seite gerade formatiert wird. Ist mehr als eine Seite vorhanden und es wird nicht die letzte Seite formatiert, erfolgt die Ausgabe der Bezeichnung „Zwischensumme“ mit der aktuellen Zwischensumme formatiert als Währung. Andernfalls, also wenn die Rechnung nur eine Seite lang ist oder die aktuell formatierte Seite die letzte Seite ist, wird der Inhalt des Feldes gelöscht und nichts angezeigt.

Die im Seitenfuß ausgegebene Zwischensumme soll nun im Seitenkopf der Folgeseite als Übertrag erscheinen.

Es bietet sich an – analog zur Zwischensumme im Seitenfuß – einfach ein Textfeld und eine Formel der folgenden Art im Seitenkopf zu verwenden:

=[txtZwischensumme]

Auf den ersten Blick müsste diese Formel den aktuellen Inhalt des Textfeldes im Seitenfuß und damit die aktuelle Zwischensumme in das Textfeld im Seitenkopf übertragen. Das geschieht jedoch nicht. Da beim Formatieren des Seitenkopfes bereits der erste Datensatz für den Detailbereich eingelesen ist, umfasst die laufende Summe und damit die Zwischensumme die ursprüngliche Summe plus den Wert des ersten ausgegebenen Datensatzes.

Mit dem folgenden Trick lösen Sie das Problem:

1. Legen Sie im Seitenfuß ein Textfeld „txtÜbertrag“ an.

2. Stellen Sie die Eigenschaft „Sichtbar“ auf „Nein“ ein.

3. Wählen Sie bei der Eigenschaft „Beim Formatieren“ des Seitenfußes den Eintrag „[Ereignisprozedur]“.

3. Klicken Sie auf die Schaltfläche mit den drei Punkten, um den VBA-Editor zu öffnen.

5. Geben Sie die folgenden Anweisungen ein: Diese Zuweisung überträgt nun am Seitenende die aktuelle Zwischensumme aus dem Textfeld im Detailbereich in das versteckte Textfeld „txtÜbertrag“ im Seitenfuß.
Private Sub
Seitenfußbereich_Format(Cancel As Integer, FormatCount As Integer)
Me.txtÜbertrag = Me.txtLaufendeSumme
End Sub


6. Legen Sie im Seitenkopf ein Textfeld „txtÜbertragKopf“ an.

7. Geben Sie in der Eigenschaft „Steuerelementeinhalt“ die folgende Formel ein:
P=Wenn([Seite]=1;““;“Übertrag: “ & Format$([txtÜbertrag]; „#.##0,00 €“))

Mithilfe einer „Wenn“-Abfrage stellen wir hier zunächst sicher, dass der Übertrag nur ab der zweiten Seite der Rechnung ausgegeben wird. Auf der ersten Seite löschen wir den Inhalt, sodass nichts angezeigt wird. Den zuvor festgehaltenen Übertrag lesen wir aus dem Textfeld „txtÜbertrag“ im Seitenfuß aus und zeigen ihn formatiert als Währung im Seitenkopf an.

 

Laufende Nummerierung für Berichte

Datenbank

In einem Access-Bericht geben Sie normalerweise alle Datensätze einer Tabelle oder bei Einsatz eines Filters gezielt eine bestimmte Datensatzgruppe aus. Dieses Verfahren ist allerdings nicht geeignet, wenn Sie gezielt einen bestimmten Datensatz mehrfach ausgeben möchten, wie das unter anderem bei Eintrittskarten, Verpackungsaufklebern oder Preisetiketten der Fall ist. Kommt dann noch eine automatische Nummerierung hinzu, die bei spielsweise für Seriennummern benötigt wird, erhöht das den Schwierigkeitsgrad noch einmal erheblich. Wir zeigen anhand eines konkreten Beispiels, wie Sie mit wenig Aufwand zum Ziel kommen.

Öffnen sie die Datenbank und rufen dann das Formular „frmArtikel“ auf. Es zeigt die Datensätze der Tabelle „Artikel“ in der üblichen Formularansicht, sodass Sie mit den Navigationsschaltflächen die Details aller Datensätze betrachten können.

Einzige Besonderheit des Artikelformulars ist die Schaltfläche SERIENNUMMERN im Formularfuß. Klicken Sie die Schaltfläche an, nachdem Sie einen Artikel ausgewählt haben, für den Sie Verpackungsaufkleber mit Seriennummern drucken wollen.

Im Formular mit dem Titel SERIENNUMMERN DRUCKEN haben Sie nun Gelegenheit, den Bereich der Seriennummern einzugeben – beispielsweise VON „1“ BIS „10“. An schließend klicken Sie auf DRUCK VORSCHAU, um sich das Resultat am Bildschirm anzusehen.

Wichtig dabei: Sobald Sie das Berichtslayout überprüft haben, kehren Sie mit der Symbolleisten-Schaltfläche SCHLIEßEN zum Formular SERIENNUMMERN DRUCKEN zurück. Versuchen Sie nicht, den Bericht direkt aus dem Vorschaufenster zu drucken! Sie erhalten dann nur leere Seiten. Das liegt an den VBA-Prozeduren, die für die Nummerierung zuständig sind. Sie werden nur einmal beim Öffnen des Berichts ausgeführt. Ein Starten des Druckvorgangs aktiviert die Prozeduren nicht erneut.

Wenn Sie den Bericht mit seinen fortlaufenden Seriennummern auf dem Drucker ausgeben wollen, klicken Sie im Formular SERIENNUMMERN DRUCKEN auf die Schaltfläche BERICHT DRUCKEN.

So werden Berichte per VBA nummeriert

Die Funktionalität des Beispiels ergibt sich komplett durch VBA-Routinen in den Formularen „frmArtikel“ (dem Formular mit der Artikelliste) und „frmSNDrucken“ (dem Formular mit dem Titel SERIENNUMMERN DRUCKEN) sowie im Bericht „repEinzelartikel“.

Aus der normalen Datenbank-Eingabemaske öffnen Sie per Schaltfläche das Formular „frmSNDrucken“. Die entsprechende Ereignisprozedur lautet:

Private Sub cmdSNDrucken_Click()
DoCmd.OpenForm _
FormName:=“frmSNDrucken“, _
OpenArgs:=Me![Artikel-Nr]
End Sub

Eine Schaltfläche mit diesem Programmcode lässt sich leicht in Ihre eigenen Datenbankanwendungen integrieren. Beachten Sie dabei, dass das Filterkriterium, das den Bericht auf einen einzelnen Datensatz beschränken soll, als „OpenArgs“- Parameter übergeben wird. Im Beispiel dient die Artikelnummer als ein schränkendes Kriterium.

Das Formular „frmSNDrucken“, in dem Sie Start- und Endzahl der Seriennummer eingeben, hat ansonsten nur die Aufgabe, den Bericht zu öffnen. Dabei leitet es das Filterkriterium an den Bericht weiter. Hier zum Beispiel der Programmcode für die direkte Druckausgabe:

Private Sub cmdPrint_Click()
[…]
DoCmd.OpenReport _
ReportName:=“repEinzelartikel“, _
View:=acViewPreview, _
WhereCondition:=“[Artikel-Nr]=“ & Me.OpenArgs
[…]
End Sub

Die Zeilen, die im Listing übersprungen und mit den Platzhaltern „[…]“ gekennzeichnet sind, dienen lediglich dazu, Eingabefehler auszuschließen. So wird etwa geprüft, ob überhaupt Start- und Endwerte eingetragen worden sind und ob der Endwert größer ist als der Startwert.

Die automatische Nummerierung steuert der Be richt selbst. Beim Öffnen liest er Start- und Endnummer aus dem Formular „frmSN Drucken“ aus. Gespeichert wer den diese Werte in den Variablen „lngErsteSN“ und „lngLetzteSN“. Die Variablen sind am Anfang des Berichtscodes auf Modul ebene deklariert, damit sie auch in den an deren Berichtsprozeduren verfügbar sind.

Neben der Initialisierung der Variablen enthält die Ereignisprozedur „Report_Open“ einige Anweisung zur Vermeidung von Fehlermeldungen beim direkten Öffnen

Private Sub Report_Open(Cancel As Integer)
On Error Resume Next
lngErsteSN = Forms!frmSNDrucken!txtStartNr.Value
If Err <> 0 Then
MsgBox „Bericht muss per Formular geöffnet werden“
Cancel = True
Else
lngLetzteSN = Forms!frmSNDrucken!txtEndNr.Value
End If
End Sub

des Berichts aus dem Datenbankfenster.

Dass Access den Bericht mehrfach für einen einzigen Datensatz ausgibt und dabei jedes Mal eine fortlaufende Nummer einfügt, verdanken Sie einer zweiten Ereignisprozedur.

Sie wird „beim Drucken“ des „Detailbereichs“ ausgeführt und enthält folgenden Code:

Private Sub Detailbereich_Print(Cancel As Integer, PrintCount As Integer)
If lngErsteSN <= lngLetzteSN Then
Me.txtSerienNr = Format(lngErsteSN, „00000“)
lngErsteSN = lngErsteSN + 1
Me.NextRecord = False
Else
Cancel = True
End If
End Sub

Der Aufruf der Prozedur erfolgt automatisch – entweder beim direkten Drucken des Berichts oder beim Erstellen der Berichtsvorschau am Bildschirm. Solange die Anfangsseriennummer kleiner als oder gleich groß wie die Endseriennummer ist, schreibt die Prozedur den aktuellen Wert in einem fünfstelligen Format in das Feld „txtSerienNr“.

Dabei handelt es sich um ein ungebundenes Textfeld im Bericht. Anschließend wird der Wert der ersten Seriennummer für den nächsten Durchgang um „1“ erhöht.

Wichtig ist nun vor allem die Anweisung „Me.NextRecord = False“. Damit er reichen Sie, dass Access noch einmal versucht, den Detailbereich zu drucken. So mit erfolgt ein erneuter Vergleich von Anfangs- und Endnummer, eine erneute Werteausgabe im Berichtsfeld und eine erneute Erhöhung der Anfangsnummer.

Erst wenn Anfangs- und Endnummer identisch sind, springt die Prozedur zum „Else“-Zweig. „Cancel = True“ bricht die Ausgabe des Detailbereichs ab und präsentiert den Bericht – je nach vorheriger Auswahl im Formular „frmSNDrucken“ – auf dem Bildschirm oder auf dem Drucker.

Ja/Nein-Felder mit beliebigen Zeichen ausgeben

Während Kontrollkästchen mit ihrer Darstellung als Rechteck und einem „X“ oder einem Häkchen in Formularen durchaus passend sind, möchten Sie in Berichten manchmal eine andere Darstellung verwenden. So stört z. B. beim Ausfüllen vorgedruckter Formulare per Bericht das Rechteck des Kontrollkästchens oder Sie möchten anstelle des normalen „X“ lieber ein anderes Kreuz verwenden.

Leider stellt Access keine Einstellmöglichkeiten für das Aussehen des Kontrollkästchens in Berichten zur Verfügung, aber mit ein paar Tricks erhalten Sie dennoch das Zeichen nach Wunsch.

Dazu wird einfach ein ungebundenes Textfeld eingesetzt, dessen Inhalt Sie abhängig von dem Feld setzen, das normalerweise als Kontrollkästchen ausgegeben wird:

  1. Fügen Sie im Bericht an der gewünschten Stelle ein Textfeld ein und stellen Sie die Eigenschaften „Hintergrundart“ und „Rahmenart“ auf „Transparent“ ein.
  2. Geben Sie in der Eigenschaft „Steuerelementeinhalt“ folgende Formel ein:
    =Wenn([Feldname]=-1;“X“;““)
  3. „Feldname“ ersetzen Sie dabei durch den Namen des Ja/Nein-Feldes, dessen Status ausgegeben werden soll. Die Formel sorgt dafür, dass bei Status „Aktiviert“ (Wert= „-1“) ein „X“ und bei Status „Deaktiviert“ gar nichts (leere Zeichenfolge) ausgegeben wird.

Wenn Sie den Bericht nun einmal anzeigen lassen, wird der Status mit einem einfachen „X“ ohne Rechteck ausgegeben, sodass der Bericht zum Beispiel zum Füllen vorgedruckter Formulare oder Fragebögen eingesetzt werden kann.

Möchten Sie statt des normalen „X“ ein handschriftlich gesetztes Kreuz ausgeben, gehen Sie wie folgt vor:

  1. Fügen Sie im Bericht an der gewünschten Stelle ein Textfeld ein und stellen Sie die Eigenschaften „Hintergrundart“ und „Rahmenart“ auf „Transparent“.
  2. Geben Sie in der Eigenschaft „Steuerelementeinhalt“ folgende Formel ein:
  3. „Feldname“ ersetzen Sie dabei durch den Namen des Ja/Nein-Feldes, dessen Status ausgegeben werden soll. Setzen Sie den Cursor dann zwischen die ersten leeren Anführungszeichen, halten Sie die Alt-Taste gedrückt, tippen Sie „0-2-5-1“ auf dem numerischen Cursorblock ein und lassen Sie die Alt-Taste wieder los. Zwischen den Anführungszeichen erscheint nun der Buchstabe „û“.
  4. Stellen Sie als „Schriftart“ für das Textfeld den Zeichensatz „Windings“ ein.

Wenn Sie den Bericht nun einmal anzeigen lassen, wird der Status des Kontrollkästchens mit einem Kreuz ausgegeben, das wie handschriftlich gesetzt erscheint. Möchten Sie statt des handschriftlichen „X“ ein normales Häkchen ausgeben, tippen Sie in Schritt 3 die Ziffernfolge „0-2-5-2“ ein.

Weitere Zeichen können Sie auswählen, wenn Sie die „Zeichentabelle“ von Windows aufrufen, die Schrift „Wingdings“ einstellen, das gewünschte Zeichen an – klicken, auf AUSWÄHLEN und KOPIEREN klicken und das Zeichen dann in die Formel einfügen.

Daten in Bericht hervorheben

Berichte enthalten häufig Werte, auf die man besonders aufmerksam gemacht werden möchte. Zum Beispiel in der Artikelverwaltung: Bei der Analyse des Berichtes sollen Lagerbestände kleiner „1“ auffällig hervorgehoben werden, sodass fehlende Artikel mit einem Blick erkannt werden können. Wenig bekannt ist die Tatsache, dass in Berichten auch einfache Zeichenfunktionen zur Verfügung stehen.

So sind Sie beispielsweise in der Lage, kritische Werte wie folgt mit einem roten Kreis zu versehen:

1. Öffnen Sie den Bericht, in dem Werte auffällig hervorgehoben werden sollen, im Entwurfsmodus.

2. Klicken Sie den grauen Balken mit der Bezeichnung „Detailbereich“ mit der rechten Maustaste an.

3. Rufen Sie das Kontextmenü EIGENSCHAFTEN auf.

4. Stellen Sie die Eigenschaft „Beim Formatieren“ auf den Eintrag „[Ereignisprozedur]“ ein, klicken Sie auf die Schaltfläche mit den drei Punkten und geben Sie im VBA-Editor die folgenden Anweisungen ein:

Private Sub Detail_Format(Cancel As Integer,
FormatCount As Integer)
Dim intHoehe As Integer
Dim intBreite As Integer
Dim sglXPos As Single
Dim sglYPos As Single
If Me.Lagerbestand < 1 Then
With Me.Lagerbestand
intHoehe = .Height * 1.5
intBreite = .Width * 1.5
sglYPos = (.Top + .Height) \ 2
sglXPos = .Left + (.Width \ 2)
End With
Me.DrawWidth = 6
Me.Circle (sglXPos, sglYPos),
intBreite \ 2, QBColor(12), , , 0.25
End If
End Sub

Den oben fett dargestellten Feldnamen „Lagerbestand“ und die Bedingung „< 1“ ersetzen Sie dabei durch den Namen des Feldes, das Sie prüfen möchten, sowie durch die Bedingung, die für eine Markierung des Feldes erfüllt sein muss. Möchten Sie z. B. in einer Umsatzübersicht alle Kunden mit mehr als 10.000 EUR Umsatz hervorheben, würden Sie hier dementsprechend „Me.Umsatz > 10000“ angeben.

5. Speichern Sie die Änderungen und lassen Sie den Bericht testweise anzeigen.

Die Zuweisung „Me.Draw- Width“ legt die Dicke des Striches für die Markierung in Pixeln fest. Hier sind gegebenenfalls je nach Drucker ein paar Experimente notwendig, um den richtigen Wert zu finden. Die Farbe wird direkt beim Aufruf der „Circle“- Methode über die Funktion „QBColor()“ angegeben. „12“ steht hierbei für „Hellrot“. Weitere mögliche Werte können Sie der Online-Hilfe zu „QBColor()“ entnehmen.

Das Argument Farbe in QBColor() hat folgende Einstellungen:

Nummer
Farbe
Nummer
Farbe

0

Schwarz

8

Grau

1

Blau

9

Hellblau

2

Grün

10

Hellgrün

3

Cyan

11

Hellcyan

4

Rot

12

Hellrot

5

Magenta

13

Hellmagenta

6

Gelb

14

Hellgelb

7

Weiß

15

Leuchtend Weiß

Bemerkungen

Das Argument Farbe stellt die von früheren Basic-Versionen (wie Microsoft Visual Basic für MS-DOS und dem Basic-Compiler) verwendeten Farbwerte dar. Beginnend mit dem niedrigst wertigen Byte gibt der zurückgegebene Wert die Rot-, Grün- und Blauwerte an, mit denen die entsprechende Farbe in dem RGB-System gesetzt wird, das von Visual Basic für Applikationen verwendet wird.

Wenn Sie nur einzelne Felder eine andere Farbe geben möchten, benutzen sie folgende Programmierung:

if Me!Lagerbestand >1 then
Me!Lagerbestand.ForeColor= = 4227072
else
Me!Lagerbestand.ForeColor= 255
endif

Berichtszeilen abwechselnd formatieren

Datenbank

Viele Berichte geben die Datensätze zeilenweise als Liste aus und sind schwer zu lesen. Häufig müssen Sie sich mit einem Lineal oder einer ähnlichen „Lesehilfe“ behelfen. Abhilfe schaffen Sie zum Beispiel mit einer Trennlinie, die Sie unter die Felder setzen. Aber die benötigt Platz und verlängert die Liste unnötig.

Wesentlich effektiver können Sie die Lesbarkeit von Listen erhöhen, indem Sie den Hintergrund der einzelnen Zeilen abwechselnd in Weiß/Grau oder Dunkelgrau/ Hellgrau ausgeben. Access bietet diese Formatierung standardmäßig nicht an, aber mit einer VBA-Prozedur können Sie ein wenig nachhelfen:

1. Öffnen Sie den gewünschten Bericht im Entwurfsmodus.

2. Aktivieren Sie den Detailbereich, indem Sie auf den grauen Balken mit der Bezeichnung „Detailbereich“ klicken.

3. Wählen Sie das Menü ANSICHTEIGENSCHAFTEN an.

4. Stellen Sie die Eigenschaft „Beim Formatieren“ auf „[Ereignisprozedur]“ und klicken Sie auf die Schaltfläche mit den drei Punkten, um den VBAEditor zu öffnen. Hier geben Sie folgende Anweisungen ein:

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
‚ Weiß: 16777215
‚ Hellgrau: 12632256
‚Dunkelgrau: 8421504
Const clngCol1 = 16777215 ‚Weiß
Const clngCol2 = 12632256 ‚Hellgrau
If Me.Detail.BackColor = clngCol1 Then ‚Von Weiß auf Grau
Me.Detail.BackColor = clngCol2
Else ‚Von Grau auf Weiß
Me.Detail.BackColor = clngCol1
End If
End Sub

Diese Anweisungen sorgen dafür, dass die Hintergrundfarbe des Detailbereichs wechselweise auf Weiß oder Grau gesetzt wird. Wahlweise können Sie auch einen Wechsel von Hell- auf Dunkelgrau verwenden, indem Sie die Anweisungen für die Konstanten ändern:

Const clngCol1 = 8421504 ‘Dunkelgrau
Const clngCol2 = 12632256 ‘Hellgrau

5. Sichern Sie die Änderungen und lassen Sie den Bericht anzeigen, um das Ergebnis zu prüfen.

basBerichtAnzeigen (Bericht maximiert anzeigen)

Function BerichtPassendMaximiert(strReport As String)
Dim R As Report

Application.Echo False
On Error Resume Next
DoCmd.OpenReport strReport, acViewPreview
If Err <> 0 Then
Application.Echo True
Beep
MsgBox „Bericht/Auswertung »“ & strReport & „« nicht gefunden…“, vbOKOnly + vbExclamation, „BerichtPassendMaximiert():“
Exit Function
End If
DoCmd.Maximize
Set R = Reports(strReport)
R.ZoomControl = 0 ‚Passend…
Application.Echo True

End Function

Bericht maximiert anzeigen

Datenbank

Zum Öffnen von Berichten setzen Sie in Ihren Datenbanken häufig die Anweisung „DoCmd.OpenReport“ mit dem Parameter „acPreView“ ein. Access öffnet den Bericht dann allerdings in einem Fenster, das willkürlich positioniert und skaliert wird, sodass oftmals nur Teile des Berichtes zu sehen sind. Wünschenswert wäre es, wenn die Anzeige generell maximiert mit dem Zoomfaktor „Passend“ erfolgen würde. Das lässt sich leicht durch den Einsatz einer VBA-Funktion lösen.

Sie finden eine solche Funktion „Bericht- PassendMaximiert()“ im Modul „basBerichtAnzeigen“. Um diese Funktion zu nutzen, gehen Sie wie folgt vor:

  1. Importieren Sie über das Menü DATEIEXTERNE DATEN-IMPORTIEREN das Modul „basBerichtAnzeigen“ aus der Beispieldatenbank in die Datenbank, in der Sie die Lösung einsetzen möchten.
  2. Öffnen Sie das Formular, aus dem Sie einen Bericht per Schaltfläche öffnen möchten.
  3. Setzen Sie die Eigenschaft „Beim Klicken“ der betreffenden Schaltfläche auf „=BerichtPassendMaximiert(„Berichtname>“)“, wobei Sie „<Berichtname>“ durch den Namen des zu öffnenden Berichtes ersetzen.

  4. Stellen Sie die Eigenschaft „Rahmenart“ des Formulars auf „Dialog“.
  5. Testen Sie den Aufruf des Berichtes, indem Sie das Formular über das Menü ANSICHT-FORMULARANSICHT laufen lassen.

Beim Klicken auf die Schaltfläche wird die im Modul „basBerichtAnzeigen“ abgelegte Funktion „BerichtPassendMaximiert()“ aufgerufen:

Function BerichtPassendMaximiert(strReport As String)
Dim R As Report

Application.Echo False
On Error Resume Next
DoCmd.OpenReport strReport, acViewPreview
If Err <> 0 Then
Application.Echo True
Beep
MsgBox „Bericht/Auswertung »“ & strReport & „« nicht gefunden…“, vbOKOnly + vbExclamation, „BerichtPassendMaximiert():“
Exit Function
End If
DoCmd.Maximize
Set R = Reports(strReport)
R.ZoomControl = 0 ‚Passend…
Application.Echo True

End Function

Dabei schalten wir zunächst die Bildschirmaktualisierung ab, um störendes Flackern durch die folgenden Anweisungen zu vermeiden. Dann öffnen wir den über den Parameter „strReport“ spezifizierten Bericht im Vorschau-Modus. Tritt beim Öffnen ein Fehler auf, melden wir das entsprechend und verlassen die Funktion. Andernfalls ist der Bericht jetzt „unsichtbar“ als Fenster vorhanden. Über „DoCmd.Maximize“ schalten wir auf maximierte Darstellung um und setzen den Zoomfaktor über die Zuweisung von „ZoomControl = 0“ auf „Passend“.

Da Access für alle Objekte nur die Darstellung „Normal“ oder „Maximiert“ kennt, muss das aufrufende Formular mit der Rahmenart „Dialog“ angezeigt werden. Access setzt dann beim Schließen des Berichtes automatisch wieder „Normal“ für alle Objekte ein, da es die Größe von Dialog-Formularen nicht auf „Maximiert“ ändern kann.