Textdateien vergleichen

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Textdateien vergleichen

Als ich bei verschiedenen Projekten die gleichen Module und Formulare einsetzte und diese unabhängig voneinander anpasste, hatte ich plötzlich verschiedene Versionen der Objekte. Das war nicht beabsichtigt, die Objekte sollten möglichst überall gleich aussehen. Um keinen der Entwicklungsschritte zu verlieren, musste ich den Code der Objekte vergleichen. Dummerweise bietet Access keine eingebaute Funktion für so etwas, also musste ich mich selbst an die Arbeit machen und eine entsprechend Lösung programmieren. Diese sollte schlicht und einfach zwei Textdateien Zeile für Zeile miteinander vergleichen und mir die unterschiedlichen Zeilen anzeigen.

Zunächst einmal muss man sich überlegen, wie die Benutzeroberfläche eines solchen Tools aussehen könnte. Da hier zwei Dateien miteinander verglichen werden sollen, wird es auf jeden Fall zwei Textfelder zur Eingabe der Dateinamen geben beziehungsweise zwei Schaltflächen, mit denen Sie einen Dateidialog zum Auswählen der beiden Dateien aufrufen können. Darunter befinden sich der Übersicht halber nebeneinander die Texte der beiden Dateien – gegebenenfalls mit den markierten unterschiedlichen Zeilen.

Wenn man nun zwei Dateien zeilenweise vergleicht, sind weitere Fragen zu beantworten:

  • Wie soll man überhaupt zwei Textdateien zeilenweise miteinander vergleichen?
  • Und wie stelle ich das Ergebnis so dar, dass der Benutzer auch etwas damit anfangen kann?

Kommen wir zunächst zur zweiten Frage. Im Endergebnis soll unser Formular mit den beiden nebeneinander dargestellten Dateien etwa wie in Bild 1 aussehen.

So soll das Formular später aussehen.

Bild 1: So soll das Formular später aussehen.

Gleiche Zeilen werden direkt nebeneinander dargestellt, unterschiedliche Zeilen werden nur auf der jeweiligen Seite angezeigt und außerdem rot markiert, damit man diese sofort erkennen kann.

Die erste Frage ist schon aufwendiger zu beantworten. In unserer Lösung verwenden wir etwa einen Ablauf wie den folgenden:

Wir beginnen bei der ersten Zeile der ersten Datei und vergleichen diese mit der ersten Zeile der zweiten Datei. Sind beide Zeilen gleich, ist alles okay – wir bilden einfach beide Zeilen ab. Dann schauen wir uns die zweite Zeile an, bei der beispielsweise die erste Datei noch einen zusätzlichen Kommentar am Ende der Zeile enthält. Wir stellen fest, dass die zweite Zeile nicht in beiden Dateien gleich ist. Das kann nun Verschiedenes bedeuten: Zum Beispiel kann es sein, dass sich wirklich nur die zweiten Zeilen der beiden Dateien unterscheiden. Vielleicht finden wir aber die zweite Zeile der ersten Datei auch in der dritten oder in einer späteren Zeile der zweiten Datei – oder umgekehrt! In diesem Fall schauen wir, ob die zweite Zeile der ersten Datei früher in der zweiten Datei auftaucht als die zweite Zeile der zweiten Datei in der ersten. Wenn die zweite Zeile der ersten Datei früher in der zweiten Datei auftaucht als andersherum, zeigen wir für die erste Datei einige leere Zeilen an, während für die zweite Datei die bis zur gesuchten Zeile enthaltenen Zeilen erscheinen. Erst dann sollen die beiden gleichen Zeilen nebeneinandergestellt werden.

Am besten lässt sich dies anhand eines einfachen Beispiels erklären. Schauen wir uns dazu die beiden Textdateien aus Bild 2 an. Diese enthalten jeweils einen Satz, dessen Wörter auf jeweils einer eigenen Zeile abgebildet wurden. Wenn Sie diese beiden Dateien vergleichen, sollte sich das Ergebnis aus Bild 3 ergeben.

Beispieldateien für den Vergleich

Bild 2: Beispieldateien für den Vergleich

Ergebnis des Vergleichs

Bild 3: Ergebnis des Vergleichs

