On 1 Apr 2004, Werner Warweg <- Werner.Warweg@t-online.de wrote:
Karl Pflästerer schrieb:
Wie sind denn die einzelnen Sätze vonaeinader getrennt? Ich nehme an newline und du hast dies nur in deiner E-Mail wegen der Zeilenlänge so nicht dargestellt? Die Sätze sind 80 Byte lang und enden mit carriage-return/line feed (CRLF,0d0a)
Das ist gut. Dies machr es einfach, über sie zu iterieren. [...]
z. B. so (du beginnst mit 1 zu zählen): 1 2 3 4 5 6 7 8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 aabbbbbcccccdddddeefggggggggggggggggggggggggggggggggggggggggggggghhhhhhhhhhhiijk
und hierunter die Beispielfelder. meintest Du das so? Dann ist a = Satzart n b = Mandant n c = Kontonummer n d = Unterkonto n [...] (a = alpha, n = numerisch) weitere Satzarten kann ich später beschreiben. Ich benötige eigentlich erst einmal einen Ansatz, wie solch ein Programm anzugehen ist.
Jetzt erst einmal die simpelste Frage: wie liest du die Daten ein und spaltest sie in die einzelnen Felder auf. Wenn du eine Textdatei in Python in Python öffnest (mit file()) und sie zeilenweise einlesen möchtest, geht dies folgendermaßen: f = file('filename.txt') for line in f: print line f.close() Dies würde die Datei zeilenweise auf dem Bildschirm ausgeben. Um einzelne Abschnitte eines Strings zu erhalten, kann man in Python eine sogenannte Slice Notation benutzen; du gibst hierzu einen Start- und Endindex an; die Indexzählung beginnt bei 0. das Ergebnis ist ein rechtsseitig offenes Intervall (das Ende ist nicht mehr Bestandteil des Ergebnisses). Bsp:
s = '0123456789' s[0:2] '01'
Für deine Zwecke ist eine kleine Hilfsfunktion ganz praktisch. def substrings (s, *indice): return [s[beg-1:end] for (beg, end) in indice] Diese Funktion erwartet einen String und beliebig viele Tupel (die jeweils Start- und Endindex) angeben und liefert eine Liste mit den entsprechenden Abschnitten zurück. Ich schrieb oben »beg-1«, damit es für dich bequemer ist; da du von 1 zu zählen beginnst, muß der Index für Python um 1 erniedrigt werden. Das Ende muß nicht angepaßt werden, da es ja nicht im Ergebnis erscheint. Testen wir die Funktion.
s = "aabbbbbcccccdddddeefggggggggggggggggggggggggggggggggggggggggggggghhhhhhhhhhhiijk" substrings(s, (1,2), (3,7), (8,12), (13,17), (18,19), (20, 20), (21, 65), (66,76), (77,78), (79,79), (80,80)) ['aa', 'bbbbb', 'ccccc', 'ddddd', 'ee', 'f', 'ggggggggggggggggggggggggggggggggggggggggggggg', 'hhhhhhhhhhh', 'ii', 'j', 'k']
Scheint zu passen. Jetzt könnte man entweder über die Indice der Einträge einzelne Felder herausfischen oder mit Pattermatching (letzeres ist schöner). Angenommen, du wolltest Mandant und Kontonummer (b und c). Dann kannst du folgendes schreiben:
mand, ktnr = substrings(s, (3,7), (8,12)) mand 'bbbbb' ktnr 'ccccc'
Die Variablen mand, ktnr haben also jetzt den Wert, der in dem String an (3,7) bzw. (8,12) stand. Das ist im Groben, was du brauchst.
Ich denke, wenn das Kontenplan "Einlese- und Aufbereitungsprogramm" steht sind die anderen Modifikationen.
Dies kann mit obigem erstellt werden.
Vorsicht Falle: Daten kommen von Groß-EDV (EBCDIC-Code) und Umlaute seltsam: RCKST., das soll RÜCKST. (Rückstellung) heißen KST KÖST (Körperschaftssteuer)
Solange die Daten nur gelsen, verglichen und geschrieben werden, sollte dies kein Problem darstellen. Was ist nicht weiß: Stehen die Ziffern und der Dezimalpunkt bei EBCDIC-Code an der gleichen Stelle wie bei ASCII? Wird ein Punkt als Dezimalzeichen genutzt oder ein Komma? Wenn ein Punkt (der an der gleichen Stelle wie bei ASCII steht) verwendet wird, ist dies am einfachsten. Wenn diese Annahmen nicht zutreffen, muß man die Zeichen eben übersetzen (mit einer Tabelle); dies ist auch nicht wild.
148213018430 99998 311003 000108819 (Sollseite des Kontos) 148213099998 18430 311003 000135425 (Habenseite des Kontos) 1 2 3 4 5 6 7
Ich verstehe nicht ganz, was obiges genau darstellen soll, um ehrlich zu sein.
12345678901234567890123456789012345678901234567890123456789012345678901234567890 llmmmmmnnnnnooooopppppqqqqqrrrrrrssssssttuuuuuuuuuvvvvvvvvvvvvvvvvvvwwxxxxxyyyyy l = Satzart n [...] y = Kostenträger
Das Ausschneiden erfolgt mit obiger Funktion.
Die Eingabe-Datei für obige Daten heißt FB82130.DAV
[...]
- erstellen einer "Saldenliste" Saldenliste ist eine Zeile je Konto Anfangsbestand laut Eröffnungswert im Kontensatz + und - der Bewegungszahlen (aus Buchungen) errechnet: neuer Endwert Beispiel: Überschrift: Saldenliste Mandant 82130 vom 31.12.2003, Seite : 1
Konto Bezeichnung Anfangssaldo Umsatz-Soll Umsatz-Haben Endsaldo ccccc ggg...ggggg hhhhhhhhh,hh uuuuuuu,uu uuuuuuu,uu zzzzzzzzz,zz
Als Dezimaltrenner scheint ein Komma verwendet zu werden.
wobei h + uS - uH = z ist.
wenn n = 99998, dann ist u = uH, wenn p = 99998, dann ist u = uS
Interessant sind hier also: Die jeweilige Kontonummer, die Bezeichnung, und der Umsatz. Konto ist das, was du als Unterkonto bezeichnest? Also o und q? Wie berechnest du das Anfangssaldo? Als Übertrag vom Endsaldo aus der vorhergehenden Zeile? (und 0 zu Beginn?). Da mir dies noch nicht so klar ist, kann ich dir keine Beispiellösung geben. Hier nur ein Ansatz: import time def substrings (s, *indice): return [s[beg-1:end] for (beg, end) in indice] def proc_mand (mand, fun): inf = file('FB' + mand + '.DAV') fun(inf, mand) inf.close() def write_sald (inf, mand): outf = file('SALD' + mand + '.TXT', 'w') outf.write('Saldenliste Mandant %s vom %s, Seite 1 :\n' % (mand, time.strftime('%d.%m.%Y'))) outf.write('Konto Bezeichnung Anfangssaldo Umsatz-Soll Umsatz-Haben Endsaldo\n') for line in inf: soll, sk, haben, hk, bez, wert = substring(line, (8,12),(13,17),(18,22), (23,26),(51,68),(42,50)) . . . outf.close() Die letzte Funktion (write_saldo) ist noch unvollständig (wegen der Fragen). Aber das Prinzip sollte klar sein. Du hättest eine Funktion proc_mand(), die als Argumente die Mandantennummer und eine Funktion, die die eigentliche Arbeit erledigt bekommt (ob die Aufteilung so günstig für dich ist, weiß ich nicht). Man könnte auch daran denken, eine Klasse (Mandantendatei) zu schreiben, die die einzelnen Auswertungsmöglichkeiten als Methoden enthält. Dies ist aber leicht anzupassen, wenn das Grobgerüst steht. HTH Karl -- The PROPER way to handle HTML postings is to cancel the article, then hire a hitman to kill the poster, his wife and kids, and fuck his dog and smash his computer into little bits. Anything more is just extremism. -- Paul Tomblin, asr _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de