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.
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.
Bild 2: Beispieldateien für den Vergleich
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 wiederum 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.
Bild 4: Textfelder zum Erfassen der DateinamenDamit 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).
Bild 5: Optionentabelle zum Speichern der zuletzt verwendeten DateienDas 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:
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.
Bild 7: In der Tabelle tblZeilen gespeichertes VergleichsergebnisDateien 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.