Skip to main content

bankstatementparser-writer-xlsx: Excel writer for parsed bank statements

PyPI Version Python Versions License Coverage

An Excel .xlsx writer for data parsed by bankstatementparser — turn parsed transactions (a pandas DataFrame, a list of Transaction objects, or a list of plain dicts) into a polished workbook that accountants, auditors, and reconciliation macros can open directly.

Latest release: v0.0.14 — single write_xlsx(data, path, ...) function, 100% line + branch coverage, 100% docstring coverage, mypy --strict clean.

Contents

Overview

bankstatementparser-writer-xlsx is a small, focused companion to the bankstatementparser library. It does one thing well: given already-parsed bank-statement records, write a clean Excel workbook with a bold header row, one row per transaction, auto-sized columns, and an optional second Summary sheet.

The package consumes parsed data — it does not read PDFs, CSVs, or XML itself. Parsing (and the security surface that comes with untrusted input) lives upstream in the bankstatementparser core.

Install

bankstatementparser-writer-xlsx runs on macOS, Linux, and Windows and requires Python 3.10+. It pulls in bankstatementparser, openpyxl, and pandas automatically.

pip install bankstatementparser-writer-xlsx

Quick start

from bankstatementparser import CsvStatementParser
from bankstatementparser_writer_xlsx import write_xlsx

parser = CsvStatementParser("statement.csv")
df = parser.parse()                      # a pandas DataFrame
write_xlsx(df, "statement.xlsx")         # one polished workbook

That's an Excel workbook ready for your accountant. Add a summary sheet in one extra argument:

from bankstatementparser import CsvStatementParser
from bankstatementparser_writer_xlsx import write_xlsx

parser = CsvStatementParser("statement.csv")
df = parser.parse()
write_xlsx(df, "statement.xlsx", summary=parser.get_summary())

Input shapes

write_xlsx(data, path, *, sheet_name="Transactions", summary=None) accepts three input shapes and normalises each to a flat table:

Input Column order
pandas.DataFrame (from a parser's .parse()) the DataFrame's own column order
list[bankstatementparser.Transaction] the stable Transaction field order
list[dict] the union of keys, in first-seen order

A header row (bold) is written to the sheet_name sheet, followed by one row per record. Columns are auto-sized to their widest cell, capped at 60 characters so wide descriptions don't run off-screen (the cell content itself is never truncated — only the displayed column width).

Empty input is accepted: an empty list writes an empty sheet (no header), while an empty DataFrame that still carries column labels writes a header-only sheet.

Value coercion

Spreadsheet cells can't hold arbitrary Python objects, so the writer coerces the rich types the parser emits:

Python type Written as
decimal.Decimal float (Excel has no decimal type; floats aggregate natively)
datetime.date / datetime.datetime native Excel date cell (unchanged)
str, int, float, bool, None unchanged
None / float('nan') (e.g. a missing DataFrame cell) blank cell
anything else str(value)

bool is preserved as a true/false cell (it is not coerced to 0/1), and a missing list[dict] key writes a blank cell in the same way a None value does.

Errors

write_xlsx validates its data argument and fails fast with a precise exception rather than writing a malformed workbook:

Condition Raised
data is neither a DataFrame nor a list/tuple (e.g. a str or int) TypeError
data is a non-empty sequence whose items are neither dict records nor Transaction objects (e.g. [42]) ValueError
from bankstatementparser_writer_xlsx import write_xlsx

try:
    write_xlsx("not-a-table", "out.xlsx")  # a bare str is not a table
except TypeError as exc:
    print(f"rejected: {exc}")

try:
    write_xlsx([42], "out.xlsx")           # 42 is not a dict/Transaction
except ValueError as exc:
    print(f"rejected: {exc}")

The summary sheet

If you pass summary= a mapping (for example a parser's get_summary() result), the writer adds a second sheet titled Summary with a bold Key / Value header and one row per item:

from decimal import Decimal

from bankstatementparser_writer_xlsx import write_xlsx

transactions = [
    {"date": "2026-06-01", "description": "Salary", "amount": Decimal("3000.00")},
    {"date": "2026-06-03", "description": "Coffee Shop", "amount": Decimal("-4.20")},
]

write_xlsx(
    transactions,
    "out.xlsx",
    summary={
        "account_id": "DE89370400440532013000",
        "transaction_count": 128,
        "total_amount": Decimal("12045.67"),
        "currency": "EUR",
    },
)

Examples

Six runnable examples live in examples/ and are exercised in CI on every commit. Together they cover every supported input shape, option, coercion rule, and error path of write_xlsx:

When not to use this package

  • You need a custom sheet layout. The single-sheet (+ optional Summary) structure is intentionally simple. Compose your own openpyxl workbook if you need pivot-ready, multi-sheet layouts.
  • You need .xls (legacy binary). openpyxl writes .xlsx only; convert downstream if you must.
  • You need encrypted output. Out of scope; encrypt the produced .xlsx downstream with a tool like msoffcrypto-tool.
  • You want to read Excel. This package is a writer.

Development

git clone https://github.com/sebastienrousseau/bankstatementparser-writer-xlsx
cd bankstatementparser-writer-xlsx
poetry env use python3.12
poetry install
poetry run pytest        # 100% line + branch coverage gate
poetry run ruff check bankstatementparser_writer_xlsx tests
poetry run mypy bankstatementparser_writer_xlsx
poetry run interrogate -c pyproject.toml bankstatementparser_writer_xlsx

Security

bankstatementparser-writer-xlsx consumes already-parsed data, not raw statement files — the PDF/CSV/XML parsing surface lives upstream in the bankstatementparser core. Reporting practice, supported versions, and supply-chain posture are documented in SECURITY.md.

Documentation

License

Licensed under the Apache License, Version 2.0. Any contribution submitted for inclusion shall be licensed as above, without additional terms.

Contributing

Contributions are welcome — open an issue or PR on the repository.

Acknowledgements

Built on the bankstatementparser library and openpyxl.

Metadata

Release files for bankstatementparser-writer-xlsx 0.0.14

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bankstatementparser-writer-xlsx 0.0.14
File Size Uploaded
bankstatementparser_writer_xlsx-0.0.14.tar.gz 13.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bankstatementparser-writer-xlsx 0.0.14
File Interpreter ABI Platform
bankstatementparser_writer_xlsx-0.0.14-py3-none-any.whl Python 3 none any Details

Total release size: 28.6 kB

Release files / bankstatementparser_writer_xlsx-0.0.14.tar.gz

Download URL bankstatementparser_writer_xlsx-0.0.14.tar.gz
Size 13.4 kB
Tags Source
SHA-256 checksum
How to use checksums
87287bc7d2b3e00d43153b4ecd1440016a3ecf35141805f77fb2778ae820cd89
BLAKE2b-256 checksum
How to use checksums
6113349f1d6b0a5813438a9e7697065b7f9d47dff6a106f06d8b4f29fabba8f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / bankstatementparser_writer_xlsx-0.0.14-py3-none-any.whl

Download URL bankstatementparser_writer_xlsx-0.0.14-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1d9fd9974c3af0e6cf4070e9d0253c5cce065d764d8ffb008011f2f933ce2664
BLAKE2b-256 checksum
How to use checksums
4ec739ba6fba9bacff4cae794add20e55b336376487a40563c9dcb296bc832ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.0.18

2 release files

0.0.15

2 release files

This release

0.0.14 This release

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page