Auflistungszeichen aus Textdateien ersetzen

Wenn Sie die Daten aus Textdateien oder ähnlichen Datenquellen einlesen möchten, benötigen Sie ein Trennzeichen, welches die einzelnen Spalten einer Zeile trennt. Das ist meist durch ein Tabulator-Zeichen, das Semikolon oder das Komma gegeben. Beim Tabulator-Zeichen treten meist keine Probleme auf, aber beim Semikolon oder beim Komma kann es zu folgendem Problem kommen: Die Zeile könnte Spalten enthalten, die ihrerseits das als Trennzeichen verwendete Zeichen enthalten. In diesem Beitrag schauen wir uns an, wie Sie mit solchen Datenquellen unter VBA umgehen können.

Ein ganz einfaches Beispiel für eine solche Zeile ist diese:

1; 'Beispielartikel'; 'Dies ist ein Beispielartikel.'

Hier können wir einfach nach dem Semikolon trennen und erhalten den Inhalt der drei Spalten. Aber was ist mit der folgenden Zeile

2; 'Noch ein Beispielartikel'; 'Semikola kommen selten vor; manchmal aber schon.'

Hier können wir nun nicht mehr einfach nach dem Semikolon trennen. Stattdessen müssten wir untersuchen, ob sich das Semikolon innerhalb eines Paars von einfachen Anführungszeichen befindet – oder auch innerhalb eines Paares von normalen Anführungszeichen.

Wir starten einmal mit einer Prozedur, die nach Schema F vorgeht und so tut, als würde es innerhalb von Spalten keine Delimiter-Zeichen geben. Diese stellt in einem String-Array namens strTestdaten die beiden oben genannten Zeilen zusammen und durchläuft dieses dann in einer For…Next-Schleife über alle Elemente. Darin ruft sie die Prozedur SpaltenErmitteln auf, der sie die jeweilige Zeile übergibt sowie das zu verwendende Delimiter-Zeichen (siehe Listing 1).

Public Function Testdaten()
     Dim strTestdaten(2) As String
     Dim i As Integer
     Dim j As Integer
     Dim strSpalten() As String
     strTestdaten(0) = "1; 'Beispielartikel'; 'Dies ist ein Beispielartikel.'"
     strTestdaten(1) = "2; 'Noch ein Beispielartikel'; 'Semikola kommen selten vor; manchmal aber schon.'"
     For i = LBound(strTestdaten) To UBound(strTestdaten)
         strSpalten = SpaltenErmitteln(strTestdaten(i), ";")
         For j = LBound(strSpalten) To UBound(strSpalten)
             Debug.Print j, strSpalten(j)
         Next j
     Next i
End Function

Listing 1: Prozedur, die Zeilen an eine Funktion zum Trennen einer Zeile nach dem Trennzeichen übergibt

Diese Funktion soll ein Array der Spalten der Zeile zurückliefern, die wir dann innerhalb einer weiteren For…Next-Schleife, diesmal mit der Zählervariablen j versehen, im Direktbereich des VBA-Editors ausgeben.

Die Funktion SpaltenErmitteln erwartet die zu untersuchende Zeile sowie das Delimiter-Zeichen. Sie trennt dann die Zeile mit der Split-Methode auf, welche die Zeile und den Delimiter erwartet, und ein Array der Elemente zurückliefert (siehe Listing 2).

Public Function SpaltenErmitteln(strZeile As String, strDelimiter As String) As Variant
     Dim strSpalten() As String
     strSpalten = Split(strZeile, strDelimiter)
     SpaltenErmitteln = strSpalten
End Function

Listing 2: Funktion zum Auftrennen von Zeilen am Delimiter

Das Ergebnis für die obigen beiden Zeilen sieht dann wie folgt aus, wenn wir zusätzlich noch die Spaltennummern ausgeben:

0    1
1    'Beispielartikel'
2    'Dies ist ein Beispielartikel.'
0    2
1    'Noch ein Beispielartikel'
2    'Semikola kommen selten vor
3    manchmal aber schon.'

Sie sehen hier bereits, dass einmal drei und einmal vier Spalten ermittelt wurden. Das Semikolon innerhalb der Anführungszeichen wurde nämlich als Delimiter erkannt. Das ist keine Basis, um die Daten etwa in eine Tabelle einzutragen.

Also müssen wir einen Weg finden, um nur die Delimiter zu berücksichtigen, die sich nicht innerhalb von Anführungszeichen befinden.

Spalten nur außerhalb von Literalen erkennen

Dazu erweitern wir die Funktion SpaltenErmitteln erheblich und gehen innerhalb der Funktion prinzipiell wie folgt vor:

  • Wir teilen die Zeile zunächst wieder mit der Split-Funktion an allen Stellen, die das Semikolon (oder ein anderes Trennzeichen) enthalten, auf.
  • Dann durchlaufen wir alle Elemente des Arrays und schauen, ob die jeweils aktuelle Zeile eine ungerade Anzahl von Anführungszeichen enthält. In diesem Fall setzen wir einen Marker, der beim nächsten Durchlauf dafür sorgt, dass die folgende Spalte an die zuvor untersuchte angehängt wird. Das wiederholen wir solange, bis wir nochmal in einer Spalte eine ungerade Anzahl von Anführungszeichen vorfinden. Dann schließen wir die Zeile ab und ändern den Wert dieses Markers.

Im Detail sieht das wie in Listing 3 aus. Die Funktion SpaltenErmitteln nimmt nun noch einen weiteren Parameter entgegen, mit dem Sie festlegen, welches Zeichen als Anführungszeichen verwendet wird – zum Beispiel das Hochkomma oder das normale Anführungszeichen.

Public Function SpaltenErmitteln(strZeile As String, strDelimiter As String, strAnfuehrungszeichen As String) As Variant
     Dim strSpalten() As String
     Dim strSpaltenBereinigt() As String
     Dim i As Integer
     Dim intAnzahlSpalten As Integer
     Dim intAnzahlAnfuehrungszeichen As Integer
     Dim bolAnfuehrungszeichen As Boolean
     Dim strTemp As String
     strSpalten = Split(strZeile, strDelimiter)
     For i = LBound(strSpalten) To UBound(strSpalten)
         intAnzahlAnfuehrungszeichen = Len(strSpalten(i)) - Len(Replace(strSpalten(i), strAnfuehrungszeichen, ""))
         If intAnzahlAnfuehrungszeichen Mod 2 = 1 Then
             If bolAnfuehrungszeichen = False Then
                 strTemp = strSpalten(i)
                 bolAnfuehrungszeichen = True
             Else
                 strTemp = strTemp & strDelimiter & strSpalten(i)
                 ReDim Preserve strSpaltenBereinigt(intAnzahlSpalten)
                 strSpaltenBereinigt(intAnzahlSpalten) = strTemp
                 intAnzahlSpalten = intAnzahlSpalten + 1
                 bolAnfuehrungszeichen = False
             End If
         Else
             If bolAnfuehrungszeichen = False Then
                 ReDim Preserve strSpaltenBereinigt(intAnzahlSpalten)
                 strSpaltenBereinigt(intAnzahlSpalten) = strSpalten(i)
                 intAnzahlSpalten = intAnzahlSpalten + 1
             Else
                 strTemp = strTemp & strDelimiter & strSpalten(i)
                 ReDim Preserve strSpaltenBereinigt(intAnzahlSpalten)
                 strSpaltenBereinigt(intAnzahlSpalten) = strTemp
                 intAnzahlSpalten = intAnzahlSpalten + 1
             End If
         End If
     Next i
     SpaltenErmitteln = strSpaltenBereinigt
End Function

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar