150 lines
5.2 KiB
Python
150 lines
5.2 KiB
Python
#!/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) ---")
|