Die Zeilen 0, 1 und 2 stimmen in beiden Dateien überein. Zeile 3 jedoch unterscheidet sich in den beiden Dateien. Also schauen wir zunächst, ob und wann sich der Inhalt von Zeile 3 der ersten Datei in der zweiten Datei wiederholt. Dies ist in Zeile 6 der Fall. Dann prüft der Algorithmus, wann sich Zeile 2 aus der zweiten Datei sich in der ersten Datei wiederholt. Dies ist gar nicht der Fall, also gehen wir davon aus, dass Zeile 2 der ersten Datei und Zeile 6 der zweiten Datei übereinstimmen und Zeile 3, 4 und 5 der zweiten Datei eingeschoben wurden. Dann geht der Vergleich weiter, und zwar mit der jeweils folgenden Zeile nach den zueinander passenden Zeilen (also 2 und 6). Zeile 4 der ersten Datei stimmt nicht mit Zeile 7 der zweiten Datei überein. Beide können auch im weiteren Verlauf nicht gefunden werden, also werden beide im Ergebnis in jeweils einer eigenen Zeile abgebildet.

Zeile 5 der ersten Datei und Zeile 8 der zweiten Datei stimmen wiede­rum wieder überein und werden folgerichtig nebeneinander abgebildet. Zeile 6, 7, 8 und 9 der ersten Datei finden sich hingegen nicht in der zweiten Datei wieder und erscheinen solo in je einer Zeile. Dann passen wieder Zeile 11 der ersten und Zeile 9 der zweiten Datei zueinander, die übrigen Zeilen hingegen nicht.

Formular anlegen

Das Formular der Lösung soll frmTextdateienVergleichen heißen und soll keine Daten aus einer Tabelle oder Abfrage anzeigen – also stellen wir die Eigenschaften Bildlaufleisten, Datensatzmarkierer, Navigationsschaltflächen und Trennlinien auf Nein ein.

Dateien auswählen

Beginnen wir mit der Auswahl der Dateien. Dazu fügen Sie dem Formular zwei Textfelder namens txtDatei1 und txtDatei2 hinzu. Rechts neben den Textfeldern platzieren Sie jeweils eine Schaltfläche namens cmdDatei1 und cmdDatei2.

Für die beiden Schaltflächen hinterlegen Sie eine Beim Klicken-Ereignisprozedur wie in Listing 1. Die hier verwendete Prozedur OpenFileName finden Sie im Modul mdlTools.

Private Sub cmdDatei1_Click()
    Dim strDateiendung As String
    Me!txtDatei1 = OpenFileName(CurrentProject.Path, "Textdatei auswählen", _
        "Textdatei (*.txt)|Alle Dateien (*.*)")
End Sub

Listing 1: Anzeigen eines Datei öffnen-Dialogs und Eintragen des Ergebnisses im Textfeld

Die Textfelder und Schaltflächen legen Sie etwa wie in Bild 4 im Formular an.

Textfelder zum Erfassen der Dateinamen

Bild 4: Textfelder zum Erfassen der Dateinamen

Damit ich beim Testen der Lösung nicht bei jedem Schließen und Öffnen des Formulars die Dateien neu auswählen musste, habe ich die zuletzt verwendete Datei in den beiden Feldern Datei1 und Datei2 einer Tabelle namens tblOptionen gespeichert (s. Bild 5).

Optionentabelle zum Speichern der zuletzt verwendeten Dateien

Bild 5: Optionentabelle zum Speichern der zuletzt verwendeten Dateien

Das Formular ist an die Tabelle tblOptionen gebunden, die beiden Textfelder txtDatei1 und txtDatei2 an die entsprechenden Felder der Tabelle.

Tabelle zum Speichern des Vergleichs

Um das Ergebnis des Vergleichs in einer Ansicht darzustellen, gibt es mehrere Möglichkeiten – zwei Unterformulare in der Datenblattansicht, zwei Listenfelder oder auch ein einzelnes Unterformular in der Datenblattansicht.

Nach einigen Experimenten wurde klar: Man muss durch die Ergebnisse scrollen können, und dies für die Zeilen aus beiden Dateien synchron. Außerdem sollten bei Bedarf die Spaltenbreiten mit den Zeileninhalten angepasst werden können. Das Ergebnis: Es sollte ein einziges Unterformular in der Datenblattansicht mit den Zeilen der beiden Dateien und weiteren Feldern werden. Um diese Informationen nach dem Vergleich per VBA schnell in einem Formular anzeigen zu können, sollte man diese am besten in einer Tabelle speichern. Diese sieht im Entwurf wie in Bild 6 aus und hat folgende Felder:

Tabelle zum Speichern des Ergebnisses des Vergleichs

Bild 6: Tabelle zum Speichern des Ergebnisses des Vergleichs

  • ZeileID: Primärschlüssel der Tabelle
  • Unterschied: Ja/Nein-Feld, das angibt, ob sich die beiden abgebildeten Felder unterscheiden (es sollen standardmäßig alle Zeilen angezeigt werden, auch diejenigen, die in beiden Dateien identisch sind – dies könnte man gegebenenfalls variieren).
  • ZeileDatei1: Gibt die Nummer der Zeile innerhalb der jeweiligen Datei an, beginnt bei 0
  • Uebernehmen1: Ja/Nein-Feld, mit dem der Benutzer festlegen können soll, ob diese Zeile in eine neu zu erstellende dritte Datei übernommen werden soll
  • TextDatei1: Text der Zeile mit der angegebenen Zeilennummer in der ersten Datei
  • ZeileDatei2, Uebernehmen2, Textdatei2: siehe oben, nur für die zweite Textdatei

