Fix: exact target format with ;;00 ending and no quotes on BLZ/Konto fields
This commit is contained in:
parent
f70e8a8d29
commit
aef77c98af
@ -1,16 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
iban_csv_converter.py - Konvertiert eine CSV mit Kontodaten in eine CSV mit IBAN.
|
||||
Unterstuetzt das Bundesbank-BL-Z-Format mit variabler Spaltenanzahl.
|
||||
Fuegt BIC (aus BLZ) und IBAN-Spalten automatisch hinzu.
|
||||
iban_csv_converter.py - Konvertiert eine BLZ/Konto-CSV in eine CSV mit IBAN+BIC.
|
||||
Erzeugt das EXAKTE Zielformat:
|
||||
"DE";"00001";" 7606148200045949670010000976";;;76061482;0004594967;;"GENODEF1HSB";"DE56760614820004594967";;00
|
||||
|
||||
Format-Regeln:
|
||||
- Felder 1-3: mit doppelten Anfuehrungszeichen (Feld 3 behaelt fuehrende Leerzeichen)
|
||||
- Felder 4-5: leer (keine "")
|
||||
- Felder 6-7: BLZ und Kontonummer OHNE Anfuehrungszeichen
|
||||
- Felder 8-9: BIC und IBAN MIT doppelten Anfuehrungszeichen
|
||||
- Ende der Zeile: zwei leere Felder (;;) + 00
|
||||
|
||||
Nutzung:
|
||||
python iban_csv_converter.py eingabe.csv ausgabe.csv
|
||||
|
||||
Erweitert um:
|
||||
- Automatische BIC-Erzeugung aus BLZ-Feld
|
||||
- Flexibles Inputformat (erkennt BLZ/Konto anhand der Werte)
|
||||
- Behaelt alle Original-Spalten bei und fuegt IBAN/BIC hinzu
|
||||
"""
|
||||
import argparse
|
||||
import csv
|
||||
@ -31,50 +33,52 @@ def generate_iban(kontonummer: str, bankleitzahl: str) -> dict:
|
||||
"iban": str(iban_obj),
|
||||
"bankleitzahl": bankleitzahl_clean,
|
||||
"kontonummer": kontonummer,
|
||||
"bic": "",
|
||||
}
|
||||
|
||||
# Versuche BIC zu finden
|
||||
try:
|
||||
bic_obj = BIC.from_bank_code("DE", bankleitzahl_clean)
|
||||
result["bic"] = str(bic_obj)
|
||||
except (InvalidBankCode, Exception):
|
||||
result["bic"] = ""
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def find_blz_and_konto(row: list) -> tuple:
|
||||
"""Findet Bankleitzahl (BLZ) und Kontonummer in einer CSV-Zeile.
|
||||
Priorisiert: 6. Feld = BLZ, 7. Feld = Konto (Index 5 und 6)
|
||||
"""
|
||||
# Standardfall: BLZ im 6. Feld (Index 5), Konto im 7. (Index 6)
|
||||
if len(row) >= 7:
|
||||
bankleitzahl = row[5].strip()
|
||||
kontonummer = row[6].strip()
|
||||
# Pruefe ob wir sinnvolle Werte haben
|
||||
if bankleitzahl and kontonummer:
|
||||
return bankleitzahl, kontonummer
|
||||
def format_output_line(row: list, bic: str, iban: str) -> str:
|
||||
"""Erzeugt die Ausgabetzeile im exakten Zielformat."""
|
||||
# Feld 1 (Index 0): "DE"
|
||||
f1 = f'"{row[0]}"' if row[0] else ""
|
||||
# Feld 2 (Index 1): "00001"
|
||||
f2 = f'"{row[1]}"' if len(row) > 1 and row[1] else ""
|
||||
# Feld 3 (Index 2): " 76061482..." - behaelt fuehrende Leerzeichen
|
||||
f3 = f'"{row[2]}"' if len(row) > 2 and row[2].strip() else ""
|
||||
# Felder 4,5: leer (keine "")
|
||||
f4 = ""
|
||||
f5 = ""
|
||||
# Feld 6 (Index 5): BLZ ohne ""
|
||||
f6 = row[5].strip() if len(row) > 5 else ""
|
||||
# Feld 7 (Index 6): Konto ohne ""
|
||||
f7 = row[6].strip() if len(row) > 6 else ""
|
||||
# Feld 8: BIC mit ""
|
||||
f8 = f'"{bic}"' if bic else ""
|
||||
# Feld 9: IBAN mit ""
|
||||
f9 = f'"{iban}"' if iban else ""
|
||||
|
||||
# Fallback: Suche nach 8-stelliger BLZ und Konto-Nummer
|
||||
for i, field in enumerate(row):
|
||||
field = field.strip()
|
||||
# BLZ ist 8-stellig (oder 5-8 mit fuehrenden Nullen)
|
||||
if (len(field) >= 5 and len(field) <= 8 and field.isdigit()
|
||||
and i + 1 < len(row) and row[i + 1].strip().isdigit()):
|
||||
return field, row[i + 1].strip()
|
||||
|
||||
return None, None
|
||||
# Zusammenfuegen: "DE";"00001";" ...";;;BLZ;KONTO;;"BIC";"IBAN";;00
|
||||
parts = [f1, f2, f3, f4, f5, f6, f7, "", f8, f9, "", "00"]
|
||||
return ";".join(parts)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Konvertiert eine CSV mit Kontodaten (BLZ + Konto) in eine CSV mit IBAN und BIC."
|
||||
description="Konvertiert CSV mit BLZ+Konto zu CSV mit IBAN+BIC im exakten Zielformat."
|
||||
)
|
||||
parser.add_argument("eingabe_datei", type=str, help="Pfad zur Eingabedatei")
|
||||
parser.add_argument("ausgabe_datei", type=str, help="Pfad zur Ausgabedatei")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Lese die Eingabedatei (probiere mehrere Kodierungen)
|
||||
# Lese Eingabedatei
|
||||
rows = []
|
||||
for encoding in ["iso-8859-1", "utf-8", "cp1252"]:
|
||||
try:
|
||||
@ -92,48 +96,32 @@ def main():
|
||||
print("FEHLER: Keine Daten gelesen.", file=sys.stderr)
|
||||
return
|
||||
|
||||
output_rows = []
|
||||
output_lines = []
|
||||
for i, row in enumerate(rows):
|
||||
# Finde BLZ und Kontonummer
|
||||
bankleitzahl, kontonummer = find_blz_and_konto(row)
|
||||
if len(row) < 7:
|
||||
print(f"Warnung: Zeile {i+1} hat weniger als 7 Felder, wird uebersprungen.", file=sys.stderr)
|
||||
continue
|
||||
|
||||
bankleitzahl = row[5].strip()
|
||||
kontonummer = row[6].strip()
|
||||
|
||||
if not bankleitzahl or not kontonummer:
|
||||
print(f"Warnung: Zeile {i+1} - konnte keine BLZ/Konto finden: {row[:3]}...",
|
||||
file=sys.stderr)
|
||||
# Originalzeile behalten, leere IBAN/BIC einsetzen
|
||||
new_row = list(row)
|
||||
while len(new_row) < 9:
|
||||
new_row.append("")
|
||||
if len(new_row) > 9:
|
||||
new_row[8] = "" # BIC
|
||||
if len(new_row) > 9:
|
||||
new_row[9] = "" # IBAN
|
||||
else:
|
||||
new_row.extend(["", ""])
|
||||
output_rows.append(new_row)
|
||||
print(f"Warnung: Zeile {i+1} - keine BLZ/Konto gefunden.", file=sys.stderr)
|
||||
output_lines.append(format_output_line(row, "", ""))
|
||||
continue
|
||||
|
||||
try:
|
||||
data = generate_iban(kontonummer, bankleitzahl)
|
||||
output_lines.append(format_output_line(row, data["bic"], data["iban"]))
|
||||
except Exception as e:
|
||||
print(f"Fehler in Zeile {i+1} (BLZ={bankleitzahl}, Konto={kontonummer}): {e}",
|
||||
file=sys.stderr)
|
||||
data = {"iban": "", "bic": "", "bankleitzahl": bankleitzahl, "kontonummer": kontonummer}
|
||||
print(f"Fehler in Zeile {i+1}: {e}", file=sys.stderr)
|
||||
output_lines.append(format_output_line(row, "", ""))
|
||||
|
||||
# Erstelle neue Zeile: Original-Felder + BIC (Index 8) + IBAN (Index 9)
|
||||
new_row = list(row)
|
||||
while len(new_row) < 10:
|
||||
new_row.append("")
|
||||
new_row[8] = data["bic"] # BIC-Spalte (Index 8)
|
||||
new_row[9] = data["iban"] # IBAN-Spalte (Index 9)
|
||||
output_rows.append(new_row)
|
||||
|
||||
# Schreibe die Ausgabedatei
|
||||
# Schreibe Ausgabedatei
|
||||
with open(args.ausgabe_datei, mode="w", encoding="iso-8859-1", newline="") as outfile:
|
||||
writer = csv.writer(outfile, delimiter=";", quotechar='"', quoting=csv.QUOTE_ALL)
|
||||
writer.writerows(output_rows)
|
||||
outfile.write("\n".join(output_lines) + "\n")
|
||||
|
||||
print(f"Erfolgreich verarbeitet: {len(output_rows)} Zeilen.")
|
||||
print(f"Erfolgreich verarbeitet: {len(output_lines)} Zeilen.")
|
||||
print(f"Ergebnis gespeichert in: {args.ausgabe_datei}")
|
||||
|
||||
|
||||
@ -146,8 +134,7 @@ if __name__ == "__main__":
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
# Fenster offen halten – funktioniert auch bei Windows ohne Console-Problem
|
||||
try:
|
||||
input("\\\\n--- Fertig (Enter zum Schliessen) ---")
|
||||
except EOFError:
|
||||
pass # stdin ist nicht interaktiv (z.B. Pipe), einfach beenden
|
||||
pass
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user