PHP

php_excel

PHP Extension interface to the Excel writing/reading library

I

iliaal

Dernière activité 27 sept. 2026
iliaal/php_excel

604

étoiles

129

forks

0

issues ouvertes

excellibxlpeclphpphp-extensionxlsx

Ce README est souvent en anglais.

php_excel

Tests Windows Build Stars Version License: PHP-3.01 Follow @iliaa

php_excel: 7-10× faster Excel I/O for PHP

Native C extension for reading and writing Excel files in PHP, powered by LibXL. 7-10× faster than PhpSpreadsheet with substantially lower memory pressure. Full XLS and XLSX support: rich text, conditional formatting, formulas, autofilters, form controls, embedded charts, and structured tables. PHP 8.1+ minimum. 2.0 ground-up modernization shipped April 2026.

🚀 Install

Via PIE (PHP Foundation's PECL successor):

pie install iliaal/php-excel \
  --with-libxl-incdir=/path/to/libxl/include_c \
  --with-libxl-libdir=/path/to/libxl/lib64

Or build from source:

phpize
./configure --with-excel \
  --with-libxl-incdir=/path/to/libxl/include_c \
  --with-libxl-libdir=/path/to/libxl/lib64
make
sudo make install

Then add extension=excel.so to your php.ini.

LibXL is a commercial library; download it from libxl.com and point the configure flags at its include_c and lib64 directories.

🛠️ Getting started

<?php
$book = new ExcelBook(null, null, true); // xlsx mode
$book->setLocale('UTF-8');

$sheet = $book->addSheet('Sheet1');

$data = [
    [1, 1500, 'John', 'Doe'],
    [2,  750, 'Jane', 'Doe'],
];

$row = 1;
foreach ($data as $item) {
    $sheet->writeRow($row++, $item);
}

// formula
$sheet->write($row, 1, '=SUM(B1:B3)');

// untrusted input: AS_TEXT stores the string verbatim, with no '=' formula
// promotion. It takes a string, so cast first. See SECURITY.md.
$sheet->write($row, 2, (string) $userSuppliedValue, null, ExcelFormat::AS_TEXT);

// date with format
$dateFormat = new ExcelFormat($book);
$dateFormat->numberFormat(ExcelFormat::NUMFORMAT_DATE);
$sheet2 = $book->addSheet('Sheet2');
$sheet2->write(1, 0, (new DateTime('2024-08-02'))->getTimestamp(), $dateFormat, ExcelFormat::AS_DATE);

$book->save('output.xlsx');

save() stages the workbook to a temporary sibling file and renames it into place, so a failed save leaves the destination untouched. If the rename fails, local-path saves fail closed (return false); stream wrappers that omit rename() fall back to a direct write with a warning. Failed handle creation and rejected header, footer, font-size, and staging inputs emit warnings naming the cause. Suppress them with @ only where you handle false explicitly.

📊 Performance

Write 100,000 rows × 20 columns vs PhpSpreadsheet 5.5.0 on PHP 8.4.19 NTS, Apple M3:

Rows Cells php_excel PhpSpreadsheet Speedup
1,000 20K 0.05s / 85 MB 0.45s / 162 MB 10×
10,000 200K 0.55s / 153 MB 4.59s / 282 MB 9×
50,000 1M 2.72s / 508 MB 24.7s / 790 MB 9×
100,000 2M 5.37s / 908 MB 51.1s / 1,415 MB 10×

Reads are 8-9× faster than PhpSpreadsheet and 3× faster than OpenSpout, at the cost of memory that grows with the file, where OpenSpout streams in a flat 130 MB.

For read-heavy import paths, prefer readRow(), readCol(), or readRange() over per-cell read() loops. Pass false for $read_formula when cached values are enough, to skip the per-cell formula-text probe. For sparse sheets, readSparseRow() and readSparseCol() return only occupied cells keyed by their original column or row indexes.

Native memory and PHP's memory_limit

PHP's memory_get_peak_usage() reports about 2 MB for php_excel in the benchmark above because LibXL allocates on the C heap, outside PHP's memory manager and memory_limit. PHP's memory counters do not include these native allocations, even with real_usage set to true. This allows php_excel to write 100,000 rows without raising PHP's 128 MB limit, but the same run still peaked at 908 MB of process virtual memory (VmPeak). save() without a path, to a stream-wrapper URL, or while open_basedir is set copies the entire workbook into a PHP string, so that copy also counts against memory_limit.

php_excel can still run out of memory or hit an operating-system or container memory limit. Size your workers and concurrency using process-level memory measurements (such as resident set size), not PHP's memory counters alone. PHP arrays, strings, and buffered stream input also consume PHP-managed memory and remain subject to memory_limit; see stream-loading limits.

📦 Classes

Class Description
ExcelBook Workbook management: create, load, save, sheets, fonts, formats, pictures
ExcelSheet Cell read/write, formatting, printing, protection, hyperlinks, data validation
ExcelFormat Cell formatting: colors, borders, number formats, alignment, patterns
ExcelFont Font properties: name, size, bold, italic, underline, color
ExcelAutoFilter AutoFilter operations and sorting
ExcelFilterColumn Filter column criteria
ExcelRichString Mixed-font text in a single cell
ExcelFormControl Form controls: checkboxes, dropdowns, spinners, buttons
ExcelConditionalFormat Conditional formatting style rules
ExcelConditionalFormatting Conditional formatting ranges and rule application
ExcelCoreProperties Workbook metadata: title, author, dates, categories
ExcelTable Structured table support (xlsx)

2.0 added six new classes (ExcelRichString, ExcelFormControl, ExcelConditionalFormat, ExcelConditionalFormatting, ExcelCoreProperties, ExcelTable) plus full arginfo coverage: 399 typed parameters and 277 typed return values across the surface.

php.ini settings

Store LibXL credentials in php.ini instead of source code. The extension reads them automatically when you pass null to the constructor.

[excel]
excel.license_name="YOUR_LICENSE_NAME"
excel.license_key="YOUR_LICENSE_KEY"
excel.skip_empty=0

🔗 Native PHP extensions

Companion native PHP extensions:

  • mdparser: native CommonMark + GFM markdown parser via md4c. 15-30× faster than pure-PHP libraries.
  • php_clickhouse: native ClickHouse client speaking the wire protocol directly. Picks up where SeasClick left off.
  • pdo_duckdb: PDO driver for DuckDB, analytical SQL in your PHP stack.
  • fastjson: drop-in faster ext/json, backed by yyjson. 6× encode, 2.7× decode, 5× validate.
  • phpser: decoder-optimized binary serializer for cache workloads. Faster than igbinary on packed numerics and DTO batches.
  • fast_uuid: high-throughput UUID generation (v1/v4/v7), batched CSPRNG and SIMD hex formatter, ramsey-compatible API.
  • fastchart: native chart-rendering extension. 38 chart types behind one fluent OO API, SVG-canonical with PNG/JPG/WebP and optional PDF output.
  • statgrab: system statistics (CPU, memory, disk, network) via libstatgrab, no parsing /proc by hand.
  • phonetic: native phonetic name matching (Double Metaphone, Beider-Morse, Daitch-Mokotoff, NYSIIS, Match Rating), the encoders PHP core lacks.

📚 Read more

The launch post covers background, design rationale, and benchmark methodology: php_excel 2.0: The C Extension for Excel That PHP Should Have Had All Along.

API reference lives in docs/; usage examples live in tests/.

License

PHP License 3.01. See LICENSE.

LibXL itself is commercial. See libxl.com for licensing.


Follow @iliaa on X • Blog • If this sped up your stack, ⭐ star it!

Projets similaires

🚀 PHP Extension for creating and reader XLSX files.

Cdllexcelexcel-export
Vviest
2,4 k étoiles237

A pure PHP library for reading and writing spreadsheet files

PHPexcelgnumerichacktoberfest
PPHPOffice
14 k étoiles3,6 k

🚀 Supercharged Excel exports and imports in Laravel

PHPcsvlaravellaravel-5-package
SSpartnerNL
12,7 k étoiles2 k