Open-source project
viest/php-ext-xlswriter avatar
viest/php-ext-xlswriter

php-ext-xlswriter: an XLSX reader and writer built as a PHP extension

🚀 PHP Extension for creating and reader XLSX files.

2,371 stars237 forksCBSD-2-Clause

At a glance

What is it?
A C extension that writes and reads Excel 2007+ files without building a PHP object model, with two memory modes and a fixed-memory path that stays flat at scale.
Who is it for?
php-ext-xlswriter is the right pick when a PHP service has to emit a large workbook without the memory profile of a pure-PHP writer, and zlib is the only system dependency it asks for. It is the wrong pick when you need macros, pivot tables, or the parts of the Excel format that never appear in the feature list, because the project only implements the subset it lists.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 49 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why a C extension for spreadsheet output

The project exists because of a specific problem: writing an Excel file from PHP normally means building an object model in memory, serializing it at the end, and watching the process grow until the export dies. The repository description says it plainly, in slightly broken English, as a tool for creating and reading XLSX files. The README argues the case with a chart comparing against PhpSpreadsheet, which it names as the maintained successor to PHPExcel, scaled to Excel's own row limit of 1,048,576 rows.

The tree explains the shape of the work. There is a single entry point, `xlswriter.c`, with `php_xlswriter.h` beside it, then `kernel/`, `library/` and `include/` for the actual implementation. Build glue sits alongside it in `config.m4` for Unix autoconf and `config.w32` for Windows, which is the pairing you expect from a project that ships prebuilt DLLs as well as source. `bench/` holds the benchmark harness, `backup/` holds legacy sources, and `examples/` holds twelve numbered scripts.

Two things are worth noticing about the packaging. The project is on PECL as `xlswriter`, and it also works with PIE, the newer PHP installer. Topics on the repository name both, along with `swoole` and `phalcon`, which tells you the intended audience is people running PHP in long-lived worker processes rather than people writing one-shot CLI scripts.

Installing on Unix and Windows

Both Unix install paths build from source, so the zlib development headers have to be there first. The README is explicit that minimal container images often ship without them:

bash
apt-get install -y zlib1g-dev

The other package managers are one line each, `apk add zlib-dev` for Alpine and `yum install -y zlib-devel` for RHEL and its descendants. Once the headers exist, PECL is the shorter route:

bash
pecl install xlswriter

PIE needs the autotools chain on top of that, and can install the missing pieces for you except zlib:

bash
pie install --auto-install-build-tools viest/xlswriter

On Windows there is no build step at all. The README points at the releases page for a prebuilt DLL, which is the reason `config.w32` exists in the tree.

There is also a separate companion package for IDE autocompletion, installed through Composer:

bash
composer require viest/php-ext-xlswriter-ide-helper:dev-master

That one is documentation rather than functionality, but it is worth installing if you write PHP against this extension, because the type signatures come from it. The project claims its only dependency is zlib, and nothing in the install path above contradicts that.

Two memory modes and what each one costs

The library has two writing modes and the README is candid about the trade-off, which is unusual. Fixed-memory mode streams each row to disk and frees it immediately. Normal mode keeps the entire workbook in memory, which is what lets you write cells in any order and restyle them before saving. The consequence of that choice is spelled out: fixed-memory mode cannot revisit a cell once written, and its strings are stored inline rather than de-duplicated, so the file can come out slightly larger.

The benchmark section gives concrete numbers on a MacBook Pro 13 inch with an Intel Core i5, 16 GB of 2133 MHz LPDDR3 and a 128 GB SSD, exporting one million rows of string data across 27 columns. Normal mode took 29 seconds and 2083 MB. Fixed-memory mode took 52 seconds and less than 1 MB. On import, one million rows of a single integer column took 3 seconds and 558 MB in full mode, and 2.8 seconds and under 1 MB in cursor mode.

Those figures sit oddly next to the comparison chart near the top of the README, which claims xlswriter holds peak memory flat at roughly 30 MB no matter how many rows you write, while a pure-PHP library needs about 7 GB for the same file. Both statements are in the same document. The chart measures ten columns and the benchmark measures 27, and the chart is describing fixed-memory mode while the 2083 MB figure is normal mode, so the two are not strictly contradicting each other. If your export has many wide columns, treat the 30 MB number as the optimistic case rather than a promise.

Reading workbooks back, including cursor streaming

Writing is only half of it. The README lists a full read mode and a cursor read mode, plus the ability to read by data type, cell styles and number formats, merged cells, images, charts and comments. Formulas come back together with their cached values, which matters when you are parsing files produced by Excel rather than by this library.

The `examples/` directory shows how this is meant to be used. `02_read_full.php` and `03_read_streaming.php` are separate scripts, so cursor reading is treated as a first-class path rather than a flag on the same function. `09_images_roundtrip.php` suggests the round-trip claim is exercised rather than aspirational, and `11_read_styles.php` shows style reading as its own example.

