Fahrtenbuch mit Import- und Stornierungsfunktion

André Minhorst, Duisburg

Bei der Arbeit mit Computeranwendungen treten zwangsläufig Eingabefehler auf und es gibt keine Validierung, die hundertprozentig vor nicht gewünschten Eingaben schützt. So auch beim Fahrtenbuch, das in Ausgabe 2/2003 von Access im Unternehmen vorgestellt wurde: Man kann einmal eingegebene Fahrten nicht mehr stornieren, und somit mussten die Daten noch einmal neu eingegeben werden. Um dieses Manko zu beheben, lernen Sie im vorliegenden Beitrag einige Erweiterungen für das Fahrtenbuch kennen.

Die neue Version des Fahrtenbuchs enthält einige änderungen. Die wichtigste änderung ist, dass es von nun an die Möglichkeit gibt, den letzten eingegebenen Datensatz zu stornieren und noch einmal an der Stelle vor Eingabe des letzten Datensatzes zu beginnen.

Außerdem gibt es zwei kleinere änderungen: Wenn man mit der bisherigen Version des Fahrtenbuchs die Fahrten, den Verbrauchsbericht oder die Ausgaben ausgeben wollte, wurde die Berichtsvorschau nur in verkleinerter Ansicht angezeigt. Nun können Sie alle Berichte in beliebiger Größe anzeigen, bevor Sie den Druckvorgang mit der entsprechenden Schaltfläche initiieren. Außerdem zeigte die Verbrauchsübersicht bisher in manchen Fällen den Wert #Fehler an. Auch dieser Fehler ist behoben. Und wenn Sie schon mit der Vorgängerversion des Fahrtenbuchs gearbeitet haben, möchten Sie vermutlich nicht alle Daten erneut mit der neuen Version eingeben. In dem Fall finden Sie eine Import-Funktion für die einfache und schnelle übernahme Ihrer bestehenden Daten.

Die erste Version des Fahrtenbuchs, das Sie im Beitrag Fahrtenbuch in Ausgabe 2/2003 kennen lernen konnten und das auch unter www.access-im-unternehmen.de als Businesslösung zum Download bereitsteht, enthält keine Möglichkeit, einmal getätigte Eingaben zu redigieren. Diese Einstellung hat den Sinn, die Anwendung “finanzamttauglich” zu machen.

Damit das Fahrtenbuch in elektronischer Form dort anerkannt wird, darf es entweder gar keine Möglichkeit geben, einmal eingegebene Fahrten nachträglich zu manipulieren, oder die änderungen müssen als solche gekennzeichnet werden. Unter der Prämisse, dass eine auffällig gestaltete Sicherheitsabfrage bezüglich der Richtigkeit der Daten ausreichen würde, um Fehleingaben zu vermeiden, wurde damals erstere Variante aufgegriffen.

Im Laufe der Zeit wandelt sich jedoch auch das Bestätigen der Rückfrage vor dem Speichern von Daten in das nervige Wegklicken einer nicht mehr gelesenen Meldung; die erste Eingabe einer Fahrt mit 1000 statt 100 gefahrenen Kilometern lässt nicht mehr lange auf sich warten.

Hinweis

Die erste in Access im Unternehmen 2/2003 vorgestellte Version des Fahrtenbuchs und die unter der Rubrik Businesslösungen auf www.access-im-unternehmen.de veröffentlichte Version unterscheiden sich bereits enorm voneinander. Der vorliegende Beitrag beschreibt die änderungen, die an der letzten Version der Businesslösung vorgenommen werden, um den in diesem Beitrag beschriebenen Stand zu erreichen. Auch die Beschreibung der Routine zum Import bestehender Daten bezieht sich auf den Import von der Fahrtenbuch-Businesslösung. Diese kann aber leicht der Version aus Heft 2/2003 angepasst werden.

Stornieren des letzten Datensatzes

