26705
Goto Top

Variablen mit Visual Basic aus Textdatei auslesen

Hallo Leute,
ich habe ein VB-Problem beim Auslesen von großen Textdateien.

Diese Textdateien sind wie folgt aufgebaut:

Datensatz_eins
Variable_1 Wert_1
...
Variable_5 Wert_5
Variable_6 Wert_will_haben_1
Variable_7 Wert_7
Variable_6 Wert_will_haben_2
Variable_8 Wert_9
Variable_6 Wert_will_haben_3
Variable_9 Wert_11
Datensatz_zwei
Variable_1 Wert_12
...
Variable_5 Wert_16
Variable_6 Wert_will_haben_2
Variable_7 Wert_18
Variable_6 Wert_will_haben_3
Variable_8 Wert_20
Variable_6 Wert_will_haben_4
Variable_9 Wert_22
Datensatz_drei...usw...


Diese Textdateien haben mehrere Tausen Zeilen und ich möchte nur die Werte einiger weniger Variablen auslesen und je Datensatz eine Zeile in eine .csv-Datei schreiben.
Es sollen auch die Werte einer Variablen jeweils nur in eine Spalte geschrieben werden, das klappt auch, sieht dann ungefähr so aus:

Datensatz Variable_1 Variable_5 ...
Datensatz_eins Wert_1 Wert_5 ...
Datensatz_zwei Wert_12 Wert_16 ...

Alle Variablen sind vom Typ String und bis auf meine Problemvariable (hier mal "Variable_6" genannt) kommen sie je Datensatz nur ein Mal vor.

Das ganze frage ich mit einigen If-Anweisungen innerhalb einer Do-While-Schleife ab, die meine .csv-Datei jeweils um eine Spalte (Wert, ";") bzw. bei einem neuen Datensatz um eine Zeile ergänzen.

        Do While (lineInput <> Nothing)

            If lineInput.StartsWith(Datensatz) Then
                sw.Write(CrLf & (lineInput.Substring(21, 19) & ";"))   
                lineInput = sr.ReadLine()
            End If
            If InStr(lineInput, Variable_1) Then
                sw.Write(SplitArray(lineInput, " ", 1) & ";")  
                lineInput = sr.ReadLine()
            End If
usw.

Hier ist das Problem:
Die Probleme bereitet mir nun Variable_6. Sie kommt innerhalb eines Datensatzes 0-4 mal mit verschiedenen Werten vor.
Insgesamt kann sie ca. 20 verschiedene Werte je Textdatei annehmen.
Nun ist es ja keine Problem sie einfach auszulesen: "Guck nach, ist sie da, hat sie nen Wert, wenn ja füg den Wert in die Zeile ein".

Allerdings sollen die Werte dieser Variablen nach Spalten sortiert werden. d.h. gleiche Werte sollen untereinander stehen.
Wenn kein Wert vorhanden ist soll das Feld leer bleiben, so ungefähr:

Datensatz ... Variable_6 Variable_6 Variable_6 Variable_6
Datensatz_eins ... Wert_1 Wert_5
Datensatz_zwei ... Wert_5 Wert_7 Wert_8
Datensatz_drei ... Wert_1 Wert_7 Wert_8
Datensatz_vier ... Wert_8

Das sollte doch eigentlich über Arrays machbar sein. Mir fehlt da wahrscheinlich noch ne Menge Erfahrung, aber ich komme im Moment einfach nicht weiter.

Ich hoffe, dass ich meine Sorgen verständlich formuliert habe und bin für jede Idee dankbar.

Gruß,
Seppel

Content-Key: 73457

Url: https://administrator.de/contentid/73457

Printed on: April 24, 2024 at 06:04 o'clock

Member: bastla
bastla Nov 13, 2007 at 14:26:14 (UTC)
Goto Top
Hallo SeppelCeh!

Da Du nicht angeführt hast, welcher Art die Werte "Wert_1", ... sind, ganz allgemein (und total ungetestet): Zunächst vorweg ein Array für alle möglichen Werte erstellen mit
arrCheck = Array("Wert_1", "Wert_2", ..., "Wert_n")  
Nachdem Du in der Einlese-Schleife den Wert für "Variable_6" gefunden hast (strGelesenerWert), in einer weiteren Schleife den Index suchen:
intIndex = -1
For i = 0 To UBound(arrCheck)
	If strGelesenerWert = arrCheck(i) Then
		intIndex = i
		Exit For
	End If
Next
If intIndex = -1 Then 'Nicht gefunden - weitere Vorgangsweise selbst festlegen  
strExtraDelims = String(intIndex, ";")  
Mit der String-Funktion wird eine entsprechende Anzahl zusätzlicher Trennzeichen (im Beispiel ";", schöner natürlich als Variable) erzeugt, welche bei der Ausgabe der Ergebniszeile dann etwa so verwendet werden können:
objCSVFile.WriteLine strDatensatz & ";" & strWasWeissIch & ";" & strExtraDelims & strGelesenerWert  