The topic list includes `xlsxreader` and `xlsxwriter` as separate entries, but both live in the same extension. If your use case is parsing uploaded spreadsheets rather than generating them, the memory numbers above are the reason to look here: cursor mode read a million rows in 2.8 seconds under 1 MB, which is a very different profile from loading a workbook into a PHP array.

External documentation sits at xlswriter-docs.viest.me, and the README calls it extensive. The README itself does not show a single PHP snippet, which is the main gap to be aware of: the method names in the release notes are the fastest route to the actual API surface.

Version 3 added formula evaluation and round-trip editing

The v3.0.0 release, published on 2026-07-05, is the one that changed the scope of the library. Two features stand out.

The first is formula calculation. `evaluateFormula(string $formula)` takes an Excel formula and returns its result. The release notes describe the coverage: operator precedence and arithmetic, cell and range references such as `A1` and `A1:A3` resolved against values already written, the aggregates SUM, AVERAGE, MIN, MAX, COUNT and COUNTA, and logical and text functions including IF, CONCATENATE, UPPER and LEN. Excel error values like `#DIV/0!` and `#NUM!` surface as strings rather than throwing. There is a companion opt-in, `computeFormula(bool $enable = true)`, which makes `insertFormula()` write the cached result into the file so other readers see a value without recalculating.

The second is round-trip editing. `openFile()` loads a saved `.xlsx` and lets you change cell values, styles, merged ranges, dates and sheet dimensions in place, add worksheets, insert images and charts, then call `output()`. Notably, the existing write methods keep working unchanged in edit mode, and the release notes say unsupported edit operations are now reported instead of being silently dropped. That last detail matters more than it sounds, because silent drops in a spreadsheet library are how you lose formatting.

The v2.0.3 release from 2026-06-14 added `autoSize(?string $range = null)`, which estimates column widths from written values, counts wide and CJK code points as two columns, applies the widths at output time, and clamps to Excel's maximum of 255. It is opt-in, so writes that never call it pay no per-cell cost.

Where the README and the repository disagree

There are a few places where the README and the repository metadata tell different stories, and in each case the practical advice is the same: check the file, not the prose.

The feature list says the library is under the FreeBSD License. GitHub reports BSD-2-Clause for the repository, and there is a `LICENSE` file in the tree. Those two are close relatives and both are permissive, but if you are shipping this in a product, read the `LICENSE` file rather than the feature bullet.

Several badges still point at an older repository name. The release badge, the contributors badge and the issues badge all reference `viest/php-ext-excel-export` while the project now lives at `viest/php-ext-xlswriter`. That is why the issue count the badges show may not match the repository you are looking at. It is a cosmetic leftover, but it is a useful signal that the badges were copied forward rather than regenerated.

The topics list both `pie` and `pecl` and both `xlsxwriter` and `xlswriter`, which is helpful for discovery and slightly confusing for reading, since only one extension exists. The repository is not archived and the last push was on 2026-08-24, with v3.0.0 released in July, so this is an actively worked-on version line.

Editorial conclusion

php-ext-xlswriter is the right pick when a PHP service has to emit a large workbook without the memory profile of a pure-PHP writer, and zlib is the only system dependency it asks for. It is the wrong pick when you need macros, pivot tables, or the parts of the Excel format that never appear in the feature list, because the project only implements the subset it lists. Two things are worth checking before you commit: whether your build environment can supply the zlib headers and a compiler, and whether the ~30 MB claim in the comparison chart matters to you as much as the 2083 MB the benchmark section reports for normal mode. Start with the pecl install on a scratch machine, write one file with the constant-memory option on, and watch your own peak RSS before you point it at a real report.

Frequently asked questions

Is there a library for Excel in PHP?

There are several, and they fall into two groups. Pure-PHP libraries such as PhpSpreadsheet give you the widest feature coverage and load the whole workbook into memory. Extensions such as php-ext-xlswriter write the file from C instead, which is the difference between a flat memory profile and one that grows with row count.

How can I export PHP data to an Excel file?

Install the extension, then build a workbook from your data and hand it to the output call. The `examples/` directory in the repository starts at `01_basic_write.php`, and `04_const_memory.php` shows the streaming variant for large exports. Full method signatures are in the IDE helper package rather than the README.

Does php-ext-xlswriter support reading as well as writing?

Yes, and it has two read modes. Full mode reads a whole workbook at once, cursor mode streams it row by row with flat memory use. The reader can return values by data type, styles and number formats, merged cells, images, charts and comments, plus formulas with their cached results.

Official sources

  1. License: BSD-2-Clause
  2. Project website
  3. README
  4. Releases
  5. viest/php-ext-xlswriter on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/viest-php-ext-xlswriter.svg)](https://hysenlabs.com/projects/viest-php-ext-xlswriter)