kami202
Goto Top

CSV per Batch umschreiben

Hallo,
kann mir ev. jemand bei folgendem Problem helfen?

ich habe in einem Ordner mehrere *.csv. Ganz normal mit ; getrennt. Jede Datei beginnt mit 2 Zeilen, die ich ignorieren muss.
Hier ein paar Beispielzeilen:

Zeile1 (nicht verändern, aber "mitnehmen")
Zeile2 (nicht verändern, aber "mitnehmen")
24779;00;120000;9401812;;0203;275003;130;;;;irgendwelcher Text 091424;;;EUR;;;
-534;00;622500;9300538;;0203;275003;131;;;;bissel Text {294};;;EUR;;;

In jeder vorhandenen *.csv soll ab der dritten Zeile für jede Zeile folgendes gemacht werden:
- Suche im 12.Feld (das mit irgendwelcher Text + Leerzeichen + 6stellige Zahl) die letzten 6 Zeichen. Wenn das 6 Zahlen sind schreibe diese in das 9. Feld derselben Zeile, sonst lass es.
- Speichere das Ergebnis unter demselben Dateinamen.

Das Ergebnis müsste also dann so aussehen:

Zeile1
Zeile2
24779;00;120000;9401812;;0203;275003;130;091424;;;irgendwelcher Text 091424;;;EUR;;;
-534;00;622500;9300538;;0203;275003;131;;;;bissel Text {294};;;EUR;;;

Das Ganze soll unter WinXP funktionieren, wenn es mit Bordmitteln nicht geht kann ich auch SED oder ähnliches installieren.
ich glaube dafür reicht mein Shell-Wissen nicht mehr aus...
Hat jemand eine Idee?
Danke schonmal.

Content-Key: 110418

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

Printed on: April 19, 2024 at 09:04 o'clock

Member: bastla
bastla Mar 03, 2009 at 20:20:26 (UTC)
Goto Top
Hallo kami202 und willkommen im Forum!

Mit Batch alleine wäre es etwas mühsam, daher bietet es sich an, etwas Unterstützung durch ein integriertes VBScript zu verwenden:
@echo off & setlocal
set "Basis=D:\CSV-Dateien\"  
set "Maske=*.csv"  
set "Trenn=;"  

set M=%temp%\ModifyCSV.vbs
> %M% echo Set fso=CreateObject("Scripting.FileSystemObject"):D=WScript.Arguments(0):T=Split(fso.OpenTextFile(D).ReadAll,vbCrLf)  
>>%M% echo W=False:For i=2 To UBound(T):F=Split(T(i),"%Trenn%"):Z=Right(F(11),6):If Len(Z)=6 Then  
>>%M% echo OK=1:For j=1 To 6:OK=OK*(Mid(Z,j,1)^>="0")*(Mid(Z,j,1)^<="9"):Next:If OK Then F(8)=Z:T(i)=Join(F,"%Trenn%"):W=True  
>>%M% echo End If:Next:If W Then fso.CreateTextFile(D).Write Join(T, vbCrLf)

for %%i in ("%Basis%%Maske%") do cscript //nologo %M% "%%i"  
Bitte beachten: Bei der Angabe des Ordners, in welchem die CSV-Dateien liegen (Zeile 2), immer am Ende des Pfades einen "\" schreiben.

Die Informationen über die Anzahl der zu überspringenden Zeilen, die Feldnummern 12 und 9 sowie die Zeichenanzahl (6) am Ende des Feldes 12 sind im Script "hart codiert" (wobei die Zählung der Feldnummern bei 0 beginnt und daher die um 1 verminderten Werte angegeben werden müssen). Das Script ist übrigens nach dem ersten Durchlauf unter "%temp%\ModifyCSV.vbs" zu finden.

Da die Zeilen "in den Dateien" (ohne Sicherungskopie) verändert werden, bitte Vorsicht beim Testen!

Grüße
bastla
Member: kami202
kami202 Mar 04, 2009 at 07:30:35 (UTC)
Goto Top
Hallo und vielen Dank für die Mühe!
Soweit wie ich das verstehe sieht das genau nach dem aus, was ich suche. Leider klappts nicht:

ModifyCSV.vbs(2, 48) Laufzeitfehler in Microsoft VBScript: Index außerhalb des gültigen Bereichs: '[number: 11]'

Irgendwas mit dem Split scheint nicht zu klappen, aber ich blicks nicht.

Schöne Grüße,
kami202
Member: bastla
bastla Mar 04, 2009 at 08:26:32 (UTC)
Goto Top
Hallo kami202!

