Using the app
Bank layouts
How a bank lays its CSV out — encoding, delimiter, preamble, which column is which — is read off the file itself. There is no tab for this and no setup step: drop a statement on the Import tab and the app works the layout out, shows you every row it read on the review screen, and pins the layout when you commit. Every later export of the same shape reuses the pin unchanged.
Two things are deliberately not left to a fresh guess each time:
- Duplicates must keep working. A fingerprint is built from the parsed date, title and counterparty account. If a later, cleverer guess read a different column for the same bank, the same rows would fingerprint differently and a re-imported month would stop deduping. A pinned layout never moves: once a shape is confirmed, the guesser is not consulted for it again.
- An absence must stay visible. "The bank stopped sending the balance column" is a claim about what used to be there — only a remembered layout can make it, and the review head does (
not in this file: …).
What a layout holds#
| Setting | What it is |
|---|---|
| Encoding | UTF-8 or windows-1250. A byte-order mark is stripped either way. |
| Delimiter | One character — ;, ,, tab or |. |
| Skip rows | Junk lines above the header. Some banks write twenty-plus. |
| Has header | Without one, columns are positional: #1…#N. |
| Skip first data rows | Data rows to always drop from the top — some exports open with a balance summary shaped exactly like a transaction. |
| Date format | DD.MM.YYYY, DD-MM-YYYY, YYYY-MM-DD, or a timestamp whose time is dropped. |
| Decimal separator | , or .. Thousand separators are handled either way, including non-breaking spaces. |
| Amount mode | How direction is expressed — see below. |
| Row filter | Keep only rows whose column has one of the listed values, e.g. State = COMPLETED. |
| Fee column | A separate fee, subtracted from the amount. |
| Balance column | The running balance, if the export has one. Powers the continuity check. |
| Field mapping | Which column feeds date, title, counterparty, counterparty account, currency. One date per transaction — the transaction date; the second date column in the file is simply left unmapped. |
Four of those are worth refusing a file over: the date, the title, the amount columns, and the row filter — a filter whose column is gone keeps nothing out, which would import the rows it exists to drop. The rest are optional. A file lacking the fee, balance, counterparty or currency column the layout names still imports: the column reads as empty, the review head lists what wasn't there, and the balance check says balance not checked rather than quietly not running. Banks drop these between exports for reasons of their own — ING omits Saldo po transakcji from a statement generated with the running balance hidden, under an otherwise identical header.
Amount modes#
Banks express direction four ways:
- Signed — one column, negative for money out. Most banks.
- Debit / credit — two columns, one filled per row.
- Amount + direction — a magnitude plus a
DEBIT/CREDITmarker. - First non-empty of several — for banks where a transfer's amount lands in one column and a card payment's in another, and the header names don't tell you which.
How a dropped file is read#
First the format is sniffed: encoding, delimiter, where the table starts under the preamble, whether there is a header row, the date format and the decimal separator. Then the columns are assigned. The assignment reads header names in Polish and English (Data transakcji, Started Date, Kwota, Obciążenia/*Uznania*, Saldo) and, where a file has no header row at all, the shape of the cells themselves — which column holds dates, which holds IBANs, which running total steps by the amount beside it. It leaves a field alone rather than guess it: an unmapped field asks you a question, a wrongly mapped one quietly answers it.
Then it counts the rows each reading would lose. Names and shapes narrow every field to a handful of columns, and the file itself decides between them: the assignment that parses the most rows wins. This is what keeps a bank's habits from costing you a tenth of the statement — ING leaves Data księgowania empty on every card block, so the column whose name recommends it is the column that throws those rows away, and Data transakcji beside it keeps all of them. A single unreadable line does not move anything: it takes a pattern, not an anomaly, to override what the names said.
Finally the reading has to prove itself on the whole file. A layout that resolves the date, the title and the amount, and loses no more than a stray line or two — a bank's legal footer, a malformed row — goes straight to the review screen, where the head says which columns were chosen. A layout that cannot say that opens the mapper instead, prefilled with everything it did work out.
The pin#
Committing an import is what makes a layout permanent. The confirmed reading is stored together with the file's full header, and the next dropped file is matched against those remembered shapes before anything is guessed:
- Same shape — the pin is reused verbatim and the review head says `known layout`. Preamble length may drift between exports; the per-file skip rows override covers that without touching the pin.
- Same shape minus an optional column — still the pin. The absence is reported, not rediscovered:
not in this file: Saldo po transakcji, and the balance pill holds its slot withbalance not checked. - Same shape minus a column rows are made of — the file is re-read from scratch, and a banner says what happened: *this looks like «…», but Kwota is gone — the columns were re-read from the file*. Committing writes a new pin; the old one stays with the imports it made.
One habit worth knowing: if a new bank's export opens with a summary row — erste's first data row is the current balance, shaped exactly like a 0,00 transaction — just skip that row on the review screen before committing. A new pin learns from the exclusion: from the next import on, the row is dropped as a lead row automatically.
If a reading was ever wrong, adjust on the review head opens the mapper on the same file; saving re-stages the rows with your corrections, and the commit updates the pin, so the correction holds for every later export too.
The mapper#
The escape hatch, not a step: it opens when the app would not vouch for its own reading, or when you press adjust on the review screen.
It arrives pre-filled with everything the reading did establish, and every assignment is a guess in an editable control showing the first value it found in the column it names — the check happens in the mapping list rather than somewhere else on the screen. Field mapping comes first and is one list of six, the amount included: picking its mode is a chip row inside the amount field. File format and Extras fold shut behind a line stating what they are currently set to, and open again on a click. Every count sits in a strip under the title: fields mapped, rows parsed, and rows that fail on value format. A failing row is linked from there, marked in the table, and quoted underneath it in the parser's own words.
The preview#
Beside the mapping list, the source columns are tinted and tagged with the field they feed, and Parsed preview switches that table to the rows as they will be stored, per-cell errors included.
Both tables show every line of the file, a hundred at a time, and a line that will not become a transaction says why it won't: preamble, header, blank, dropped (by drop first rows) or filtered (by the row filter). Nothing is silently missing, and the line numbers run unbroken, so show it on a failing row lands on the page that holds it. Once there, the same link reads back and returns you to the page and the view you left. The table opens where the data starts — a bank's twenty junk lines are above it, one scroll up.
Hovering a line offers skip 1…N — the cut that declares everything through that line preamble, made from the row you can see rather than by counting into a number field. The cut that would leave the file without a single data row is refused rather than made. The Skip rows field is held to the same ceiling.
A row that fails to parse never has to be cut out at all. The import leaves it behind and says so on the review screen, so the legal footer most banks end a statement with costs nothing.
guess columns re-runs the whole assignment, which is what to press after correcting the delimiter or the skip-rows count. It never fires on its own over a mapping you have started editing.
The file you were correcting is stored with the pin, so a later adjustment still has a working preview. It never leaves your database.
When an import complains#
"The file is missing columns a row cannot be built without: …" means the expected header row wasn't found — usually the preamble changed length, so a junk line was read as the header. Try the per-file skip-rows override under Advanced first. An optional column the file simply doesn't have never raises this; it is reported on the review screen instead.
Two things worth checking on a new bank's first review: whether the amount column means the same thing on every row (for some banks it doesn't, and it's invisible until a card payment shows a blank amount), and whether the file carries a counterparty account — without one, transfers between your own accounts surface as uncategorized instead of being recognized.