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

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

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:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 6/2010.

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

Zusammenfassung

Drucken Sie Inhalte von Textdateien und farbige Listings in Berichten.

Techniken

Berichte, VBA

Voraussetzungen

Access 2000 und höher

Beispieldateien

BerichteOhneDatenherkunft.mdb

Shortlink

www.access-im-unternehmen.de/751

Berichte ohne Datenherkunft

André Minhorst, Duisburg

Haben Sie schon einmal einen Access-Bericht missbraucht? Um beispielsweise ein Kalenderblatt zu erstellen oder ein Sudoku zu drucken? Dann haben Sie sicher auf eine entsprechende Datenherkunft zurückgegriffen, denn ohne diese lassen Berichte sich nur bedingt mit Informationen füllen. Dieser Beitrag zeigt, wie Sie auch ohne Daten eine Menge mit Berichten anstellen. Dabei sollen zunächst der Inhalt einer Textdatei und später der eines Moduls in Berichtsform abgebildet werden - Letzteres mit entsprechender Färbung von Kommentarzeilen und Schlüsselwörtern!

Normalerweise läuft die Berichtserstellung etwa so ab: Sie überlegen sich den Aufbau des Berichts, stellen dann die benötigten Tabellen in einer Abfrage zusammen (oder auch in mehreren, wenn Unterberichte zum Einsatz kommen) und positionieren dann die an die Datenherkunft gebundenen Steuerelemente im Bericht.

Was aber, wenn die auszugebenden Daten gar nicht in Tabellenform vorliegen? Vielleicht möchten Sie ja einfach mal eine Textdatei in Berichtsform abbilden oder auch ein Codemodul (wobei dies den Charme hätte, dass man bestimmte Code-Elemente farbig darstellen könnte - der VBA-Editor bietet diese Möglichkeit nicht).

Zunächst kümmern wir uns um die Anzeige einer einfachen Textdatei in einem Bericht. In diesem Fall haben wir einfach den Inhalt einer Prozedur in eine Textdatei geschrieben. Diese soll nun wie in Abb. 1 in einem Bericht dargestellt werden.

pic001.png

Abb. 1: Dieser Bericht druckt den Inhalt einer Textdatei.

Zur einfachen Auswahl der Textdatei finden Sie in der Beispielanwendung ein kleines Formular mit einem Textfeld zur Anzeige des Dateinamens und einer Schaltfläche zum Öffnen eines Dateiauswahl-Dialogs (s. Abb. 2). Die Schaltfläche mit der Beschriftung Datei in Bericht anzeigen erledigt nichts weiter als das Öffnen des Berichts rptTextdatei in der Vorschauansicht. Dabei übergibt die durch die Schaltfläche ausgelöste Prozedur den Namen der anzuzeigenden Textdatei als Öffnungsparameter an den Bericht (da dies erst ab Access 2002 möglich ist, prüft der Bericht beim Öffnen, ob OpenArgs einen Wert enthält, und fragt gegebenenfalls direkt den Inhalt des Textfelds mit dem Dateinamen ab).

pic002.png

Abb. 2: Die Auswahl der auszugebenden Textdatei erfolgt komfortabel per Formular.

Bericht aus Datei füllen

Damit bewegen wir uns nun aus der Komfortzone der bekannten Techniken heraus und betrachten die Vorgehensweise, einen Bericht zeilenweise mit dem Inhalt einer Textdatei zu füllen.

Die Daten sollen in einem Bericht namens rptTextdatei erscheinen. Diesen legen Sie neu an und stellen die Größe seiner Bereiche etwa wie in Abb. 3 ein.

pic009.png

Abb. 3: Entwurf des Berichts zur Ausgabe von Textdateien

Danach benötigen Sie zwei Variablen, die Sie gleich oben im Klassenmodul des Berichts unterbringen. Das Klassenmodul fügen Sie am einfachsten zum Bericht hinzu, indem Sie die Berichtseigenschaft Enthält Modul auf Ja einstellen. Die Variablen speichern den Namen der Textdatei sowie die aktuell bearbeitete Zeile der Textdatei:

Dim strTextdatei As String

Dim strTextzeile As String

Im Prinzip durchlaufen wir dann die Textdatei auf die gewohnte Weise, also etwa mit folgenden Anweisungen:

Open strTextdatei For Input As #1

Do While Not EOF(1)

    Line Input #1, strTextzeile

    'was mit dem Text machen

Loop

Close #1

Allein die Aufteilung und die Realisierung der Schleife sieht anders aus. Beginnen wir mit dem Öffnen des Berichts und somit auch der Textdatei. Beim Öffnen des Berichts soll das Ereignis Beim Öffnen ausgelöst werden, weshalb Sie dem gleichnamigen Ereignis den Wert [Ereignisprozedur] zuweisen und nach einem Klick auf die Schaltfläche rechts von der Eigenschaft den automatisch angelegten Prozedurrumpf wie folgt ergänzen:

Private Sub Report_Open(Cancel As Integer)

    If Not IsNull(Me.OpenArgs) Then

        strTextdatei = Me.OpenArgs

    Else

        If IstFormularGeoeffnet("frmDateiDrucken") Then

            strTextdatei = Forms!frmDateidrucken!txtDatei

        Else

            MsgBox "Keine Datei!"

            Cancel = True

        End If

    End If

    Open strTextdatei For Input As #1

End Sub

Diese Prozedur prüft, ob das Öffnungsargument einen Dateinamen enthält. Falls nein, wird dieser direkt aus dem Textfeld txtDatei des aufrufenden Formulars ermittelt. Ist dieses gar nicht geöffnet, bricht die Anzeige des Berichts an dieser Stelle mit einer kurzen Meldung ab. Ist jedoch eine Textdatei angegeben, wird ihr Name in die Variable strTextdatei eingetragen. Die letzte Zeile öffnet die Datei schließlich für den lesenden Zugriff. Nun prüft der Bericht, ob er irgendwelche Daten in den Detailbereich schreiben soll. Auch wenn die Datenherkunft des Berichts wie in diesem Fall leer ist, löst er dabei trotzdem zumindest einmalig die beiden Ereignisse Beim Formatieren und Beim Drucken des Detailbereichs aus. Wenn Sie keine außergewöhnlichen Anweisungen in den entsprechenden Ereignisprozeduren hinterlegen, geschieht nichts und der Bericht wird ohne Daten im Detailbereich angezeigt.

Das gilt es zu verhindern: Wir wollen dafür sorgen, dass der Bericht im Detailbereich die Zeilen unserer Textdatei anzeigt. Dazu gibt es nun zwei Möglichkeiten:

  • Wir zeigen alle Zeilen in einem entsprechend großen Detailbereich an.
  • Der Detailbereich soll mehrmals gefüllt werden, und zwar mit jeweils einer Zeile der Textdatei.

Die erste Variante wäre einfach, denn dies können wir durch einen schlichten Aufruf der Print-Methode des Berichts erledigen. Wir müssen einfach nur den Detailbereich so groß wie möglich machen, damit dieser (mit ein wenig Glück) die komplette Textdatei fasst.

Aber was geschieht, wenn die Datei nicht auf eine Berichtsseite passt? Der Rest wird schlicht abgeschnitten. Dem können wir nur entgegenwirken, indem wir berechnen, wie viele Zeilen in einen Detailbereich passen, und den Inhalt der Textdatei darauf aufteilen. Das scheint kompliziert zu sein, also schauen wir uns zunächst die zweite Variante an.

Wenn wir jede Zeile in einen Detailbereich schreiben, gibt es kaum Probleme - zumindest, wenn sich der Bericht beim Hinzufügen von Inhalten mit der Print-Methode genau so verhält wie sonst: Er sollte einen Detailbereich, der nicht mehr auf die aktuelle Seite passt, einfach auf die folgende Seite verschieben.