Das Ergebnis für den Vergleich der beiden Beispieldateien von oben würde etwa wie in Bild 7 in der Tabelle gespeichert werden. Diese kann genau so als Datenherkunft für das Unterformular sfmTextdateienVergleichen verwendet werden, fügen Sie dort alle Felder aus der Feldliste zum Formular hinzu. Stellen Sie außerdem die Eigenschaft Standardansicht auf Datenblatt ein.

In der Tabelle tblZeilen gespeichertes Vergleichsergebnis

Bild 7: In der Tabelle tblZeilen gespeichertes Vergleichsergebnis

Dateien vergleichen

Die Hauptarbeit beim Erstellen dieser Lösung steckte in der Programmierung der Routine, welche die Textdateien vergleicht und die Ergebnisse in die Tabelle tblZeilen einträgt. Sie finden den ersten Teil dieser Prozedur, die durch das Anklicken der Schaltfläche cmdVergleichen ausgelöst wird, in Listing 3.

Private Sub cmdVergleichen_Click()
    Dim strZeilen1() As String, strZeilen2() As String
    Dim lngAktuelleZeile1 As Long, lngAktuelleZeile2 As Long
    Dim lng1 As Long, lng2 As Long
    Dim db As DAO.Database
    Dim lngAbstand1 As Long, lngAbstand2 As Long
    Dim bolTreffer1 As Boolean, bolTreffer2 As Boolean
    Dim bolEnde1 As Boolean, bolEnde2 As Boolean
    Dim lngZeilenGesamt As Long
    Set db = CurrentDb
    db.Execute "DELETE FROM tblZeilen", dbFailOnError
    strZeilen1 = DateiInArray(Me!txtDatei1)
    strZeilen2 = DateiInArray(Me!txtDatei2)
    lngAktuelleZeile1 = 0
    lngAktuelleZeile2 = 0
    lngZeilenGesamt = UBound(strZeilen1)
    If lngZeilenGesamt < UBound(strZeilen2) Then
        lngZeilenGesamt = UBound(strZeilen2)
    End If
    SysCmd acSysCmdClearStatus
    Do While (lngAktuelleZeile1 < UBound(strZeilen1) And lngAktuelleZeile2 < UBound(strZeilen2))
        SysCmd acSysCmdSetStatus, "Zeile " & lngAktuelleZeile1 & "/" & lngZeilenGesamt
        lngAbstand1 = 0
        lngAbstand2 = 0
        Do While Not bolTreffer2 And Not bolEnde2
            If (strZeilen1(lngAktuelleZeile1) = strZeilen2(lngAktuelleZeile2 + lngAbstand2)) Then
                bolTreffer2 = True
            End If
            If lngAktuelleZeile2 + lngAbstand2 = UBound(strZeilen2) - 1 Then
                bolEnde2 = True
            End If
            If Not bolTreffer2 And Not bolEnde2 Then
                lngAbstand2 = lngAbstand2 + 1
            End If
        Loop
        Do While Not bolTreffer1 And Not bolEnde1
            If strZeilen2(lngAktuelleZeile2) = strZeilen1(lngAktuelleZeile1 + lngAbstand1) Then
                bolTreffer1 = True
            End If
            If lngAktuelleZeile1 + lngAbstand1 = UBound(strZeilen1) - 1 Then
                bolEnde1 = True
            End If
            If Not bolTreffer1 And Not bolEnde1 Then
                lngAbstand1 = lngAbstand1 + 1
            End If
        Loop

Listing 2: Textdateien vergleichen, Teil I

Die Prozedur löscht zunächst alle gegebenenfalls noch in der Tabelle tblZeilen enthaltenen Datensätze. Dann füllt sie die beiden Array-Variablen strZeilen1 und strZeilen2 mit Arrays, die aus den einzelnen Zeilen der Dateien bestehen. Das heißt, dass jedes Feld des Arrays je eine Zeile aufnimmt. Das Einlesen und Umwandeln der Dateien übernimmt dabei die Funktion DateiInArray aus Listing 2. Diese erwartet den Dateinamen als Parameter. Sie öffnet die Datei und durchläuft in einer Do While-Schleife alle Zeilen der Datei. Dabei fügt sie jede Zeile durch einen Zeilenumbruch (vbCrLf) getrennt zur Variablen strZeilen hinzu.

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.