josken69
Goto Top

Batch zur Umwandlung einer Datei nach fester Formatvorgabe

Hallo libe Helfer,
bin neu hier und leider auch neu in der Batchprgrammierung. Komme aus der Notes-Programmierung und bin bei folgender Aufgabe ratlos und bitte um Anregungen:

Ich habe eine Textdatei, die nach einer genauen Formatvorlage umzuwandeln ist. Die Inhalte sind dafür in bestimmte Felder mit fester Zeichenlänge vorgegeben. Ist ein Inhalt nicht lang genug muss er mit Leerzeichen aufgefüllt werden.
Zeile 1 und 2 der Datei sind korrekt und sollen nicht verändert werden.
Ab Zeile 3 geht's also los. Hier sind jeweils pro Datensatz die Felder von Zeichenposition 1-93 korrekt und müssen nicht verändert werden. Aber dann gehts los. Das Feld, das dann folgt, ist zu kurz. Er soll eine Länge von 27 Zeichen haben und muss also bis zur Zeichenposition 120 mit Leerzeichen aufgefüllt werden. Bisher folgt hier aber der Text, der ins nächste Feld soll direkt dran. Der Text der in dieses darauffolgende Feld soll, ist immer der gleiche. Man könnte also zur Trennung nehmen such ab Poition 94 bis dieser Text auftaucht, ermittle die Länge bis dorthin und fülle mit Leerzeichen auf bis 27 Zeichen erreicht sind.

Danach sind 8 weitere Leerzeichen einzufügen, bevor dann das nächste Feld beginnt, welches widerum 27 Zeichen lang sein soll, Dies ist das Feld, nennen wir es Firma, welches immer den gleichen Text enthält. Es muss auch bis auf 27 Zeichen mit Leerzeichen aufgefüllt werden.
Zum Schluss eines Datensatzes müssen noch 11 Leerzeichen angefügt werden

So muss die ganze Datei umgewandelt werden bis zur letzten Zeile. Diese darf ebenso wie Zeile 1 und 2 bei der Umwandlung nicht beachtet werde. An die letzte Zeile müssen dafür 51 Leerzeichen angehängt werden.

Zur Veranschaulichung, da die Beschreibung doch etwas konfus klingt, füge ich unten mal ein Beispiel an, wie die Struktur vor und nach der Umwandlung aussieht bzw. aussehen soll. Die Positionen 1-93 lasse ich mal aussen vor, da sie ja nicht verändert werden müssen.


Die Datei, welche umzuwandeln ist, sieht also ungefähr so aus:
Zeile1
Zeile2
Max MustermannFirmaxyz12345678Musterzweckbbbbbbbbbbbbbbbbabbccddeeeeeeeeeeeeeeeeeeeeeeeeeeffggggggggggggggggggggggggggg
Marie MustefrauFirmaxyz12345678Musterzweckbbbbbbbbbbbbbbbbabbccddeeeeeeeeeeeeeeeeeeeeeeeeeeffggggggggggggggggggggggggggg
Zeile Ende

Rauskommen soll dann aber sowas:
Zeile1
Zeile2
Max MustermannbbbbbbbbbbbbbbbbbbbbbFirmaxyzbbbbbbbbbbbbbbbbbbbMusterzweckbbbbbbbbbbbbbbbbabbccddeeeeeeeeeeeeeeeeeeeeeeeeeeffgggggggggggggggggggggggggggblankblankblankblankblankblankblankblankblankblankblank
Marie MusterfraubbbbbbbbbbbbbbbbbbbFirmaxyzbbbbbbbbbbbbbbbbbbbMusterzweckbbbbbbbbbbbbbbbbabbccddeeeeeeeeeeeeeeeeeeeeeeeeeeffgggggggggggggggggggggggggggblankblankblankblankblankblankblankblankblankblankblank

Zeile Ende mit 51 Blanks

Das Ganze soll dann über eine Batch oder Exe-Prozedur laufen.
Vielen Dank schon mal für jeden hilfreichen Hinweis.

Gruss Josh

Content-Key: 127932

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

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

Mitglied: 60730
60730 Oct 26, 2009 at 17:09:50 (UTC)
Goto Top
Servus,