Bleibt das Problem, dass wir nicht wissen, wie wir den Bericht dazu bewegen, auch ohne Datenquelle mehr als einen Detailbereich anzuzeigen.

Hier kommen zwei Eigenschaften des Berichts zum Tragen. Diese können Sie jeweils im Beim Formatieren-Ereignis der einzelnen Berichtsereignisse unterbringen:

  • MoveLayout: Diese Eigenschaft legt fest, ob der Bericht zum nächsten zu druckenden Bereich wechselt. Das bedeutet in der Regel, dass er nach der Ausgabe eines Bereichs eine Zeile weiter unten am linken Rand mit dem folgenden Bereich fortfährt.
  • NextRecord: Diese Eigenschaft legt fest, ob der nächste Datensatz der Datenherkunft zum Füllen des aktuellen Bereichs herangezogen werden soll - abhängig davon, ob es überhaupt noch einen weiteren Datensatz gibt.

Diese beiden Eigenschaften machen wir uns zunutze: Mit Me.MoveLayout = True sorgen wir dafür, dass die folgende Zeile der Textdatei links unter der aktuellen Zeile ausgegeben wird. Dazu muss es aber erst einmal kommen: Der Bericht druckt nämlich den Detailbereich nur einmal, wenn die Datenherkunft keine weiteren Daten enthält. Und in unserem Fall enthält diese ja gar keine Daten - nach dem ersten Durchlauf wäre also eigentlich Schluss.

Dieser hier unerwünschten Arbeitsverweigerung des Berichts können wir durch Setzen der Eigenschaft Me.NextRecord auf False vorbeugen: Dann versucht der Bericht nämlich nicht, zum nicht vorhandenen zweiten Datensatz zu springen, sondern druckt den aktuellen Bereich nochmals.

Im Detail profitieren wir davon in den beiden Ereignisprozeduren Beim Formatieren und Beim Drucken. In Beim Formatieren lesen wir jeweils eine Zeile der Textdatei ein. Dort stellen wir auch die Höhe des Bereichs auf einen passenden Wert ein. Schließlich erhält die Eigenschaft MoveLayout den Wert True, wenn noch die letzte Zeile eingelesen wurde, und False, wenn dies die letzte Zeile war. Sprich: Enthält die Textdatei noch ungedruckte Zeilen, mache noch einen Detailbereich auf und fahre fort.

Die Eigenschaft NextRecord bestücken wir mit dem umgekehrten Wert der Eigenschaft MoveLayout: Wenn noch Zeilen vorliegen, soll der Bericht nicht zum nächsten Datensatz springen. Dort würde er ja bemerken, dass eigentlich gar keine Daten vorliegen, und die Ausgabe gegebenenfalls mit dem übrigen Bereich wie etwa dem Seitenfuß beenden:

Private Sub Detailbereich_Format(Cancel As _

    Integer, FormatCount As Integer)

    Line Input #1, strTextzeile

    Me.Detailbereich.Height = 200

    Me.MoveLayout = Not EOF(1)

    Me.NextRecord = Not Me.MoveLayout

End Sub

Im Ereignis Beim Drucken erfolgt schließlich die eigentliche Ausgabe der aktuellen Zeile der Textdatei. Vorher stellen wir jedoch noch einige Texteigenschaften ein und geben dann mit der Print-Methode des Berichts den Inhalt der Textzeile in den Bericht aus:

Private Sub Detailbereich_Print(Cancel As Integer, PrintCount As Integer)

    Me.FontSize = 8

    Me.FontBold = False

    Me.FontName = "Courier New"

    Me.Print strTextzeile

End Sub

Diese beiden Prozeduren werden entsprechend der Zeilenzahl der Textdatei wiederholt. Probieren Sie dies später ruhig auch mit einer Textdatei aus, die mehr als eine Berichtsseite lang ist - der Bericht wird die Zeilen, die nicht auf die erste Seite passen, auf den folgenden Seiten ausgeben. Schließlich soll der Bericht im Seitenkopfbereich den Namen der Datei anzeigen. Das ist leicht: Die Ereignisprozedur Seitenkopfbereich_Print braucht dazu nur die Schrifteigenschaften nach Wunsch einzustellen und den Dateinamen mit der Print-Methode auszugeben:

Private Sub Seitenkopfbereich_Print(Cancel As Integer, PrintCount As Integer)

    Me.FontSize = 10

    Me.FontBold = True

    Me.Print strTextdatei

End Sub

Schließlich soll beim Schließen des Berichts noch die Textdatei geschlossen werden:

Private Sub Report_Close()

    Close #1

End Sub

Offene Baustellen

Das hat doch schon was, oder? Textdateien einfach mal so in einem Access-Bericht anzeigen? Immerhin lassen sich diese nach Gusto mit zusätzlichen Informationen ausstatten, zum Beispiel mit einer Zeilenzahl, mit Seitenzahlen et cetera. Alles Dinge, die der geneigte Access-Entwickler schneller programmiert, als er die entsprechenden Konfigurationsmöglichkeiten im Texteditor seiner Wahl gefunden hat.

Leider hat die Lösung noch eine kleine Schwachstelle: Wenn nämlich eine Zeile länger als die Berichtsbreite ist, wird sie einfach abgeschnitten. Die Länge der Zeile können wir in Abhängigkeit von Schriftgröße et cetera mit der Funktion TextWidth des Berichts ermitteln. Aber wie genau nutzen wir das Wissen um die Breite der Textzeile? Wir könnten ungefähr festlegen, auf wie viele Zeilen wir den Text aufteilen müssen, damit er nicht abgeschnitten wird.

Aber wie schneiden wir die Textzeilen auseinander? Am einfachsten wird es wohl sein, zunächst nur überlange Textzeilen mit einer kleinen Spezialbehandlung zu versehen. Dabei müssen wir zunächst prüfen, wann eine Zeile nicht mehr in die Spaltenbreite des Berichts passt. In diesem Falle muss der Text umbrochen, die Höhe des Detailbereichs angepasst und erst dann der Text in den Bericht gedruckt werden.

Textzeilen umbrechen

Die Version des Berichts mit der Funktion zum Umbrechen überlanger Textzeilen finden Sie in der Beispieldatenbank unter dem Namen rptTextdateiMitZeilenumbruch.

Den Hauptteil der Änderungen finden Sie in der Ereignisprozedur Beim Formatieren (s. Listing 1). Hier werden wie gehabt zunächst der Inhalt der aktuellen Textzeile ermittelt und die Schrifteigenschaften festgelegt. Dann kommt frischer Code: Die TextWidth-Funktion des Berichtsobjekts ermittelt die Breite des aktuell in der Variablen strTextzeile enthaltenen Textes. Ist diese breiter als die Berichtsspalte, unterzieht die Prozedur den Text einer Sonderbehandlung in der Funktion NarrowText. Diese haben wir bereits im Beitrag Zeichenketten zerlegen (www.access-im-unternehmen.de/560) vorgestellt. Die Funktion erwartet einen Text und die maximale Zeichenanzahl pro Zeile. Die Prozedur liefert einen an den Leerzeichen umbrochenen Text zurück. Der Aufruf

Listing 1: Formatieren des Detailbereichs und optimieren des Textes im Hinblick auf die Spaltenbreite

Private Sub Detailbereich_Format(Cancel As Integer, FormatCount As Integer)

    Dim intFontWeight As Integer

    Dim intZeilen As Integer

    Dim lngX As Long

    Dim lngY As Long

    Line Input #1, strTextzeile

    Me.FontSize = 8

    Me.FontBold = False

    Me.FontName = "Courier New"

    If Me.TextWidth(strTextzeile) > Me.Width Then

        strTextzeile = NarrowText(strTextzeile, 80, intZeilen)

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

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:

© 2003-2015 André Minhorst Alle Rechte vorbehalten.