xlswriter

Efficient and fast xlsx file extension.


xlswriter is a PHP C Extension that can be used to write text, numbers, formulas and hyperlinks to multiple worksheets in an Excel 2007+ XLSX file.

Writer

- 100% compatible Excel XLSX files.
- Full Excel formatting.
- Merged cells.
- Defined names.
- Autofilters.
- Charts.
- Data validation and drop down lists.
- Worksheet PNG/JPEG images.
- Memory optimization mode for writing large files.
- Works on Linux, FreeBSD, OpenBSD, OS X, Windows.
- Compiles for 32 and 64 bit.
- FreeBSD License.
- The only dependency is on zlib.

Reader

- Full read data
- Cursor read data
- Read by data type
- Xlsx to csv

License: BSD license

Latest releases

Version Release Download
2.0.2 2026-06-03 xlswriter-2.0.2.tgz
2.0.1 2026-05-25 xlswriter-2.0.1.tgz
2.0.0 2026-05-16 xlswriter-2.0.0.tgz
1.5.8 2024-11-10 xlswriter-1.5.8.tgz
1.5.7 2024-09-04 xlswriter-1.5.7.tgz
Show all releases

Changelog

Version Message
2.0.2 - Feature: insertImageOpt($row, $col, $path, $options) adds pixel-precise x_offset / y_offset within the anchor cell, scale via width/height, a "don't move or size with cells" anchor mode, plus mouseover tip, alt text (description / decorative) and a hyperlink overlay. Object positioning is exposed through new Excel::OBJECT_POSITION_* constants. The original insertImage() signature is untouched (#357 / #437 / #473 / #297 / #449).
- Feature: insertDynamicFormula() and insertDynamicArrayFormula() emit the t="array" + ref-range XML that Excel 365 dynamic array functions (UNIQUE, FILTER, SORT, SEQUENCE, XLOOKUP, etc.) require, which insertFormula() does not produce (#503).
- Feature: outlineSettings(bool $visible = true, bool $below = true, bool $right = true, bool $autoStyle = false) configures worksheet outline (grouping) display (#540).
- Fix: PHP true/false passed to writeSheet / data now writes a real boolean cell (xlsx type="b") via worksheet_write_boolean; previously bool fell through type_writer() silently and the cell was emitted as blank (#543).
2.0.1 - Fix: insertDate / insertText with $format string now caches each distinct format on its own cache slot; previously ZEND_STRL on a zend_string flexible-array key collapsed every format into one entry, so the first format won and every subsequent call returned the wrong cached format (#552 / #548 / #544).
- Fix: format_copy() now carries font_name (and font_scheme / has_font / has_dxf_font), so a Format resource passed alongside a num-format string keeps the caller's font() instead of falling back to Calibri (#545 / #472).
- Fix: data-validation inline list now rejects with an exception when the joined CSV exceeds Excel's 255-character spec limit, instead of overflowing libxlsxwriter's fixed-size buffer (#486 / #530 / #546).
- Fix: header() called after data() throws instead of silently overwriting the first data row (#535).
- Fix: empty-string sheet name is rejected up-front instead of producing an xlsx that Excel can't open (#528).
- Fix: outline-level warnings in setColumn / setRow / defaultRowOptions use %ld instead of %d so the build no longer fails on Alpine 3.22 + gcc 14 hardening defaults (#556).
- Build: tests + examples now parse on PHP 7.0 (the declared minimum); CI matrix expanded to PHP 7.0-7.3 on ubuntu-22.04 (#565).
- Build: composer.json declares download-url-method=pre-packaged-source so `pie install viest/xlswriter` fetches the self-contained xlswriter-(version).tgz attached to the GitHub release instead of the submodule-less packagist zipball.
2.0.0 - Refactor: replaced libxlsxio dependency with the in-tree libxlsxreader (PHP-agnostic C library, lives under library/libxlsxreader/).
- Reader: shared-strings table now supports both FULL and STREAMING modes; FSM-driven worksheet parser with 64KB XML buffer; honors 1900 vs 1904 date systems via workbook.xml.
- Reader: PHP API (openFile/openSheet/nextRow/nextCellCallback/getSheetData/setType/setGlobalType/setSkipRows/putCSV/putCSVCallback) is fully backward compatible.
- Reader: surface sheet-level metadata — getMergedCells, getHyperlinks, getSheetProtection, getRowOptions/getColumnOptions, getDefaultRowHeight/getDefaultColumnWidth, getDefinedNames, sheetListWithMeta.
- Reader: surface page setup, rich-text runs, comments, charts, and conditional formats — getPageSetup, nextRowRich, iterateImages, iterateComments, iterateCharts, getConditionalFormats.
- Reader: full formula attributes (next-row-with-formula), data validations (getDataValidations), autofilter (getAutoFilter); new static helper Excel::getFormulaAst() for tokenizing formulas without evaluation.
- Reader: getStyleFormat resolves a style id to a rich array of font/fill/border/alignment/protection.
- Writer: conditional formats (Vtiful\Kernel\ConditionalFormat + conditionalFormatCell/Range).
- Writer: Excel tables (Vtiful\Kernel\Table + addTable).
- Writer: page setup — setHeader/setFooter, repeatRows/repeatColumns, printArea, horizontalPageBreaks/verticalPageBreaks, fitToPages, setTabColor.
- Writer: workbook properties — setProperties, setCustomProperty.
- Writer: defined names — defineName (workbook- and sheet-scoped).
- Writer: insertCommentOpt, insertImageBuffer, setBackgroundImage/Buffer, insertRichText.
- Format: borderColorOfTheFourSides, borderOfTheFourSides, indent, rotation, locked/unlocked/hidden cell protection.
- Fix: setBackgroundImage / setBackgroundImageBuffer now bundle the referenced media inside the xlsx (the sheet's picture relationship pointed at a media file that was never written).
- Fix: setHeader/setFooter with image_left/image_center/image_right options now produces a valid xlsx (header VML drawing and content-type registration were missing, making the output unopenable).
- New constants: Excel::COMMENT_DISPLAY_DEFAULT / HIDDEN / VISIBLE so insertCommentOpt(['visible' => …]) callers don't have to guess libxlsxwriter's lxw_comment_display enum.
- Build: feature-flagged reader (--disable-reader produces a write-only build); minizip is shared between writer and reader.
- Update libxlsxwriter from 1.1.3 to 1.1.6.
1.5.8 - Fix: insertDate format.
- Feat: format rotation.
1.5.7 - Fix: insertDate memory leak.
Show complete changelog