#!/usr/bin/env python3 """ 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 """ 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, "bic": "", } try: bic_obj = BIC.from_bank_code("DE", bankleitzahl_clean) result["bic"] = str(bic_obj) except (InvalidBankCode, Exception): pass return result 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 "" # 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 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 Eingabedatei 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_lines = [] for i, row in enumerate(rows): 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} - 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}: {e}", file=sys.stderr) output_lines.append(format_output_line(row, "", "")) # Schreibe Ausgabedatei with open(args.ausgabe_datei, mode="w", encoding="iso-8859-1", newline="") as outfile: outfile.write("\n".join(output_lines) + "\n") print(f"Erfolgreich verarbeitet: {len(output_lines)} 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: try: input("\\\\n--- Fertig (Enter zum Schliessen) ---") except EOFError: pass