aus Flexibel heraus eine TXT Datei ändern

rostiger Nagel

Forums-Knochenbrecher
Teammitglied
Beiträge
16.457
Reaktionspunkte
6.061
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich habe eine Flexibel RT und möchte in einer Text Datei einfach ein paar
Werte hinzufügen. Ich habe eine Datei mit Tagesproduktion, die natürlich
jeden Tag unterschiedlich lang ist. Jede Zeile enthält die Information für
ein Werkstück. Hier ein paar Zeilen.

Code:
1101;551;1253792;000;99;SOL01   ;  LC      ;SOCKELTEIL;  LC      ;00001;45.00               ;2                   ;26                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;600.00000           ;00001;
1101;551;1253792;000;99;SOL01   ;  NN      ;SOCKELTEIL;  NN      ;00001;45.00               ;3                   ;26                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;1200.00000          ;00002;
1101;551;1253792;000;99;SOL01   ;  LC      ;SOCKELTEIL;  LC      ;00001;45.00               ;4                   ;26                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;600.00000           ;00003;
1101;551;1262810;000;99;SOL01   ;  ER      ;SOCKELTEIL;  ER      ;00001;45.00               ;1                   ;13                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;900.00000           ;00004;
1101;551;1262810;000;99;SOL01   ;  ER      ;SOCKELTEIL;  ER      ;00001;45.00               ;2                   ;13                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;600.00000           ;00005;
1101;551;1262810;000;99;SOL01   ;  ER      ;SOCKELTEIL;  ER      ;00001;136.00              ;3                   ;13                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;1800.50000          ;00006;
1101;551;1262810;000;99;SOL01   ;  ER      ;SOCKELTEIL;  ER      ;00001;45.00               ;4                   ;13                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;900.00000           ;00007;
1101;551;1263360;000;99;SOL01   ;  LC      ;SOCKELTEIL;  LC      ;00001;45.00               ;1                   ;28                  ;K                   ;K                   ;S                   ;S                   ;0.00000             ;0.00000             ;1050.50000          ;00008;

wenn jetzt das entsprechende Werkstück abgearbeitet ist möchte ich das
einfach, mit einen Hacken kenzeichnen und dann in der Datei mit "1" oder
"0" anhängen.

Code:
1101;551;1253792;000;99;SOL01  .....           ;00001;[COLOR=red]1;[/COLOR]
1101;551;1253792;000;99;SOL01  .....           ;00002;[COLOR=red]1;[/COLOR]
1101;551;1253792;000;99;SOL01  .....           ;00003;[COLOR=red]0;[/COLOR]
1101;551;1262810;000;99;SOL01  .....           ;00004;
1101;551;1262810;000;99;SOL01  .....           ;00005;[COLOR=red]1;[/COLOR]
1101;551;1262810;000;99;SOL01  .....           ;00006;
1101;551;1262810;000;99;SOL01  .....           ;00007;[COLOR=red]1;[/COLOR]
1101;551;1263360;000;99;SOL01  .....           ;00008;

in der Praxis sieht das dann so aus:

Tagespulk_1.JPG

Tagespulk_2.JPG



Das Detei auslesen oder neu schreiben ist nicht das Problemm, aber wie
mache ich das wenn ich mitten in der Datei, am Ende etwas dranhängen
möchte?

Ich währe für jeden Tip dankbar

gruß Helmut
 
Das ist ein grundsätzliches CSV-Problem. Da geht nur komplett Einlesen, Ändern und Neuschreiben. Außer WCF hätte Funktionen die das kapseln.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, aber wie kann ich den kompletten Dateininhalt zwischenspeicher?
Oder kann (muss) ich im Script selber zwei Dateien gleichzeitig offen halten,
so das ich Zeile für Zeile lese und in die andere Datei speichere?
 
Ok, aber wie kann ich den kompletten Dateininhalt zwischenspeicher?
Mit der ReadLine-Methode in ein Zeilen-Array einlesen. ReadLine liest genau eine Zeile aus einer Textdatei.
Die ReadAll-Methode (die ganze Datei in eine VBS-Variable lesen) kann ich nicht empfehlen, da programmierst Du Dich dann bei der Verarbeitung zu Tode...

ReadLine und WriteLine sind in der WinCCflex-Hilfe sehr schön mit Beispiel erklärt. Volkers FAQ zum Dateien lesen und schreiben kennst Du ja auch.

Oder kann (muss) ich im Script selber zwei Dateien gleichzeitig offen halten,
so das ich Zeile für Zeile lese und in die andere Datei speichere?
Ich würde die Datei Zeile für Zeile einlesen, vergleichen ob es die gesuchte Zeile ist, wenn ja das Zeilenende ändern, dann die Zeile (geändert oder ungeändert) in eine zweite Datei schreiben. Wenn immer nur eine Zeile zu ändern ist, dann können nach der Änderung alle restlichen Zeilen ohne weitere Prüfung kopiert werden.
Zuerst noch die Eingabe-Datei umbenennen und die Ausgabe-Datei mit dem ursprünglichen Name der Eingabe-Datei anlegen.

