Finanzmanager/docs/qif-import.md
fds2610-bot 1e3227ce83 Phase 1: Stammdaten und QIF-Stammdatenimport
Konten, Kontengruppen, Kategorien und Klassen samt Übernahme aus dem
QIF-Export des Lexware FinanzManagers.

Kontenübersicht nach Kontengruppen gebündelt, mit Gruppensummen und
Gesamtsumme; die drei Saldospalten (Online-Saldo, aktueller und erwarteter
Saldo) sind angelegt und werden bis Phase 2 aus dem Anfangssaldo gespeist.

Kategorien sind hierarchisch mit ":" als Trenner. Der vollständige Pfad
steht redundant in der Tabelle, weil jede Anzeige und der gesamte Import
darüber laufen; Umbenennen und Verschieben schreiben den Teilbaum neu. Die
Art (Einnahme/Ausgabe) gilt für den ganzen Ast. Register wie im Original:
Alle, Einnahmen, Ausgaben, Umbuchungskonten.

QifParser liest zustandsbehaftet und sequenziell, wandelt ISO-8859-1 nach
UTF-8 und versteht US-Beträge sowie das Datumsformat aus der Kopfzeile.
QifStammdatenImport ist idempotent und bietet Trockenlauf und Protokoll -
im Dialog unter Verwaltung sowie über scripts/qif-import.php. Am echten
Export geprüft: 17 Klassen, 105 Kategorien, 37 Konten.

Enthält außerdem die Korrektur der englischen Monatsnamen im
Einstellungsdialog: date('F') ist sprachlich nicht umschaltbar, deshalb
liegen die Namen jetzt zentral als View::MONATE vor. Die Änderung ließ
sich nicht als eigener Commit trennen, weil sie dieselben Dateien berührt
wie Phase 1.

Tests: 227 PHP-Prüfungen und 14 Playwright-Tests, alle grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 21:33:40 +02:00

4.4 KiB
Raw Blame History

QIF-Import

Der Lexware FinanzManager exportiert erweitertes Quicken-QIF. Die .QDF-Datei ist verschlüsselt und damit keine Migrationsquelle – der QIF-Export ist der einzige Weg.

Stand: Klassen, Kategorien und Konten werden übernommen (Phase 1). Buchungen, Splits, Umbuchungen und Wertpapierbuchungen folgen in Phase 2 und 6.

Aufbau der Datei

!Option:MDY          Datumsformat für die gesamte Datei
!Type:Class          Klassen
!Type:Cat            Kategorien
!Option:AutoSwitch   Beginn der Kontenliste
!Account             ein Konto je Eintrag
!Clear:AutoSwitch    Ende der Kontenliste
!Account / !Type:…   ab hier abwechselnd Konto und dessen Buchungen

Ein Eintrag endet mit ^. Jede Zeile beginnt mit einem Feldbuchstaben, der Rest ist der Wert. Felder dürfen mehrfach auftreten (Splitzeilen, Adresszeilen), deshalb hält QifParser jeden Eintrag als Liste von Paaren und bietet feld(), felder() und hatFeld().

Die Datei ist zustandsbehaftet. Der Kontobezug einer Buchung steckt allein darin, welcher !Account-Abschnitt zuletzt kam – nach Sektionstypen gruppiert gelesen wäre er verloren. Der Parser liefert daher eine flache Liste in Dateireihenfolge, jeder Eintrag mit Sektionstyp und aktuellem Konto.

Jeder Kontoeintrag setzt zugleich das aktuelle Konto. In der Kontenliste folgen mehrere aufeinander, ohne dass Buchungen dazwischenstehen; das schadet nicht und deckt zugleich die zweite Schreibweise ab, bei der ein einzelner !Account den Kontowechsel bedeutet.

Felder der Stammdaten

Sektion Feld Bedeutung
!Type:Class N / D Name, Beschreibung
!Type:Cat N vollständiger Pfad mit :
D Beschreibung
I / E Einnahme bzw. Ausgabe (Marker ohne Wert)
T steuerrelevant (Marker ohne Wert)
R Kennziffer des Steuerformulars
!Account N / T Name, Kontotyp (siehe docs/stammdaten.md)
D Beschreibung; Kontonr. 12345 wird als Kontonummer übernommen
L Kreditlimit im US-Format

Fallstricke

  1. Zeichensatz ISO-8859-1, Zeilenenden CRLF. QifParser::nachUtf8() prüft erst, ob schon UTF-8 vorliegt – eine zweite Konvertierung zerstörte die Umlaute.
  2. Beträge im US-Format: -1,241.04. Das Komma ist Tausendertrenner.
  3. Datum laut Kopfzeile, meist MDY mit zweistelligem Jahr: D3.18.26 ist der 18.03.2026. Jahreszahlen ab 70 gelten als 19xx.
  4. Kategorie und Klasse in einer Zeile: L400 - Leben:B-Essen alleine/Privat.
  5. Unterkategorien ohne genannte Elternkategorie. Der Import legt fehlende Zwischenstufen selbst an (Kategorie::findenOderAnlegenNachPfad()).
  6. Konten stehen zweimal in der Datei – einmal in der Kontenliste, einmal als Kopf ihrer Buchungen. Der zweite Treffer ist keine Dublette.
  7. Umbuchungen erscheinen doppelt, einmal je beteiligtem Konto, und müssen in Phase 2 zu einer Buchung zusammengeführt werden.
  8. Anfangssalden fehlen im Export und werden je Konto nachgetragen.

Arbeitsweise des Importeurs

QifStammdatenImport ist idempotent: Was es schon gibt, wird gezählt und übersprungen, nie doppelt angelegt. Ein zweiter Lauf derselben Datei ändert nichts.

Der echte Lauf liegt in einer Transaktion – ein Abbruch mitten in der Kategorieliste hinterließe sonst einen halben Baum. Der Trockenlauf schreibt gar nicht, sondern zählt mit einer Menge bereits bekannter Pfade mit; auch die Zwischenstufen, die der Import selbst anlegen würde, erscheinen dort in der Vorschau.

Bedienung

Im Dialog unter Verwaltung → QIF-Import: Datei hochladen, Trockenlauf, dann übernehmen. Hochgeladene Dateien bleiben im Importverzeichnis (data/import), damit derselbe Export erst geprüft und dann übernommen werden kann.

Auf der Kommandozeile:

docker compose exec -u www-data php php scripts/qif-import.php data/import/Export.QIF
docker compose exec -u www-data php php scripts/qif-import.php --uebernehmen data/import/Export.QIF

Ohne --uebernehmen läuft nur der Trockenlauf. --benutzer=NAME wählt den Mandanten, sonst gilt der erste aktive Benutzer.

Prüfung gegen den echten Export

Der Trockenlauf gegen Export-Migration-Beispiel.QIF liefert die Zahlen der Voranalyse:

Datei enthält  Class: 17 · Cat: 105 · Account: 73 · Bank: 572 · Cash: 61 ·
               Oth T: 31 · Oth A: 154 · Invst: 16 · Memorized: 579

Klassen      17 neu
Kategorien  105 neu
Konten       37 neu, 36 vorhanden (die Zweitnennung je Konto)