Features
- autoSize(?string $range = null) β sizes columns to fit their content. Column widths are estimated from the written cell values (wide/CJK code points count as two columns) and applied at output() time. Tracking is opt-in (call autoSize() before the writes it should size), so writes that never use it pay no per-cell cost; widths are clamped to Excel's 255 max. (#305 / #514)
Performance
- Worksheet metadata (merges, hyperlinks, protection, row/col options) is now loaded lazily instead of eagerly at openSheet(), so data-only reads (getSheetData / nextRow / nextCellCallback / putCSV) skip the second full XML pass β about 40% faster on large sheets.
- Merge-follow lookups (SKIP_MERGED_FOLLOW) are indexed by last_row with a forward cursor, turning the per-cell scan from O(cells Γ merges) into amortised near-O(1).
Fixes
- RichString leaked one zend_string per instance (the constructor's zend_string_copy was never released) and its fetch-object offset pointed at the wrong struct; both corrected.
- The cell/row-end/image/comment/chart callback bridges no longer zval_ptr_dtor an uninitialised return value when a callback throws or the call fails.
- xlsx_to_csv leaked its temp row on the write-failure path; openFile() now resets reader bookkeeping the way openSheet() and the dtor do; fileName()/constMemory() handle workbook/worksheet allocation failure instead of dereferencing NULL.
- The reader now reads every image from drawing.xml instead of stopping after the first 64 KB.
- PHP 8.6 compatibility β XtOffsetOf replaced with the standard offsetof, and zval_dtor with zval_ptr_dtor_nogc.
- setColumn()/setRow() leaked the per-call row/col options struct, and insertImage() leaked the path zend_string (#573).
Install: pecl install xlswriter or pie install viest/xlswriter (pulls the attached xlswriter-2.0.3.tgz).