Ich meine, die ganze Datei auf einmal in ein Zeilen-Array einlesen und dann durchsuchen und ändern ist aufwendiger zu programmieren als die zeilenweise Verarbeitung, benötigt auch mehr Arbeitsspeicher, könnte dafür aber eventuell schneller sein.
Man muß aber auf jeden Fall mit 2 Dateien arbeiten, entweder gleichzeitig oder nacheinander. Meines Wissens nach ist es unter VBS nicht möglich, eine Datei für Lesen und Schreiben zu öffnen, nur für nur Lesen oder nur Schreiben, weil Dateien als Textstream behandelt werden.

Falls Du die Zeilen in der Textdatei auch noch sortieren mußt, da eignet sich das komplette Einlesen der Datei in ein Zeilen-Array besser.

Harald
 
Das einlesen hatte zeilenweise hatte ich heute schon probiert,
irgendwie hat das nicht hingehauen. Wenn ich das nach Volker sein
Beispiel mache:

Code:
Set fso = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("WScript.Shell")
 
    Set TextFile = fso.openTextFile(datei, 1)
    x = 0
    do while textfile.atendofstream <> true
        x = x + 1
        name(x) = TextFile.readline
    loop
    textfile.close

Gibt es da eine beschränkung für das Array "Name" ich meine
ist da nach 256 Zeilen Schluss oder so.

Wenn ich es auf der Weise eingelesen habe kann ich es auch auf
der gleichen Weise mit writeLine wegschreiben. Kann ich da nicht
die gleiche Datei nehmen und einfach überschreiben. Oder lösche
ich die alte und erzeuge sie dann neu und Fülle sie einfach wieder
ab.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie hasst du den dein Array Name definiert??


So sollt's gehen, da wird das Array immer wieder um 100 Element vergrößert wenn die Grenze erreicht wird!

Code:
Dim fso,fs,TextFile,datei,x,y,name()
datei="c:\aa.log"

Set fso = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("WScript.Shell")
 
    Set TextFile = fso.openTextFile(datei, 1)
    x = 0
    y = 0
    Do While TextFile.atendofstream <> True
		
        x = x + 1
        If x>y Then
		y=y+100
		ReDim Preserve name(y)
	End If
        name(x) = TextFile.readline
    Loop
    TextFile.close
 
Mhmm...

Mhmm, man sollte natürlich die Array-Startgröße so wählen das es normalerweise nicht vergrößert werden muss, da die ja immer alle Elemente wieder kopiert werden müssen. (Infos zur Performance von ReDim: http://www.vbmonster.com/Uwe/Forum.aspx/vb/11270/ReDim-Preserve-performance)

Es ist bestimmt besser schon mit einer bestimmten Größe anzufangen:

Code:
Dim fso,fs,TextFile,datei,x,y,name()
datei="c:\aa.log"

Set fso = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("WScript.Shell")
 
    Set TextFile = fso.openTextFile(datei, 1)
    x = 0
    y = 1000
    ReDim name(y) ' Hier kein Preserve notwendig, array ist ja leer
    Do While TextFile.atendofstream <> True
		
        x = x + 1
        If x>y Then
		y=y+100
		ReDim Preserve name(y)
	End If
        name(x) = TextFile.readline
    Loop
    TextFile.close
 
Aber ich muss die Länge dann vor der Anwendung festlegen?
Das habe ich nicht gemacht, wenn ich zeilenweise das Werkstück
mit Split zerlegt hatte, funktionierte das ohne Störung.

Code:
Dim name(), zeile, wert_1, wert_2

zeile = Name(zeile)

wert_1 = zeile(1)
wert_2 = zeile(2)
 
Aber ich muss die Länge dann vor der Anwendung festlegen?
Das habe ich nicht gemacht, wenn ich zeilenweise das Werkstück
mit Split zerlegt hatte, funktionierte das ohne Störung.

Kein Plan, also bei mir ging's ohne eine Größenangabe gar nicht!
Aber so wie Ichs geschickt habe läufts bei mir!

Warum willst du eigentlich nicht 2 Dateien öffnen, einlesen und gleich wieder wegschreiben?

Danach killst du das Orginalfile und benennst das andere um!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das einlesen hatte zeilenweise hatte ich heute schon probiert,
irgendwie hat das nicht hingehauen.
Das lag wohl an der falschen Dim-Anweisung. Ansonsten müßte Dein Code funktionieren.
Hier meine Variante:
Code:
Const ForReading = 1, ForWriting = 2
Dim fso, f, infile, i, zeile(1000)

Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(infile, ForReading)
i = 0
Do While f.AtEndOfStream = False And i <= 1000
    zeile(i) = f.ReadLine
    i = i + 1
Loop
f.Close
If i > 1000 Then
	ShowSystemAlarm "Datei '" & infile & "' hat zu viele Zeilen"
	Exit Sub
End If

'...
'und schreiben dito.

Gibt es da eine beschränkung für das Array "Name" ich meine
ist da nach 256 Zeilen Schluss oder so.
Ja, es gibt eine Beschränkung. Da kommst Du aber garantiert nicht hin. ;)
Das Array darf reichlich 2.000.000.000 Elemente haben, außerdem darf das Array 60 Dimensionen haben ...
Entweder gleich groß genug dimensionieren oder Redim benutzen wie Jochen vorschlug.

