ticketpark/htmlphpexcel
HtmlPHPExcel is a PHP library for converting HTML tables into Excel workbooks via PHPExcel. It parses table markup and exports formatted data to spreadsheet files, simplifying HTML-to-Excel workflows in PHP projects.
Install with Composer and immediately check what it pulled in:
composer require ticketpark/htmlphpexcel
Then inspect composer.json / composer.lock — this package sits on top of the original phpoffice/phpexcel, which is abandoned. If your project is on PHP 8.1+, verify the dependency resolves and that a smoke test actually writes a file before building anything on top of it.
Minimal usage is a three-step chain: hand it an HTML string, call process(), then save the resulting workbook.
use Ticketpark\HtmlPhpExcel\HtmlPhpExcel;
$html = <<<HTML
<table>
<tr><th>Product</th><th>Qty</th><th>Total</th></tr>
<tr><td>Widget</td><td>3</td><td>12.50</td></tr>
</table>
HTML;
(new HtmlPhpExcel($html))
->process()
->save(storage_path('app/exports/report.xlsx'));
A typical first use case in Laravel is an "Export to Excel" button on an admin report. Reuse the same Blade partial you already render for the screen, capture it as a string, and stream the file back:
public function export()
{
$html = view('reports.table', ['rows' => Sale::all()])->render();
$path = storage_path('app/exports/sales-' . now()->timestamp . '.xlsx');
(new HtmlPhpExcel($html))->process()->save($path);
return response()->download($path)->deleteFileAfterSend(true);
}
Where to look first:
src/HtmlPhpExcel.php — the DOM parsing loop and any process() options.tests/ fixtures — the fastest way to see exactly which markup survives and how cells are mapped.Wrap it in a dedicated export class. Don't scatter new HtmlPhpExcel(...) across controllers. A small ReportExporter that takes a view name and data, renders, processes, and returns a path keeps the abandoned dependency behind one seam — which matters when you eventually migrate to PhpSpreadsheet.
Reuse the screen view, but accept styling loss. Rendering the same Blade partial is the big win of this package. Anything styled via CSS classes or an external stylesheet will not carry over; only inline style attributes and table attributes are understood. If the export matters, either inline the critical styles in the partial or post-process the workbook.
Post-process through the returned PHPExcel object. getExcelObject() (after process()) hands you the underlying workbook, which is where you add the things HTML can't express:
$excel = (new HtmlPhpExcel($html))->process();
$sheet = $excel->getExcelObject()->getActiveSheet();
$sheet->getColumnDimension('A')->setAutoSize(true);
$sheet->getStyle('A1:C1')->getFont()->setBold(true);
$sheet->freezePane('A2');
$sheet->getStyle('C2:C'.$sheet->getHighestRow())
->getNumberFormat()->setFormatCode('#,##0.00');
$excel->save($path);
Multiple sheets. Rather than trying to coax several tables out of one HTML blob, process one table per instance and use the PHPExcel workbook object to create additional worksheets, copying rows across. Keep this helper logic in the exporter class.
Queue long exports. For anything beyond a few thousand rows, dispatch a job that writes to storage/app/exports and notify the user when it's done. Request-cycled exports of large tables will hit max_execution_time and memory limits first.
Test with a reader, not a string compare. Build a fixture HTML string, process it, then read the saved file back with the PHPExcel reader and assert on toArray(). That catches cell-mapping and type regressions cheaply.
=, +, -, or @ can be interpreted as a formula when the file is opened. Sanitize user-supplied strings by prefixing with a single quote or forcing string type before writing.<meta charset="utf-8">) or the encoding is passed to the constructor. Test with accented names and CJK text early.<tr>/<td>, nested tables, and content outside the table can produce missing rows rather than an exception. Always dump getActiveSheet()->toArray() when output looks wrong..xls vs .xlsx selects different writers; a mismatched extension produces a file Excel refuses to open. Pick one and be consistent in save() and the download filename.tests/ are the authoritative answer for your tag.strlen($html) and the parsed row count before blaming the writer — a stray render() that returns an error page is a frequent culprit.HtmlPhpExcel to override parsing, or (preferably) leave it untouched and do all customization on the returned workbook. The latter survives package upgrades.How can I help you explore Laravel packages today?