141 lines
4.7 KiB
Python
141 lines
4.7 KiB
Python
#!/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
|