Wenn ich es auf der Weise eingelesen habe kann ich es auch auf
der gleichen Weise mit writeLine wegschreiben.
Ja, genau.

Kann ich da nicht
die gleiche Datei nehmen und einfach überschreiben. Oder lösche
ich die alte und erzeuge sie dann neu und Fülle sie einfach wieder
ab.
Ich würde die Ursprungsdatei erst löschen, wenn die Ausgabedatei erfolgreich geschrieben wurde! Falls das Script aus irgendeinem Grund abschmiert ...
Auf die schnelle etwa so (kann auch anders funktionieren):
* <datei>.bak zu <datei>.txt umbenennen, falls <datei>.txt nicht existiert, aber <datei>.bak existiert (Scriptfehler!)
* <datei>.bak löschen, falls vorhanden
* <datei>.txt zu <datei>.bak umbenennen
* <datei<.bak einlesen
* <datei>.txt schreiben

PS: bin wie immer viel zu langsam, doch anscheinend gibt es nirgendwo im inet eine Angabe, wie groß ein Array in VBS sein darf. Hab's jetzt einfach in WCCflex ausprobiert. Ich spekuliere mal, daß das die Prozessor-Registerbreite - 1 ist, bei 32-Bit also 2^31 Elemente.

Harald
 
Zuletzt bearbeitet:
Soll ich ja garnicht, das mit den zwei datein, war nur so
eine Idee, weil das temporäre zeischenspeichern
nicht klappte. Dein Vorschlag werde ich morgen
ähm heute, mal testen. Danke.

Schönen Sonntag noch
 
Harald, dir auch ein Danke, ich glaube ich werde mal
von beiden Versionen etwas nutzen, einmal mit
der bak Datei und einmal mit den nachdeklarieren
bei Überschreitung. Werde dann berichten.

Dir auch einen schönen sonntag
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Da war doch noch ein kleiner Fehler in meinem Code in #12. :(
Das hätte nach der Schleife eigentlich "If i > 1001 Then" heißen müssen.
Ich habe aber die Schleife geändert zu "And i < 1000". Das sieht besser aus, auch wenn dann ein Array-Element nicht genutzt wird.

[EDIT]
Quatsch, das war doch richtig. Habs wieder zurückgeändert.
Es ist wohl schon zu spät bzw. früh. ;)
Wünsche Euch noch einen schönen Sonntag.
[/EDIT]

Harald
 
Zuletzt bearbeitet:
Hallo Harald, Hallo Jochen,
danke noch mal für eure Tips, jetzt Funktioniert es so wie ich es möchte.
Wie gedacht habe ich ein wenig von beiden Lössungen etwas verbaut.
Harald sein Tip, von der Datei erst mal eine Sicherung zu ziehen, das sieht
mann aber nicht im folgenden Script, das wird beim ersten aufschlag der
Datei, in einen anderen Script durchgeführt.
Dann das von Jochen wie ich das Array richtig initalisiere und Dynamisch
erweiter, falls erforderlich.

Code:
Dim f, fso, Verz, Datei, Name, Endung, Pulk, Jahr, Datei_OK
Dim x, y, z
Dim Zeile, Daten
Dim Inhalt()
Const lesen = 1, schreiben = 2, anhaengen = 8
 
[COLOR=green]'Prüfen ob die Lfd_Nr aus dem Tagespulk kommt[/COLOR]
[COLOR=green]'Wenn Negativ kommt Sie nicht aus der AV[/COLOR]
If Lfd_Nr <= 0 Then Exit Sub
 
[COLOR=green]'########################################################################################[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]' Datei und Verzeichnis prüfen und Filesystem vorbereiten[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]'########################################################################################[/COLOR]
 
[COLOR=green]'Verzeichnis stellen[/COLOR]
Verz  = SmartTags("003\003-OP.Tagespulk_Verzeichnis")
 