das ganz ist aber wirklich kompliziert...

Als Denkansatz mal folgendes:

Zeile 1 und 2 der Datei sind korrekt und sollen nicht verändert werden.
Dazu ist der Schalter Skip=2 in der For Schleife dein Freund.

Aber...

Wer sagt dann der Batch, wo Sie
Max Mustermann
von
Marie Musterfrau
unterscheiden soll?

Mein rat - für das Problem - erstmal dafür sorgen dass die "ausgebende Stelle" irgendein Trennzeichen in dem Datensatzsalat drin ist - sonst wird das nüx.

Gruß
Member: Biber
Biber Oct 26, 2009, updated at Oct 18, 2012 at 16:39:47 (UTC)
Goto Top
Moin josken69,

willkommen im Forum.

Auch zum Thema "Exportdatei mit fester Satzlänge" haben wir hier bereits ein paar verwendbare Ansätze.
Eine Batchlösung (oder besser Batch-Herangehensweise) findest du z.B. hier: Exportdatei mit fester Satzlänge in CSV-Format konvertieren.

Ist also handwerklich auch durchaus mit vertretbarem Aufwand mit Batch zu lösen, allerdings würde ich die Wahl des Werkzeugs abhängig machen von

  • der voraussichtlichen Häufigkeit der Konvertierung (einmalig/ 3x täglich/ permanent/ bis die SAP-Hansels eine stabile Version zusammengeschrotet haben...)
  • dem Volumen der zu konvertierenden Datei(en). Sind das eher ein paar 100 oder ein paar 1000 Sätze oder eher über 100000 Sätze...?
  • der voraussichtlichen Änderungshäufigkeit des Quell/Zielformats. Eine Batchdatei ist schnell und von jedem anpassbar, eine whatever-.Exe nicht.

Kannst du dazu etwas sagen?

Grüße
Biber
Member: josken69
josken69 Oct 27, 2009 at 12:30:37 (UTC)
Goto Top
Hallo,
erstmal vielen Dank für die Antworten.
Zur Klärung der Fragen im letzten Post:

1. Häufigkeit: 1mal monatlich. Ist ne Abrechnungsdatei, die immer aber Monatsende zur Verfügung gestellt wird
2. Es sind relativ wenige Datesätze. ca. 130
3. Das Quell/Zielformate sollte relativ stabil bleiben und sich selten ändern.

Hilft das für weitere Hinweise?
Vielen Dank & Gruß
Josh
Mitglied: 60730
60730 Oct 27, 2009 at 12:53:04 (UTC)
Goto Top
Servus,

Hilft das für weitere Hinweise?

mir leider nicht,

Max MustermannFirmaxyz12345678Musterzweckbbbbbbbbbbbbbbbbabbccddeeeeeeeeeeeeeeeeeeeeeeeeeeffggggggggggggggggggggggggggg
zwischen Max und Mustermann ist ein Leerzeichen - das ist "gut", aber hinter Mustermann ist sofort die Firma,

wenn das einzigste "Erkennungsmerkmal" einGroßer Buchstabe ist - dann ...

Gruß
Member: Biber
Biber Oct 27, 2009 at 13:04:47 (UTC)
Goto Top
Moin josken69,

danke für die Rück-Info.

Ich denke, wenn es "nur" diese Dimensionen hat, dann schrubbeln wir da eine kurze Batch zusammen und gut.

Wie T-Mo gestern schon angedeutet hat, lässt sich mit einer FOR/F "delims=" -Anweisung diese Quelldatei Zeile für Zeile einlesen.
Eine Sonderbehandlung sollen die Zeilen 1, 2 und die letzte erhalten.
Okay, bis zwei können wir während der Verarbeitung selbst zählen, aber die Anzahl Gesamtzeilen sollten wir vorher ermitteln.

Dafür lässt sich eine FindStr /n FOR/F -kombination verwenden (Zähle Anzahl Zeilen, die irgendwas enthalten oder die etwas nicht enthalten)

Lösung für Ermittlung der letzten Zeile/Anzahl Zeilen also z.B. im Batch:

 @echo off & setlocal