Die Fehlermeldung weist darauf hin, dass kein Feld 12 gefunden wurde (was etwa am Trennzeichen oder an einer Leerzeile liegen könnte) - sieh Dir bitte die Daten an (und, soferne möglich) poste die entsprechenden Zeilen unter Verwendung der -Formatierung.

Grüße
bastla

P.S.: Mit Deinen oben dargestellten Testdaten funktioniert der Batch bei mir ...
Member: kami202
kami202 Mar 04, 2009 at 11:17:57 (UTC)
Goto Top
Hallo,

superschnelle Anwort, danke.
Also ich habe ebenfalls die 4 Beispielzeilen als irgendwas.csv gespeichert und das komplette Script von hier in eine irgendwas.bat gespeichert. Dann den Pfad angepasst (inkl. dem \\ ) und auf der Konsole aufgerufen.

Das hier ist exakt meine kleinste Testdatei:

Zeile1 (nicht verändern, aber \"mitnehmen\")  
Zeile2 (nicht verändern, aber \"mitnehmen\")  
24779;00;120000;9401812;;0203;275003;130;;;;irgendwelcher Text 091424;;;EUR;;;
-534;00;622500;9300538;;0203;275003;131;;;;bissel Text {294};;;EUR;;;

und ich bekomme leider:

Path-to-Temp\\ModifyCSV.vbs(2, 48) Laufzeitfehler in Microsoft VBScript: Index außerhalb des gültigen Bereichs: \'[number: 11]\'

Die ersten beiden Zeilen werden ja übersprungen, die können es also nicht sein. Ich habe trotzdem auch Dateien mit mehr Zeilen genommen und da mal die beiden Header-Zeilen entfernt, selbes Ergebnis.
Die 12. Spalte ist aber definitiv da. Alle Zeilen haben genauso viele Spalten, wenn etwas leer ist, steht eben dann ;;; nebeneinander, also kein Problem eigentlich.
Ich teste auf XP Pro SP3.

Danke für deine Mühe,
kami202
Member: bastla
bastla Mar 04, 2009 at 11:38:14 (UTC)
Goto Top
Hallo kami202!

Könntest Du bitte auch den Batch und die "Path-to-Temp\ModifyCSV.vbs" posten? Bei mir gibt's nämlich mit Daten und Batch (beide nochmals hier heruntergeladen) kein Problem ...

Grüße
bastla
Member: kami202
kami202 Mar 04, 2009 at 12:41:39 (UTC)
Goto Top
Hallo und danke für den tollen Support!!!
Ich habe das "Problem" gefunden:
Die CSVs, die ich verarbeiten muss, enden mit einem Enter. Also steht der Corsor ganz unten immer in einer leeren Zeile, die logischerweise keine Spalte 12 enthalten kann. Kann man die Zeile irgendwie ignorieren lassen?

kami202
Member: bastla
bastla Mar 04, 2009 at 12:50:50 (UTC)
Goto Top
Hallo kami202!

Um sich nicht darauf verlassen zu müssen, dass die letzte Zeile ignoriert werden kann/soll/muss prüft das Script jetzt auf Leerzeilen:
@echo off & setlocal
set "Basis=D:\CSV-Dateien\"  
set "Maske=*.csv"  
set "Trenn=;"  

set M=%temp%\ModifyCSV.vbs
> %M% echo Set fso=CreateObject("Scripting.FileSystemObject"):D=WScript.Arguments(0):T=Split(fso.OpenTextFile(D).ReadAll,vbCrLf)  
>>%M% echo W=False:For i=2 To UBound(T):If T(i)^<^>"" Then  
>>%M% echo F=Split(T(i),"%Trenn%"):Z=Right(F(11),6):If Len(Z)=6 Then  
>>%M% echo OK=1:For j=1 To 6:OK=OK*(Mid(Z,j,1)^>="0")*(Mid(Z,j,1)^<="9"):Next:If OK Then F(8)=Z:T(i)=Join(F,"%Trenn%"):W=True  
>>%M% echo End If
>>%M% echo End If:Next:If W Then fso.CreateTextFile(D).Write Join(T, vbCrLf)

for %%i in ("%Basis%%Maske%") do cscript //nologo %M% "%%i"  
Grüße
bastla
Member: kami202
kami202 Mar 04, 2009 at 13:00:19 (UTC)
Goto Top
Tausend dank, klappt hervorragend.
Du bist der Oberheld der VBS und Batch-Programmierung. Hat mir wirklich weitergeholfen. Danke!