[COLOR=green]'Prüfen ob Tagespulk eingetragen[/COLOR]
If SmartTags("003\003-OP.Tagespulk_EAUF_Nr") = "" Then
 ShowSystemAlarm "Datei nicht ausgewählt"
 Exit Sub
End If
 
[COLOR=green]'Prüfen ob Jahr eingetragen[/COLOR]
If SmartTags("003\003-OP.Tagespulk_Jahr") = "" Then 
 ShowSystemAlarm "Datei nicht ausgewählt"
 Exit Sub
End If
 
[COLOR=green]'Filesystem öffnen[/COLOR] 
Set fso = CreateObject("Scripting.FileSystemObject")
 
[COLOR=green]'Verzeichnis prüfen[/COLOR]
If Not fso.FolderExists(Verz) Then 
 ShowSystemAlarm "Verzeichnis nicht vorhanden"
 Exit Sub
End If
 
[COLOR=green]'Datei prüfen[/COLOR]
For Each Datei In fso.GetFolder(Verz).Files
 Name = Datei.Name
 Endung = Right(Name,3)
 
 Pulk = Left(Name,4)
 Jahr = Mid(Name,6,4)
 Datei_OK = False
 If Endung = "TXT" Or Endung = "txt" Then
   If Pulk = SmartTags("003\003-OP.Tagespulk_EAUF_Nr") Then
    If Jahr = SmartTags("003\003-OP.Tagespulk_Jahr") Then
    Datei_OK = True
    Exit For
   End If
  End If
 End If
Next
 
[COLOR=green]'Datei nicht vorhanden, Script beenden[/COLOR]
If Datei_OK = False Then
 ShowSystemAlarm "Datei nicht vorhanden"
 Exit Sub
End If
 
[COLOR=green]'Pfad OK, Pfad für den Tagespulk stellen[/COLOR]
Pulk = Verz & "\" & Name
 
[COLOR=green]'########################################################################################[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]'Datei auslesen und eintrag prüfen[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]'########################################################################################[/COLOR]
 
[COLOR=green]'Filesystem zum lesen öffnen[/COLOR]
Set f = fso.OpenTextFile(Pulk,lesen,False)
 
[COLOR=green]'Variabeln stellen[/COLOR]
x = 1
y = 1000
ReDim Inhalt(y)
 
[COLOR=green]'Datei bis zum Ende auslesen[/COLOR]
Do While f.AtEndOfStream <> True
 
[COLOR=green]'Zeile lesen und zwischenspeichern[/COLOR]
 Zeile = f.ReadLine
 Inhalt(x) = Zeile
 
[COLOR=green]'Zeile zerlegen und kontrollieren[/COLOR]
[COLOR=green]'ob Eintrag "bearbeitet" dabei ist[/COLOR]
 Daten = Split(Zeile,";")
 If Lfd_Nr = CLng(Daten(20)) Then
  If bearbeitet = True Then
   Daten(21) = "1"
  Else
   Daten(21) = "0"
  End If
 Else
  If Daten(21) = "" Then Daten(21) = "0"
 End If
 
[COLOR=green]'Zeile neu zusammen setzen[/COLOR]
 Zeile = "" 
 For z = 0 To 21 
  Zeile = Zeile & Daten(z) & ";"
 Next  
 
[COLOR=green]'kontrolle ob zwischenspeicher "Inhalt" voll[/COLOR]
[COLOR=green]'ist, wenn ja Array erweitern[/COLOR]
 If x > y Then
  y = y+100
  ReDim Preserve Inhalt(y)
 End If
 
[COLOR=green]'Zeile zwischenspeichern[/COLOR]
 Inhalt(x) = Zeile
 
[COLOR=green]'index erhöhen[/COLOR]
 x = x+1
 
Loop
 
[COLOR=green]'Datei schließen[/COLOR]
f.Close 
 
[COLOR=green]'########################################################################################[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]'Datei zurrückspeichern[/COLOR]
[COLOR=green]'[/COLOR]
[COLOR=green]'########################################################################################[/COLOR]
 
[COLOR=green]'Filesystem für das Schreiben vorbereiten[/COLOR]
Set f = fso.OpenTextFile(Pulk,schreiben,False)
z = x-1
x = 1
Do While x <= z
 f.WriteLine (Inhalt(x))
 x = x+1
Loop
 
[COLOR=green]'Datei schließen[/COLOR]
f.Close

schönen Sonntag noch
gruß Helmut
 
Zuletzt bearbeitet:
Warum machst du den das Prüfen ob die Datei existiert so umständlich?

Setz dir doch einfach einen String mit deinem Namen wie er geraden lauten soll zusammen und prüfe dann mit "FileExists" des FileSystem-Objektes!

Aber wenn's geht ist ja gut...

Dir auch nen schönen Sonntag
 
Zurück
Oben