davidannebicque/html-to-spreadsheet-bundle
A Symfony bundle that converts annotated HTML tables into Excel, OpenDocument, or CSV files using declarative data-xls attributes. Style cells, add formulas, images, and multiple sheets with Twig and HTML instead of the PhpSpreadsheet API.
Architecture fit. The package is a thin adapter, not a platform: it parses annotated HTML tables (typically Twig-rendered) and drives PhpSpreadsheet to emit XLSX/ODS/CSV. Its actual architectural value is the DSL — data-xls-* attributes become the authoring surface, so layout and formatting work moves from PHP developers to whoever can edit a template. That is a real lever for reporting/export-heavy back offices. It fits server-rendered Symfony MVC with Twig; it does not fit API-first or SPA stacks, where there is no HTML layer and the abstraction collapses into "call PhpSpreadsheet, but indirectly." Note a framing correction: this is a Symfony bundle, not a Laravel package. There is no service provider, facade, or Laravel config integration; the abstraction leaks immediately outside Symfony's container.
Integration feasibility. On Symfony 6.4/7.x with PHP 8.2+ and PhpSpreadsheet 4.x/5.x, integration is a composer require, a YAML config file, and a trait or service call — genuinely an afternoon. On Laravel, budget 1–3 days of glue (manual instantiation, config translation, no autowiring of the renderer) plus permanent divergence from upstream, with no guarantee the author accepts Laravel-oriented PRs. That glue is unpaid maintenance debt.
Technical risk. High, concentrated in the supply chain rather than the code:
strict: true.money → Euro formatting) bake in locale assumptions; ODS writer fidelity differs from XLSX for conditional formatting, comments, and formulas.Key questions. (1) Are the HTML templates developer-authored, or can tenant/user content reach the parser? (2) What is the largest export we must support, and is that synchronous or queued? (3) Do we need raw PhpSpreadsheet escape hatches, and does the bundle expose the underlying workbook object? (4) Who is on the hook if the maintainer goes quiet — do we have a fork owner and a patching budget? (5) Do we need non-Euro, non-French number and date formatting in v1? (6) Is the real requirement "author spreadsheets in Twig," or just "produce an XLSX" — because if it's the latter, direct PhpSpreadsheet or Laravel Excel is the lower-risk answer.
Stack fit. Strong fit: Symfony 6.4/7.x/8.x, PHP 8.2+, Twig already in the stack, PhpSpreadsheet likely already a transitive dependency of something. Weak fit: Laravel (needs a hand-rolled bridge), any polyglot stack where exports would be better served by a dedicated service in Python/Node, and any environment pinned below PHP 8.2.
Migration path. Do not adopt as infrastructure; adopt as a template-authoring convenience behind an internal seam. Define a narrow interface — SpreadsheetExporter::export(TemplateRef $template, array $data, Format $fmt): StreamedResponse — and let this bundle be one implementation. That keeps a swap to Laravel Excel, OpenSpout, or direct PhpSpreadsheet to a single class. If you are on Laravel, treat the framework mismatch as the deciding factor and evaluate Laravel Excel with Blade partials first; the DSL benefit is roughly replicable with Blade components and less glue.
Compatibility. Verify on your exact PHP minor and Symfony minor; the Symfony 8.x badge is a claim, not evidence given the usage base. Pin the bundle and PhpSpreadsheet explicitly and add a lockfile review to your dependency policy. Test all three writers if you promise all three — ODS is the one most likely to regress quietly, and CSV's single-sheet behavior needs to be a documented product limitation, not a surprise.
Sequencing. (1) Two-day spike: one representative report, both XLSX and ODS, with a real-size dataset to measure memory and wall time. (2) Land the internal façade and golden-file regression tests before any template author touches the DSL. (3) Ship one low-stakes export behind a feature flag. (4) Publish an internal attribute cheat-sheet and style registry so the DSL does not sprawl. (5) Review at one quarter: promote to standard, or retire and keep the façade. Gate the promote/retire decision on whether template authors actually used the DSL — if PHP developers ended up writing the templates anyway, the abstraction earned nothing.
Maintenance. Assume you will vendor or fork within 12–18 months. Budget roughly 10–20% of one engineer per quarter for dependency bumps, PhpSpreadsheet major upgrades, and patch absorption. Version-pin aggressively; do not track dev-main as the README's WIP status implies churn.
Support. There is effectively no community: no Stack Overflow corpus, no dependents to learn from, French-language preset naming and docs. Write internal documentation for the attribute set you actually permit — treat the README as the spec and the code as the truth, and reconcile the two before rollout. Every attribute in the cheat-sheet is an attribute someone will copy.
Scaling. Cost is dominated by PhpSpreadsheet, not this bundle: memory scales with cell count and styles, and autosize with content length. Design for asynchronous export — queue the job, write to object storage, return a signed link — rather than streaming large workbooks inline in a web request. Enforce per-export row/column caps and a timeout. Remote image fetching adds outbound egress and a third-party availability dependency inside your request path; prefer data-URI or pre-fetched local files, and if remote URLs must be supported, allowlist hosts.
Failure modes to instrument. Malformed or shifted table markup producing silently misaligned columns; merge overlap (rowspan/colspan collisions) throwing only in strict mode; conditional formatting evaluated against non-numeric cell values; image fetch timeouts or SSRF blocks; CSV exports containing only sheet one while users expect the full workbook; memory exhaustion on large exports; ODS formula and comment fidelity drift versus XLSX. Log the rendered template identifier and the input row count with every export so field reports are diagnosable.
Ramp-up. Low for Twig-fluent developers — a few hours to first useful export given the README examples. Moderate for the PHP owner — one to two days, most of it PhpSpreadsheet semantics and the Laravel/Symfony wiring question. The durable cost is that DSL fluency becomes a single-team asset; without the cheat-sheet and golden-file tests, that knowledge walks out the door with the first person who learned it.
How can I help you explore Laravel packages today?