Set "meineDatei=d:\eine\Rechnungsdatei.xyz"  
FOR /F "delims=:" %%i in ('findstr /v /n "Ich wähle Tigerenten!" "%meineDatei%" ') do @set /a anz+=1  
Echo Anzahl Zeilen in "%meineDatei%": %anz%.  
...

Der Rest kann schematisch nach dem Beispiel laufen, das ich gestern gepostet habe.

Grüße
Biber
Member: josken69
josken69 Nov 03, 2009 at 11:48:50 (UTC)
Goto Top
Hallo,
nochmal eine Nachfrage vom Newbie dazu:
Ich habe jetzt folgendes Skript zusammengeschustert, aber es tut nicht was es soll. Das Echo mit dem File wird noch ausgegeben, das mit der Variable ignoretext aber bereits nicht mehr.
Er scheint also gar nich in die Prozedur prozessline zu laufen. Eine Veränderung der Datei findet auch nicht statt. Kann mir bitte nochmal jemand auf die Sprünge helfen? Danke
@echo off & setlocal 
Set "File=c:\Alone\DTAUS.txt"  
set "Bak=%File%.bak"   
set "debug=1"  
copy "%File%" "%Bak%"   
FOR /F "delims=:" %%i in ('findstr /v /n "0128E" "%File%" ') do @set /a anz+=1  
Echo Anzahl Zeilen in "%File%": %anz%.  
FOR /F "skip=1 delims=" %%i in ("%File%") do set "line=%%i"  & call:processline  

if "%debug%"=="1" echo %file%  
Goto :eof 

:processline
Set "Line=%line:&=§%"   
set "var=ignoretext" & call:trim %line:~0,92%  
if "%debug%"=="1" echo wert1=ignoretext%  

set "var=bezahler_14a" & call:trim %line:~93,27%  
set "var=leerblock_14b" & Call:Trim %line:~120,8%  
set "var=empfaenger_15" & Call:Trim %line:~128,27%  
set "var=zweck_16" & call:trim %line:~145,27%  
set "var=waehrung_17a" & call:trim %line:~172,27%  
set "var=reserve_17b" & call:trim %line:~173,2%  
set "var=erweit1_18" & call:trim %line:~175,2%  
set "var=kennz1_19" & call:trim %line:~177,2%  
set "var=zweck2_20" & call:trim %line:~179,27%  
set "var=kennz2_21" & call:trim %line:~206,2%  
set "var=erweit2_22" & call:trim %line:~208,27%  
set "var=leerblock2_23" & Call:Trim %line:~235,11%  

Set "lineout=%ignoretext%%bezahler_14a%%leerblock_14b%%empfaenger_15%%zweck_16%%waehrung_17a%%reserve_17b%%erweit1_18%%kennz1_19%%zweck2_20%%kennz2_21%%erweit2_22%%leerblock2_23%  
Set "lineOut=%lineout:§=^&%"  
Echo >>"%File%" %lineOut%   

::>>"%File%" Echo %ignoretext%%bezahler_14a%%leerblock_14b%%empfaenger_15%%zweck_16%%waehrung_17a%%reserve_17b%%erweit1_18%%kennz1_19%%zweck2_20%%kennz2_21%%erweit2_22%%leerblock2_23% 
::goto :WriteLine 
:goto :eof
:trim ---setzt eine Variable %var1% auf Wert (alle Parameter) 
Set "%var%=%*"  

goto :eof
Member: Biber
Biber Nov 03, 2009 at 15:42:04 (UTC)
Goto Top
Moin josken69,

sorry für die späte Antwort.

Füge bitte mal in Zeile 8 die Option "usebackq" dazu.

Zeile 8 bisher:
FOR /F "skip=1 delims=" ....
Zeile 8 neu:
FOR /F "usebackq skip=1 delims=" ........


Um der Frage zuvorzukommen: "usebackq" ist neudeutsch für "Mach es richtig".
Den Schalter vergess ich manchmal...

Grüße
Biber
Member: josken69
josken69 Nov 06, 2009 at 09:50:29 (UTC)
Goto Top
Hallo,
vielen Dank, bin nun nach einiger anderer dringender Arbeiten wieder an dem Thema. Aufgrund des Hinweises werden jetzt zwar Daten rausgeschrieben, aber ich habe immer noch Probleme mit der korrekten Umwandlung. Folgende konkrete Fragen habe ich:
1. In meiner Ursprungsdatei ist ja bis Position 92 alles korrekt. Dann erfolgt ein String von unterschiedlicher Länge in der Form Name, Vorname, an dessen Ende ein CRLF steht. Ich muss ermitteln wieviele Zeichen dieser String von Position 93 bnis CRLF enthält und ihn dann in meine neue Datei mit Leerzeichen auf 27 Stellen auffüllen. Wie kann man das realisieren?
2. In der Ursprungsdatei gehören ab Zeile 2 immer 2 Zeilen zu einem Datensatz und sollen in der neuen Datei in einer Zeile erscheinen. Wie entferne ich den CRLF in jeder zweiten Zeile?
3. Es sollen nur die Zeilen zwischen der ersten und der letzten Zeile so verarbeitet werden. Wie ich die erste Zeiel überspringe, habt ihr mir ja schon freundlicherweise gesagt, aber wie ist die Schleife aufzubauen, wenn die letzte Zeile nicht oder anders bearbeitet werden soll?

Sorry, hab wirklich schon einiges an eigenem Hirnschmalz in Versuche gesteckt, aber leider sind meine Fähigkeiten für so eine Aufgabe wohl zu beschränkt.
Thanx
Member: Biber
Biber Nov 06, 2009 at 17:08:14 (UTC)
Goto Top
Moin josken69,

die etwas größer Herausforderung in der sich langsam konkretisierenden Aufgabenstellung ist der Punkt 2:
2. In der Ursprungsdatei gehören ab Zeile 2 immer 2 Zeilen zu einem Datensatz und sollen in der neuen Datei in einer Zeile erscheinen.
Wie entferne ich den CRLF in jeder zweiten Zeile?

Bist du sicher, dass dieses Detail allen MitleserInnern von Anfang an hätte bekannt sein müssen?
Ärgerlich dabei ist, dass die CMD-Aarbeitung von Textdateien streng zeilenorientiert, stupide eine Zeile nach der anderen.
Immer unter der Annahme, dass auch eine Zeile wie jede andere strukturiert ist.

In deinem Fall müsste die Mimik (in einem Batchfile) entsprechend geändert werden von
jetzt:

Lese alle Zeilen von der zweiten an
Mache mit jeder Zeile ein call.processline
BissuFertigbistbeiZeileLetzteMinus1

in neu:

Lese alle Zeilen von der zweiten an
Mache mit jeder Zeile ein
WennEineEinsVonZweiZeile merkDirzeileEins
WennEineZweiVonZweiZeile mache ein :ProzesslineEinsUndZwei
BissuFertigbistbeiZeileLetzteMinus1

Können wir auch machen, aber...
ist es vertretbar für dich, mal so ein halbes dutzend Zeilen (ggf. anonymisiert) deiner Quelldatei zu posten mit einem Beispiel Input-Ist/Output-Soll.?

Zusatzfrage:
Kommt denn nicht ein "falsches" Ergebnis raus, wenn du die Gesamtzeilenanzahl so ermittelst:
FOR /F "delims=:" %%i in ('findstr /v /n "0128E" "%File%" ') do @set /a anz+=1
...und hinterher ALLE Zeilen verarbeitest?

Grüße
Biber
Member: josken69
josken69 Nov 10, 2009 at 13:09:46 (UTC)
Goto Top
Hallo,
nochmal vielen Dank und sorry für die Verwirrung. Ich hab viel zu kompliziert gedacht. Wie sich jetzt rausgestellt hat muss ich nur jede Zeile außer der ersten mit Leerzeichen auffüllen bis Position 128 erreicht ist.
Also: Ermitteln, bis zu welcher Position ist die Zeile mit Text gefüllt, wieviele Zeichen fehlen bis Postion 128, Ergänze entsprechend um soviele Leerzeichen (Blanks). So das ist nun meine endgültige Aufgabenstellung, zu der ich nochmal Hilfe benötige. Vielen Dank, hoffentlich zum Letzten face-wink)