Grüße
bastla

[Edit] Dieses "set" stand vorhin unsinnigerweise noch oben in der ersten Code-Zeile - dafür fehlte aber "Array(" ... [/Edit]
Mitglied: 26705
26705 Nov 13, 2007 at 15:43:56 (UTC)
Goto Top
Moin bastla,

besten Dank schon mal. Das ";" hab ich schon mal durch ne Variable ersetzt. ^^

Die Variablen sind alle vom Typ "String" (hab ich oben im Text auch kursiv ergänzt).

Wenn ich Deinen Code richtig verstehe setzt er vor den Wert der Variable die Trenner entsprechend dem Index im Array. Wenn ich jetzt aber in einem Datensatz Für Variable_6 z.B. "Wert_1" und "Wert_8" finde würde er mir doch zu viele Trenner einsetzen.

btw. Ich schreibe momentan nicht die komplette Zeile, ich hänge immer nur den gefundenen Wert hinten dran, die neue Zeile beginne ich mit nem neuen Datensatz.
Vielleicht sollte ich die Konstruktion mal generell überdenken?!

Werde aber mit Deinem Tipp weiter probieren.

Gruß,
Seppel
Member: bastla
bastla Nov 13, 2007 at 17:09:44 (UTC)
Goto Top
Hallo SeppelCeh!

Sorry - war vorhin leider auf der Flucht und mit einem Bein sowie dem Großteil der grauen Zellen schon aus der Tür ... face-sad Deshalb habe ich auch nicht darauf geachtet, dass mehrere Werte je Datensatz vorkommen können.

Die folgende Variante sollte jetzt aber eher passen:
strDelim = ";"  

arrCheck = Array("Wert_1", "Wert_2", "Wert_3", "Wert_4", "Wert_5", "Wert_6", "Wert_7")  
M = UBound(arrCheck)
Dim arrFields()

'Do Until objTextFile.AtEndOfStream  
'...  
'...  
'...  
	Redim arrFields(M)
	'Alle für "Variable_6" gefundenen Werte behandeln ...  
	For Each strEingelesenerWert In Array("Wert_3", "Wert_7", "Wert_9", "Wert_1")  
		blnFound = False
		For i = 0 To M
			If strEingelesenerWert = arrCheck(i) Then
				arrFields(i) = arrCheck(i)
				blnFound = True
				Exit For
			End If
		Next
		If Not blnFound Then
			MsgBox strEingelesenerWert & " noch nicht vorhanden!", vbCritical  
			'...  
			'...  
		End If
	Next
	strVariable_6 = Join(arrFields, strDelim)
	MsgBox strVariable_6
	'...  
	'...  
'Loop  
Zum Testen (der Code soll stand-alone lauffähig sein) simuliere ich die Inhalte der Variablen "strEingelesenerWert" (welche Du aus dem zuletzt gelesenen Datensatz erhältst) durch ein Array mit Beispieldaten (inkl einem nicht vorgesehen Wert). Auch die Schleife zum Einlesen selbst ist nur angedeutet.

Nachdem alle Werte des aktuellen Datensatzes durchlaufen sind, wird in "strVariable_6" ein String gebildet, den Du einfach wie ein einzelnes Feld an den bereits erstellten Teil des neuen Datensatzes anhängen kannst.

Mit dem "ReDim" werden die Einträge des "arrFields" für die Behandlung des nächsten eingelesenen Datensatzes dann wieder vorweg gelöscht.
Inwieweit die ganze Struktur sinnvoll ist, musst Du natürlich selbst abschätzen - Tastsache ist jedenfalls, dass jeder der Werte ("Wert_1" etc) nur einmal auftreten darf - mehrfache Vorkommen lassen sich im Ergebnis nicht darstellen. Dies wäre nur möglich, wenn Du im Ergebnis-Datensatz die Häufigkeiten angibst, was dann etwa so aussehen würde:

Datensatz ... Wert_1 Wert_2 ... Wert_n
Datensatz_eins ... 0 2 ... 0
Datensatz_zwei ... 1 1 ... 0
Datensatz_drei ... 0 0 ... 3
Datensatz_vier ... 2 0 ... 1

Grüße
bastla
Mitglied: 26705
26705 Nov 13, 2007 at 17:18:16 (UTC)
Goto Top
Moin!

Ja, leider ist es sinnvoll. Wir brauchen aus diesen Dateien zu jedem Datensatz bestimmte Werte.
Da diese Dateien eigentlich zeilenweise ausgelesen und von den Maschinen verarbeitet werden, kommen einige wenige Variablen je Datensatz mehrfach mit unterschiedlichen Werten vor, und genau diese Werte von dieser einen Variable brauche ich.

Aber vielen Dank, ich werde den Code nachher oder morgen früh mal entsprechend anpassen und ausprobieren. Ich gebe auf jeden Fall ne Rückmeldung.