Damit man die Daten nicht nach jedem Eingabefehler erneut in eine blanko Fahrtenbuchdatenbank eingeben muss, enthält die nachfolgend vorgestellte neue Version des Fahrtenbuchs zwei änderungen:

  • Der Benutzer kann den jeweils letzten Eintrag für ein Fahrzeug stornieren. Das bedeutet keinesfalls, dass der letzte Datensatz gelöscht wird – es wird lediglich ein Ja/Nein-Feld namens Storniert auf den Wert Ja gesetzt, um stornierte Datensätze zu kennzeichnen.
  • Falls Sie mit der unter Businesslösungen veröffentlichten Version des Fahrtenbuchs oder der in Access im Unternehmen 2/2003 veröffentlichten Version arbeiten, finden Sie in der neuen Variante eine Funktion zum Import der Daten des bestehenden Fahrtenbuchs.
  • Finanzamttauglichkeit

    Die Finanzamttauglichkeit der Anwendung lassen Sie sich am besten vor der Benutzung von Ihrem Finanzamt bestätigen.

    Da der letzte eingegebene Datensatz für jedes Fahrzeug storniert werden kann, bedingt dies natürlich eine nachträgliche änderung dieses Datensatzes.

    Um den Anforderungen einer finanzamttauglichen Fahrtenbuchanwendung gerecht zu werden und stornierte Datensätze nach wie vor auszugeben und noch dazu als storniert zu kennzeichnen, gehen Sie folgendermaßen vor:

  • Die Tabelle tblFahrten erhält ein zusätzliches Feld namens Storniert mit dem Datentyp Ja/Nein.
  • Die Anwendung erhält eine neue Tabelle namens frmLetzteFahrt, die den jeweils letzten Fahrtdatensatz für jedes Fahrzeug enthält.
  • Das Formular frmFahrten erhält eine zusätzliche Schaltfläche zum Stornieren der jeweils letzten Fahrt.
  • Das Formular zeigt stornierte Fahrten aus Gründen der übersicht nicht mehr an.
  • Der Bericht zur Ausgabe des Fahrtenbuchs für ein Fahrzeug gibt die stornierten Fahrten deutlich als “storniert” markiert aus.
  • Möglicherweise fragen Sie sich, warum eine neue Tabelle für das Speichern der letzten Fahrt für jedes Fahrzeug herhalten muss und diese nicht direkt in die Tabelle tblFahrten eingetragen wird.

    Der Grund ist, dass einmal in die Tabelle tblFahrten eingetragene Fahrten nicht mehr geändert oder gelöscht werden können. Da aber die letzte Fahrt eines jeden Fahrzeugs noch als “Storniert” gekennzeichnet werden können soll, wird diese in einer separaten Tabelle gespeichert.

    Erst wenn der nächste Fahrtdatensatz für ein Fahrzeug eingegeben wurde, wird der aktuelle letzte Datensatz in die Tabelle tblFahrten geschrieben.

    Und wenn der letzte Datensatz storniert werden soll, wird zunächst dessen Feld Storniert auf den Wert Ja gesetzt, der Datensatz in die Tabelle tblFahrten kopiert und aus der Tabelle tblLetzteFahrt gelöscht.

    Anpassen der Tabelle tblFahrten

    Beginnen Sie mit dem ersten Schritt, der Anpassung der Tabelle tblFahrten. Das Hinzufügen des zusätzlichen Feldes stellt keine sonderlich große Hürde dar. Der Entwurf der Tabelle sieht anschließend wie in Bild 1 aus.

    Private Sub Form_Open(Cancel As Integer)
        If IstFormularGeoeffnet("frmFahrten") = 0 Or IsNull(Me.OpenArgs) Then
            MsgBox "Dieses Formular kann nur vom Hauptformular aus geöffnet werden.", _            vbExclamation + vbOKOnly, "Fahrtenbuch"
            Cancel = True
        End If
        Me.txtFahrzeug = Forms!frmFahrten!txtFahrzeug
        Me.txtStartDatum = Date
        Me.txtZielDatum = Date
        If DCount("FahrtID", "qryFahrten", "Kennzeichen = ''" & Me.txtFahrzeug & "''") = 0 _        Then
            Me.txtStartkmStand = DLookup("Startkilometerstand", "tblFahrzeuge", _            "Kennzeichen = ''" & Me.txtFahrzeug & "''")
        Else
            Me.txtStartkmStand = DMax("ZielkmStand", "qryFahrten", "Kennzeichen = ''" _            & Me.txtFahrzeug & "'' AND Storniert = False")
        End If
    End Sub

    Quellcode 1

    Bild 1: Angepasstes Datenmodell der Tabelle tblFahrten

    Tabelle zum Speichern der letzten Fahrt

    Die Tabelle tblLetzteFahrt hat die gleichen Felder wie die Tabelle tblFahrten. Der einzige Unterschied ist, dass die Daten der Tabelle nicht vor dem Bearbeiten und Löschen geschützt sind.

    Anpassen des Vorgangs zumAnlegen neuer Fahrten

    Neue Fahrten werden in der neuen Fassung des Fahrtenbuchs nicht mehr direkt in die Tabelle tblFahrten geschrieben, sondern zunächst in der Tabelle tblLetzteFahrt gespeichert. Dementsprechend muss das Formular zum Anlegen neuer Fahrten angepasst werden.

    Das beginnt mit der Prozedur, die beim öffnen des Formulars gestartet wird und die zur Ermittlung des Zielkilometerstands der alten und damit des Startkilometerstands der neuen Fahrt dient. Die Prozedur sieht nun wie in Quellcode 1 aus. Nach dem Eintragen des aktuellen Fahrzeugs sowie des Start- und Enddatums in das Formular überprüft die Prozedur, ob bereits eine Fahrt für das aktuelle Fahrzeug vorhanden ist. Falls nein, wird der Kilometerstand aus der Tabelle tblFahrzeuge bei Aufnahme des Fahrzeugs in das Fahrtenbuch als Startkilometerstand ermittelt. Falls ja, wird der aktuell höchste Kilometerstand für das aktuelle Fahrzeug aus der Abfrage qryFahrten ermittelt. Diese Abfrage ist eine Union-Abfrage und enthält alle Datensätze der Tabelle tblLetzteFahrt und der Tabelle tblFahrten, deren Feld Storniert den Wert False hat.

    Speichern einer neuen Fahrt

    Die Prozedur zum Speichern kann aus Platzgründen an dieser Stelle nicht abgedruckt werden. Die dortigen änderungen beziehen sich auf den Teil, der den neuen Datensatz speichert. In der neuen Version besteht dieser Speichervorgang aus mehreren Schritten:

  • Kopieren des zuletzt angelegten Datensatzes für dieses Fahrzeug von der Tabelle tblLetzteFahrt in die Tabelle tblFahrten
  • Löschen dieses Datensatzes aus der Tabelle tblLetzteFahrt
  • Anlegen des neuen Datensatzes in der Tabelle tblLetzteFahrt
  • Private Sub Form_Open(Cancel As Integer)

    Datensatzherkunft des Listenfeldes anpassen

    Da die Daten für das Listenfeld zur Anzeige der Fahrten eines Fahrzeuges nunmehr aus zwei Tabellen kommen, müssen Sie natürlich auch die Datensatzherkunft des Listenfeldes anpassen. Da diese per Code beim öffnen des Formulars festgelegt wird, setzen Sie den Hebel in der Prozedur an, die beim öffnen des Formulars frmFahrten ausgelöst wird (s. Quellcode 2). Die Datensatzherkunft besteht nicht mehr nur aus Daten der Tabelle tblFahrten. Zusätzlich kommt noch der Datensatz hinzu, der für das aktuelle Fahrzeug in der Tabelle tblLetzteFahrt gespeichert ist. Dort ist nicht zwangsläufig ein Datensatz für das aktuelle Fahrzeug gespeichert, da beispielsweise entweder noch gar kein Datensatz für dieses Fahrzeug angelegt wurde oder der letzte Datensatz dieser Tabelle storniert und damit in die Tabelle tblFahrten verschoben wurde.

        Dim Kennzeichen As String
        Dim AktuelleFahrtID As Integer
        Dim IstStorno As Boolean
        Kennzeichen = AktuellesFahrzeug
        Me.txtFahrzeug = Kennzeichen
        If DCount("FahrzeugID", "tblFahrzeuge") = 0 Then
            Me.cmdNeueFahrt.Enabled = False
        End If
        Me.lstFahrten.RowSource = "SELECT Kennzeichen, Fahrer, StartDatum, " _
        & "StartkmStand, StartOrt, ZielDatum, ZielkmStand, ZielOrt, " _    & "[ZielkmStand]-[StartkmStand] AS Strecke, Nutzungsart, Fahrtzweck " _
        & "FROM tblFahrten WHERE Kennzeichen = ''" & Kennzeichen _    & "'' AND Storniert = False " _
        & "UNION " _
        & "SELECT Kennzeichen, Fahrer, StartDAtum, StartkmStand, StartOrt, Zieldatum, " _    & "ZielkmStand, ZielOrt, [ZielkmStand] - [StartkmStand] AS Strecke, " _    & "Nutzungsart, Fahrtzweck FROM tblLetzteFahrt WHERE Kennzeichen = ''" _    & Kennzeichen & "''"
        IstStorno = Nz(DCount("FahrtID", "tblLetzteFahrt", "Kennzeichen = ''" _    & Kennzeichen & "''"), 0)
        Me.cmdStornieren.Enabled = IstStorno
    End Sub

    Quellcode 2

    Außerdem enthält der erste Teil der UNION-Abfrage, der die Daten der Tabelle tblFahrten enthält, nun eine Bedingung, die alle Datensätze ausschließt, deren Feld Storniert den Wert True enthält. Auf diese Weise zeigt das Listenfeld keine stornierten Fahrten an.

    Schaltfläche zum Stornieren von Fahrten

    Zum Stornieren von Fahrten legen Sie im Formular frmFahrten eine neue Schaltfläche mit
    der Beschriftung Letzte Fahrt stornieren an (siehe Bild 2).

    Bild 2: übersicht der Fahrten mit neuer “Stornieren”-Schaltfläche

    Die Schaltfläche löst die Prozedur aus Quellcode 3 aus. Die Prozedur fragt zunächst den Benutzer, ob er den Datensatz wirklich stornieren möchte. Falls ja, führt die Prozedur folgende Schritte durch:

  • Ermitteln des letzten Datensatzes für das aktuelle Fahrzeug aus der Tabelle tblLetzteFahrt
  • ändern des Feldwertes des Feldes Storniert auf True
  • Kopieren des Inhalts des kompletten Datensatzes von der Tabelle tblLetzteFahrt in die Tabelle tblFahrten
  • Löschen des Datensatzes aus der Tabelle tblLetzteFahrt
  • Deaktivieren der Schaltfläche zum Stornieren von Fahrten
  • Private Sub cmdStornieren_Click()
      If MsgBox("Möchten Sie die letzte in der Liste angezeigt Fahrt wirklich " _    & "stornieren", vbYesNo + vbExclamation, "Fahrt stornieren") = vbYes Then
        Dim strSQL As String
        Dim db As Database
        Dim rst As Recordset
        Dim AktuelleFahrtID As Integer
        Dim IstStorno As Boolean
        Dim Kennzeichen As String
        On Error GoTo cmdStornieren_Click_Err
        Kennzeichen = AktuellesFahrzeug
        Set db = CurrentDb
        Set rst = db.OpenRecordset("SELECT TOP 1 * FROM tblLetzteFahrt WHERE " _      & "Kennzeichen = ''" & Kennzeichen & "'' ORDER BY FahrtID DESC", dbOpenDynaset)
        strSQL = "UPDATE tblLetzteFahrt SET Storniert = TRUE WHERE FahrtID = " _      & rst!FahrtID
        db.Execute strSQL, dbFailOnError
        strSQL = "INSERT INTO tblFahrten(Kennzeichen, StartDatum, StartkmStand, " _      & "StartOrt, ZielDatum, ZielkmStand, ZielOrt, Fahrer, Nutzungsart, " _      & "Fahrtzweck, Bemerkungen, Storniert) SELECT Kennzeichen, StartDatum, " _      & "StartkmStand, StartOrt, ZielDatum, ZielkmStand, ZielOrt, Fahrer, " _      & "Nutzungsart, Fahrtzweck, Bemerkungen, Storniert FROM tblLetzteFahrt " _      & "WHERE FahrtID = " & rst!FahrtID
        db.Execute strSQL, dbFailOnError
        strSQL = "DELETE FROM tblLetzteFahrt WHERE FahrtID = " & rst!FahrtID
        db.Execute strSQL, dbFailOnError
        Me.lstFahrten.Requery
        Me.cmdNeueFahrt.SetFocus
        IstStorno = DCount("FahrtID", "tblLetzteFahrt", "Kennzeichen = ''" & Kennzeichen _      & "''") > 0
        Me.cmdStornieren.Enabled = IstStorno
      End If
    cmdStornieren_Click_Exit:
      rst.Close
      Set rst = Nothing
      Set db = Nothing
      Exit Sub
    cmdStornieren_Click_Err:
      Debug.Print Err.Number, Err.Description
      GoTo cmdStornieren_Click_Exit
    End Sub

    Quellcode 3

  • Aktualisieren des Listenfeldes zur Anzeige von Fahrten
  • Private Sub Detailbereich_Print(Cancel As Integer, _    PrintCount As Integer)
        If Me!Storniert = True Then
            If Not Nz(Me.Bemerkungen, "") = "" Then
                Me.Line (0, 415)-(Me.Width, 415), 0
            End If
            Me.Line (0, 125)-(Me.Width, 125), 0
        End If
    End Sub

    Quellcode 4

    Ausgabe des Fahrtenbuchs mit Stornierungen

    Nachdem die Stornierungen in den Formularen sauber eingegeben und angezeigt werden, fehlt noch deren Anzeige im Bericht und damit der für das Finanzamt relevante Ausdruck.

    Sie könnten nun natürlich einfach das Feld Storniert hinzufügen, sodass stornierte Datensätze einfach durch ein Häkchen in diesem Feld als solche markiert werden. Das wäre aber ein wenig zu trivial. Statt dessen werden Sie den Bericht so anpassen, dass die stornierten Fahrten durchgestrichen angezeigt werden (siehe Bild 3).

    Bild 3: Das Fahrtenbuch mit einem stornierten Eintrag

    Um diese Anpassung vorzunehmen, müssen Sie noch nicht einmal in das Layout des Berichts eingreifen. Die Linie zum Durchstreichen des Fahrtenbucheintrags können Sie nämlich ganz einfach mit der Line-Methode in der Prozedur erstellen, die durch die Ereigniseigenschaft Beim Drucken ausgelöst wird.

    Hinweis

    Die Line-Methode und verschiedene Möglichkeiten zur Verwendung von Linien und Rechtecken in Berichten finden Sie im Beitrag Malen nach Zahlen in der vorliegenden Ausgabe von Access im Unternehmen.

    Genaugenommen benötigen Sie für das Fahrtenbuch unter Umständen zwei Linien – eine zum Durchstreichen der Zeile mit den Fahrtinformationen und eine, falls zu der Fahrt noch eine Bemerkung hinzugefügt wurde, die in der Berichtsausgabe unterhalb des entsprechenden Fahrtenbucheintrags erfolgt. Beides erledigt die Prozedur aus Quellcode 4.

    Private Sub cmdImportieren_Click()
        Dim strFehler As String
        If Nz(Dir(Me.txtDatei), "") <> "" Then
            strFehler = ImportFahrtenbuch(Me.txtDatei)
            MenueleisteAktualisieren
            If Len(strFehler) > 0 Then
                MsgBox strFehler
            Else
                MsgBox "Der Import war erfolgreich."
            End If
            DoCmd.Close acForm, Me.Name
        Else
            MsgBox "Die angegebene Datei kann nicht " _            & "gefunden werden."
        End If
    End Sub

    Quellcode 4

    Schließlich müssen Sie noch die Prozedur anpassen, die beim öffnen des Berichts ausgelöst wird.

    Hier sind jedoch nur zwei Felder zu der SQL-Anweisung hinzuzufügen, die der Bericht als Datenherkunft verwendet. Für weitere Einzelheiten konsultieren Sie einfach das entsprechende Klassenmodul des Berichts rptFahrtenbuch.

    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