#!/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. 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 import sys from schwifty import IBAN, BIC from schwifty.exceptions import InvalidBankCode def generate_iban(kontonummer: str, bankleitzahl: str) -> dict: """Erzeugt eine deutsche IBAN aus Kontonummer und Bankleitzahl.""" try: bankleitzahl_clean = str(int(bankleitzahl)) # fuehrende Nullen entfernen except ValueError: bankleitzahl_clean = bankleitzahl iban_obj = IBAN.generate("DE", bank_code=bankleitzahl_clean, account_code=kontonummer) result = { "iban": str(iban_obj), "bankleitzahl": bankleitzahl_clean, "kontonummer": kontonummer, } # Versuche BIC zu finden try: bic_obj = BIC.from_bank_code("DE", bankleitzahl_clean) result["bic"] = str(bic_obj) except (InvalidBankCode, Exception): result["bic"] = "" 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 # 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 def main(): parser = argparse.ArgumentParser( description="Konvertiert eine CSV mit Kontodaten (BLZ + Konto) in eine CSV mit IBAN und BIC." ) 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) rows = [] for encoding in ["iso-8859-1", "utf-8", "cp1252"]: try: with open(args.eingabe_datei, mode="r", encoding=encoding, newline="") as f: reader = csv.reader(f, delimiter=";", quotechar='"') rows = list(reader) break except UnicodeDecodeError: continue except FileNotFoundError: print(f"FEHLER: Datei nicht gefunden: {args.eingabe_datei}", file=sys.stderr) return if not rows: print("FEHLER: Keine Daten gelesen.", file=sys.stderr) return output_rows = [] for i, row in enumerate(rows): # Finde BLZ und Kontonummer bankleitzahl, kontonummer = find_blz_and_konto(row) 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) continue try: data = generate_iban(kontonummer, bankleitzahl) 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} # 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 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) print(f"Erfolgreich verarbeitet: {len(output_rows)} Zeilen.") print(f"Ergebnis gespeichert in: {args.ausgabe_datei}") if __name__ == "__main__": try: main() except Exception as e: print(f"\\nFEHLER: {e}", file=sys.stderr) print("\\n--- Details:", file=sys.stderr) import traceback traceback.print_exc() finally: input("\\n--- Fertig (Enter zum Schließen) ---")