Gruß,
Seppel
Mitglied: 26705
26705 Nov 15, 2007 at 09:43:06 (UTC)
Goto Top
Moin bastla.

So, nach einigen Störungen und Problemen hab ich jetzt mal den Code angepasst und in mein Programm eingebaut.

Erstmal: Es funktioniert, die ausgelesenen Werte "strEingelesenerWert" von "Variable_6" werden in das neue Array "arrFields" geschrieben, mit den vordefinierten Werten aus "arrCheck" verglichen und an die dort definierte Position gesetzt.

Dafür schon mal vielen Dank!!!

Der einzige Haken an der Sache: er überschreibt die Werte beim Vergleich in "arrFields" gefundenen Werte korrekt, löscht aber die Stellen, die eigentlich nach dem Vergleich leer sein sollten nicht. (Im Beispiel unten sind das die Werte an den Stellen 2 und 4)
Was ich damit meine:

Ist von "arrFields" vor Vergleich:
... Stelle_1 Stelle_2 Stelle_3 Stelle_4 Stelle_5 Stelle_6 Stelle_7
... Wert_1 Wert_3 Wert_6 Wert_7

Ist von "arrFields" nach Vergleich:
... Stelle_1 Stelle_2 Stelle_3 Stelle_4 Stelle_5 Stelle_6 Stelle_7
... Wert_1 Wert_3 Wert_3 Wert_7 Wert_6 Wert_7

Soll von "arrFields" nach Vergleich:
... Stelle_1 Stelle_2 Stelle_3 Stelle_4 Stelle_5 Stelle_6 Stelle_7
... Wert_1 Wert_3 Wert_6 Wert_7

Hast Du noch eine Idee, wie ich die überflüssigen Werte aus "arrFields" löschen kann?
Ich probiere auf jeden Fall noch weiter. Will es schließlich auch mal lernen und nicht immer nur andere Fragen müssen. ^^

Gruß,
Seppel
Member: bastla
bastla Nov 15, 2007 at 09:56:17 (UTC)
Goto Top
Hallo SeppelCeh!

Für das Löschen wäre eigentlich das "Redim arrFields(M)" zuständig - dieses muss natürlich so platziert sein, dass es vor der Bearbeitung jedes einzelnen Datensatzes (= unmittelbar vor der Schleife für alle "Variable_6"-Werte) ausgeführt wird.

Unelegant wäre die Alternative, in einer eigenen Schleife der Art
For i = 0 To UBound(arrFields)
	arrFields(i) = ""  
Next
die Feldinhalte zu löschen.

Grüße
bastla
Mitglied: 26705
26705 Nov 15, 2007 at 12:08:52 (UTC)
Goto Top
Moin bastla.

Das Löschen mit ReDim funktioniert, hab mit der Erkennung eines neuen Datensatzes verknüpft.
Sobald die Kennzeichen für nen neuen Datensatz gefunden werden wird das Array geleert.

Die ausgegebenen Werte je Datensatz sind auch korrekt, das Array wird also an der richtigen Stelle gelöscht.

Die beiden IST-Tabellen hab ich mir direkt an der "For-Each"-Schleife ausgeben lassen.

Die "Ist-Tabelle vor Vergleich" wird ausgegeben, nachdem die Werte in "arrFields" abgelegt wurden,
die "Ist-Tabelle nach Vergleich" ist die Ausgabe nach der Zeile:
If strEingelesenerWert = arrCheck(i) Then
				arrFields(i) = arrCheck(i)

Nach diesem Vergleich muss ich anscheinend noch einmal Vergleichen.
Diesmal aber nicht wegen der Positionierung der Werte innerhalb "arrFields", sondern dann muss es ein Vergleich sein, bei dem in beiden Arrays an gleicher Stelle nach gleichen Werten gesucht werden und die nicht identischen Werte in "arrFields" müssen dann gelöscht werden.

Jetzt iszt aber erstmal Sicherheitsprüfung bei uns. Mein Rechner wird auf Strmlecks getestet. ^^

Bis später,
Seppel
Mitglied: 26705
26705 Nov 15, 2007 at 15:36:34 (UTC)
Goto Top
Ich habe die Lösung gefunden, nur leider muss ich jetzt los.
Werde sie nachher kurz beschreiben.

Gruß,
Seppel
Mitglied: 26705
26705 Nov 18, 2007 at 17:05:20 (UTC)
Goto Top
Hier die Lösung für mein Problem mit den doppelten Werten:

Direkt vor dem Schreiben in die Datei vergleiche ich die beiden Arrays erneut
und ersetze alle ungleichen Felder durch nichts. Also "".

For i = 0 To M
        StrComp(arrFields(i), arrCheck(i))
        If arrFields(i) <> arrCheck(i) Then
        arrFields(i) = ""  
        End If
Next

Jetzt klappt es und der Beitrag ist gelöst.
Besten Dank auch,
Seppel