HotXLS releaseopmerkingen
Versiegeschiedenis voor zichtbare HotXLS-functies, herstelt, XLS/XLSX-verbeteringen, exportupdates, compatibiliteitswijzigingen en documentatie-updates.
[Unreleased]
Versie 2.88.111
- Classic XLS-werkbladen ondersteunen nu zelfstandige tekenlaag-TextBoxen. Gebruik
TXLSShapes.AddTextBoxom eenTXLSTextBoxte maken met een eigen rij-/kolomanker, tekst, text runs, lijn-/vulopmaak en normale shape-verwijdering zonder een celopmerking te maken.
Versie 2.88.110
- De ApiTour-demo's behandelen nu meer workbook-automatiseringspatronen. De Delphi- en C++Builder-ApiTour-voorbeelden tonen callback-gebaseerd bereikschrijven met
WriteCells, het scannen van geladen cellen metForEachCell, template-updates metFindTextenReplaceText, HTML-export van een geselecteerd bereik naarApiTour-Range.htmlen Delphi-callbacks voor aangepaste formules viaOnUserFunction.
Versie 2.88.109
- De QuickStart-demos tonen nu een completere eerste werkmap. De Delphi- en C++Builder-QuickStart-voorbeelden maken een opgemaakte vermenigvuldigingstabel met rij- en kolomtotaalformules, bevroren vensters en overeenkomende XLS/XLSX-acties; de demomap bevat nu ook verzorgde HTML-readme-paginas voor elk voorbeeld.
Versie 2.88.108
- XLSX bereiken hebben nu directe HTML-exporthulpen.
TXLSXRange.SaveAsHTML(FileName)andTXLSXRange.SaveAsHTML(Stream)export only the geselecteerde XLSX bereik as a UTF-8 HTML tabel, sharing the werkmap HTML renderer's escaping, basic stijl output, and merged-cel span handling.
Versie 2.88.107
- XLSX werkbladen now include hulpen voor tekst zoeken en vervangen.
TXLSXWorksheet.FindTextandTXLSXWorksheet.ReplaceTextscan geladen text cellen in row-major order, skip formules and non-text values, and ondersteuning optional case-sensitive matching for template workflows.
Versie 2.88.106
- BIFF8 Window2 weergavevlaggen behoudt nu aangepaste rasterlijn and bevroren-vensterstatus. HotXLS now clears
fDefaultHdrwhenWindow2.icvHdrstores a aangepaste rasterlijn color, behoudt Excel-authoredfFrozenNoSplitduring openen/opslaan, and schrijftfFrozenNoSplitforFreezePanesoutput.
Versie 2.88.105
- CF12 formuledrempels now rondreis through BIFF8 Data Bar, Color Scale, and Icon Set rules. formule-based threshold values compile to CF12 formule token bytes on opslaan and are restored to
TXLSCfValue.Valuewhen a werkmap is reopened.
Versie 2.88.104
- Classic XLS formules and icon-set thresholds now emit tighter BIFF8 records. Integer constants in formules use the compact
tInttoken when they fit the BIFF unsigned-integer bereik, andTXLSIconSetSpec.ThresholdEqualsInclude[Index]now controls the CF12 icon-set threshold equals byte so callers can choose include or exclude comparison semantics.
Versie 2.88.103
- Classic XLS werkbladen now include a text find hulp.
IXLSWorksheet.FindText(SearchText, Row, Col[, MatchCase])locates the first matching geladen text cel, skips formules and non-text cellen, and clears the returned coordinates when no match is found.
Versie 2.88.102
- Classic XLS werkbladen now include a text replacement hulp.
IXLSWorksheet.ReplaceText(SearchText, ReplacementText[, MatchCase])replaces matches in geladen text cellen, skips formules and non-text cellen, and reports the changed cel count for template-filling workflows.
Versie 2.88.101
- bereiken hebben nu directe HTML-exporthulpen.
IXLSRange.SaveAsHTML(FileName)andIXLSRange.SaveAsHTML(Stream)export the geselecteerde bereik through the existing HTML renderer, so callers no longer need to create aTXLSHTMLExportinstance or passxlHTMLexplicitly for common bereik fragments.
Versie 2.88.100
TXLSWorkbook.GetSheetNames(Stream, AList)now leest XLSX package streams as well as classic XLS streams. Applications can pass memory streams, database BLOB streams, or downloaded XLSX streams to the classic facade and receive ordered werkblad names without first saving to a file.
Versie 2.88.99
- werkblad lookup, hyperlink creation, and multi-area selection APIs are now easier to use. Classic XLS and XLSX sheet collections add
TryGetSheetByName, classic XLS werkbladen addAddHyperlinkconvenience overloads, andIXLSWorksheet.SelectAreascan schrijven active multi-bereik selections.
Versie 2.88.98
- Classic XLS werkmappen now expose a
UserNamealias for the saved-by field.IXLSWorkbook.UserNamemaps to the same WRITEACCESS value asLastSavedBy, so code that uses theUserNamenaming convention can lezen and update the werkmap audit name directly.
Versie 2.88.97
- XLSX werkbladen now share the callback cel scan and bereik schrijven hulpen.
TXLSXWorksheet.ForEachCellenumerates geladen cellen in row order with value and formule text, whileTXLSXWorksheet.WriteCellsfills numeric or A1-stijl bereiken from a callback with per-cel skip and cancellation.
Versie 2.88.96
- Classic XLS werkbladen now ondersteuning callback-driven bereik writing.
IXLSWorksheet.WriteCellsfills a 1-based numeric bereik or A1-stijl bereik in row order, lets the callback provide each cel value, ondersteunt per-cel skip, and can cancel long schrijven loops early.
Versie 2.88.95
- Classic XLS werkbladen kan nu enumerate geladen cellen through a callback.
IXLSWorksheet.ForEachCellwalks existing werkblad cellen in row order, passes 1-based sheet, row, and column coordinates with value and formule text, and lets the callback cancel long scans early.
Versie 2.88.94
- formule calculation kan nu call application-defined functions.
TXLSWorkbook.OnUserFunctionandTXLSXWorkbook.OnUserFunctionletCalculatedelegate aangepaste or unsupported werkblad functions to application code, passing evaluated arguments and using the returnedVariantresult when handled.
Versie 2.88.93
- Classic XLS werkblad protection now exposes per-action permission flags.
IXLSWorksheetvoegt toeAllowDeleteRows,AllowInsertRows,AllowFormatCells,AllowSort,AllowAutoFilter, and the remaining SheetProtect permission eigenschappen, with BIFF8 options written and lezen back through the existing protection records.
Versie 2.88.92
- Classic XLS VBA payloads hebben nu explicit load/opslaan/clear hulpen.
IXLSWorkbook.LoadVBAProjectFromFile,SaveVBAProjectToFile,HasVBAProject, andClearVBAProjectexpose the preserved OLE VBA storage payload whileVBAProjectremains the parsed lezen-only module view.
Versie 2.88.91
- Classic XLS AutoFilter criteria kan nu be inspected through a field collection.
IXLSWorksheet.AutoFilterColumnsexposes the current BIFF8 AutoFilter field count and 1-based field items, including active state, operator, and storedCriteria1/Criteria2DOPER values.
Versie 2.88.90
- Classic XLS werkbladen hebben nu one-call AutoFilter criteria setup.
IXLSWorksheet.ApplyAutoFiltersets a werkblad AutoFilter bereik and schrijft a field criterion in the same call, with A1-stijl and 1-based numeric bereik overloads plus optional two-criterion operators.
Versie 2.88.89
- Classic XLS shapes kan nu be removed by cel bereik.
TXLSShapes.DeleteInRangedeletes anchored pictures or shapes whose OfficeArt client anchors intersect a 1-based werkblad bereik, returning the number of shapes removed.
Versie 2.88.88
- Classic HTML export tabel layout attributes are now configurable.
TXLSHTMLExport.TableBorderWidth,CellPadding, andCellSpacingcontrol the generated<table>attributes for both styled and simple HTML output while defaulting to the previous zero values.
Versie 2.88.87
- Classic HTML export ondersteunt nu minimal tabel output.
TXLSHTMLExport.SimpleExportschrijft a plain HTML tabel without generated CSS classes, hyperlink anchors, or comment title attributes while preserving escaped display text and merged-cel spans.
Versie 2.88.86
- Classic HTML export kan nu schrijven a document title.
TXLSHTMLExport.Titleschrijft an escaped HTML<title>element before the generated stijl block, while the default empty value keeps existing output unchanged.
Versie 2.88.85
- Classic HTML export now carries cel comments as tooltips.
TXLSHTMLExport.Optionsbevat nuxhCommentsby default, writing cel comment text as escapedtitleattributes while still allowing callers to remove the option for plain cel output.
Versie 2.88.84
- Classic HTML export hyperlink output is now configurable.
TXLSHTMLExport.Optionsdefaults to[xhHyperlinks]for existing behavior, and callers can removexhHyperlinksto export linked cellen as plain escaped text.
Versie 2.88.83
- Classic HTML export behoudt nu cel hyperlinks.
SaveAsHTMLwraps linked cellen in HTML anchor tags, emits hyperlink addresses as escapedhrefvalues, carries ScreenTip text as escapedtitleattributes, and keeps the displayed cel text escaped inside the link.
Versie 2.88.82
- Classic XLS werkmappen kan nu control the saved-by user name.
IXLSWorkbook.LastSavedByexposes the WRITEACCESS saved-by field so generated or edited werkmappen can store an explicit audit name while unedited source werkmappen continue preserving their original metadata.
Versie 2.88.81
- Classic XLS werkbladen kan nu control the displayed gridline color index.
IXLSWorksheet.GridlineColorIndexexposes the Window2icvHdrfield so saved werkbladen can reopen with a chosen gridline color while leaving gridline visibility and print gridline settings unchanged.
Versie 2.88.80
- Classic XLS werkmappen kan nu set the active sheet by index.
IXLSWorkbook.ActiveSheetIndexexposes a 1-based active-tab eigenschap backed by the WINDOW1 active sheet field, allowing saved werkmappen to reopen on a chosen werkblad without changing the first visible tab.
Versie 2.88.79
- Classic XLS werkblad outlines kan nu control automatic outline stijlen.
TXLSOutline.ApplyStylesexposes the WSBool outline stijl flag, allowing saved werkbladen to behouden or explicitly enable Excel outline stijl application without changing outline levels or summary placement.
Versie 2.88.78
- Classic XLS page setup kan nu control automatic page breaks.
IXLSPageSetup.AutoPageBreaksexposes the werkblad WSBool automatic page-break flag, allowing saved werkbladen to keep automatic page breaks enabled or disable them explicitly while preserving manual page breaks.
Versie 2.88.77
- Classic XLS werkmappen kan nu control AutoFilter date grouping.
IXLSWorkbook.AutoFilterDateGroupingexposes the Window1 date-grouping flag with a positive Boolean API, allowing saved werkmappen to keep Excel's date filter grouping enabled or disable it explicitly.
Versie 2.88.76
- Classic XLS werkmappen kan nu set werkmap window position and size directly.
IXLSWorkbook.XWindow,YWindow,WindowWidth, andWindowHeightexpose the Window1 geometry fields so saved werkmappen can reopen with a chosen window rectangle.
Versie 2.88.75
- Classic XLS werkmappen kan nu opslaan the werkmap window hidden state directly.
IXLSWorkbook.WindowHiddenmaps to the Window1 hidden flag, allowing saved werkmappen to reopen with the werkmap window hidden without changing werkblad visibility.
Versie 2.88.74
- Classic XLS werkmappen kan nu opslaan the werkmap window minimized state directly.
IXLSWorkbook.Minimizedmaps to the Window1 minimized flag, allowing saved werkmappen to reopen with the werkmap window minimized.
Versie 2.88.73
- Classic XLS werkmappen kan nu hide or show the vertical scrollbar directly.
IXLSWorkbook.ShowVerticalScrollmaps to the Window1fDspVScrollflag, allowing saved werkmappen to openen with the vertical scrollbar hidden or visible.
Versie 2.88.72
- Classic XLS werkmappen kan nu hide or show the horizontal scrollbar directly.
IXLSWorkbook.ShowHorizontalScrollmaps to the Window1fDspHScrollflag, allowing saved werkmappen to openen with the horizontal scrollbar hidden or visible.
Versie 2.88.71
- Classic XLS werkmappen kan nu hide or show the sheet tab bar directly.
IXLSWorkbook.ShowSheetTabsmaps to the Window1fDspTabsflag, letting saved werkmappen openen with sheet tabs hidden or visible without changing werkblad visibility.
Versie 2.88.70
- Classic XLS werkmappen kan nu set the werkmap tab bar ratio directly.
IXLSWorkbook.TabRatioexposes the Window1wTabRatiovalue so callers can adjust the space reserved for sheet tabs versus the horizontal scrollbar.
Versie 2.88.69
- Classic XLS werkmappen kan nu set the first visible sheet tab directly.
IXLSWorkbook.FirstSheetexposes the Window1itabFirstvalue as a 1-based eigenschap, so callers can choose which sheet tab appears at the left edge when Excel opens the werkmap.
Versie 2.88.68
- Classic XLS werkbladen can behoudt nu and set outline symbol visibility.
IXLSWorksheet.DisplayOutlineSymbolsmaps to the BIFF WINDOW2fDspGutsflag, allowing saved sheets to hide outline and grouping symbols in the window view.
Versie 2.88.67
- Classic XLS werkbladen can behoudt nu and set row and column heading visibility.
IXLSWorksheet.DisplayHeadingsmaps to the BIFF WINDOW2fDspRwColflag, allowing saved sheets to hide row numbers and column letters in the window view.
Versie 2.88.66
- Classic XLS werkbladen can behoudt nu and set the show-formules view.
IXLSWorksheet.DisplayFormulasmaps to the BIFF WINDOW2fDspFmlaflag so Excel can openen a sheet showing formule text instead of calculated results.
Versie 2.88.65
- Classic XLS werkbladen kan nu set Normal view zoom independently.
IXLSWorksheet.NormalViewZoomexposes the cached WINDOW2 Normal zoom so callers can opslaan distinct zoom levels while a sheet is in Page Break Preview.
Versie 2.88.64
- Classic XLS werkbladen kan nu set Page Break Preview zoom directly.
IXLSWorksheet.PageBreakPreviewZoomexposes the cached WINDOW2 preview zoom so callers can opslaan different Normal and Page Break Preview zoom levels.
Versie 2.88.63
- Classic XLS werkbladen now expose split-pane hulpen.
IXLSWorksheet.SplitPanes(Width, Height)creates a movable pane split using the existing BIFF pane writer, andUnsplitPanesclears the pane record before saving.
Versie 2.88.62
- Classic XLS werkbladen hebben nu simpler frozen-pane hulpen.
IXLSWorksheet.FreezePanes(Cols, Rows)freezes the requested left columns and top rows, whileUnfreezePanesremoves the pane record before saving.
Versie 2.88.61
- Classic XLS sheet-name discovery now accepts streams.
TXLSWorkbook.GetSheetNames(Stream, List)leest BIFF sheet names from a caller-provided XLS stream without loading werkblad contents, matching the file-name hulp for in-memory werkmap data.
Versie 2.88.60
- werkblad collections now expose direct by-name lookup hulpen.
IXLSWorkSheets.SheetByName(Name)andTXLSXSheets.SheetByName(Name)return the matching werkblad object ornil, so callers no longer need to resolve an index before accessing a sheet.
Versie 2.88.59
- The XLSX facade now leest sheet names directly from streams.
TXLSXWorkbook.GetSheetNames(Stream, List)leest ordered names fromxl/workbook.xmlwithout loading werkblad XML, matching the file-name overload for in-memory and BLOB-backed werkmappen.
Versie 2.88.58
- The XLSX facade now exposes quick sheet-name discovery.
TXLSXWorkbook.GetSheetNames(FileName, List)leest ordered names fromxl/workbook.xmlwithout loading werkblad XML.
Versie 2.88.57
TXLSWorkbook.GetSheetNamesondersteunt nu XLSX packages. The methode leestxl/workbook.xmlfrom.xlsx,.xlsm,.xltx, and.xltmfiles and returns ordered sheet names without loading werkblad XML.
Versie 2.88.56
- Classic XLS werkmappen kan nu lezen sheet names without loading werkbladen.
TXLSWorkbook.GetSheetNames(FileName, List)scans the werkmap globals stream and returns ordered sheet names from Excel 97-2003.xlsfiles.
Versie 2.88.55
- Classic XLS bereik AutoFilter criteria now schrijven BIFF8 filter records.
TXLSRange.Autofilter(Field, Criteria)creates the filter bereik when needed and emitsAUTOFILTERconditions for simple string, numeric, Boolean, blank, nonblank, and comparison-prefixed criteria.
Versie 2.88.54
- Classic XLS werkbladen hebben nu werkblad-level AutoFilter hulpen.
IXLSWorksheet.SetAutoFilter,ClearAutoFilter, andAutoFilterRangemanage BIFF8 filter dropdown bereiken directly while reusing the existingAUTOFILTERINFOand filter database name writer.
Versie 2.88.53
- Classic XLS werkbladen now expose list data-validation creation.
IXLSWorksheet.AddListValidation(Range, Items)schrijft BIFF8DVALandDVrecords, keeps the dropdown visible by default, ondersteunt comma-separated inline lists, and behoudt the rules throughOpen/SaveAsround-trips.
Versie 2.88.52
- formule calculation now works consistently across XLS and XLSX entry points.
TXLSWorkbook.Calculatenow accepts Excel-stijl leading-equals formules such as=SUM(A1:B1)+C1, and the XLSX facade voegt toeTXLSXWorkbook.CalculateplusTXLSXWorksheet.Calculate. The XLSX path shares the HotXLS formule token parser and evaluator for cel and bereik references, referenced formule cellen, cross-sheet references, and werkmap or sheet scoped defined-name bereiken.
Versie 2.88.51
- XLSX bereiken now ondersteuning Excel-stijl merge across.
TXLSXRange.Merge(True)schrijft one<mergeCell>entry per row, matching the classic XLSRange.Merge(True)behavior, while no-argumentMergeandMerge(False)continue to create one full-bereik merged rectangle.
Versie 2.88.50
- BIFF8 HeaderFooter and HFPicture placement now match the current MS-XLS rules. HotXLS behoudt Excel-authored
HeaderFooter($089C) records for even / first page header and footer text, and replaysHFPicture($0866) records after werkblad dimensions and drawing objects per the werkblad ABNF, so page-layout details survive .xls openen/opslaan round-trips.
Versie 2.88.49
- Comment rich-text runs hebben nu a typed API.
TXLSComment.TextRunsexposes BIFF8TXOFormatRunentries so callers can inspect or set per-character font boundaries in .xls comments while HotXLS still behoudt the underlying run bytes for safe round-trips.
Versie 2.88.48
- Pivot-tabel supplemental SX records are now exposed through the typed API. HotXLS now attaches geladen BIFF8 pivot records such as
SXIVD,SXLI,SXFormat,SXEx,SXVDEx,SXRule,SXFilt, andSXAddltoTXLSPivotTable.SupplementalRecordsfor inspection while still preserving the original raw bytes for opslaan round-trips.
Versie 2.88.47
- External werkmap cached values now survive .xls openen/opslaan round-trips. HotXLS behoudt nu BIFF8
XCTandCRNrecords attached to geladenSUPBOOKentries, so cached cel values for external werkmap links are no longer dropped during opslaan.
Versie 2.88.46
- Built-in stijl outline levels now survive .xls openen/opslaan round-trips. HotXLS now leest and behoudt the BIFF8
STYLEiLevelbyte for built-in stijlen, so Excel RowLevel_1..7 and ColLevel_1..7 stijl metadata is no longer reset to the default during opslaan.
Versie 2.88.45
- Defined name metadata now survives .xls openen/opslaan round-trips. HotXLS behoudt nu geladen BIFF8
NAMErecord option bits and shortcut bytes unless the defined name is edited, so Excel-authored function, object, procedure, calculated-expression, and binary-name metadata is no longer cleared during opslaan.
Versie 2.88.44
- ObProj werkmap markers now survive .xls openen/opslaan round-trips. HotXLS behoudt nu geladen BIFF8
ObProjrecords even when no VBA storage is exposed through the object model, so werkmap-level VBA project markers and third-party metadata are no longer dropped during opslaan.
Versie 2.88.43
- werkblad option flags now survive .xls openen/opslaan round-trips. HotXLS behoudt nu unmodeled BIFF8
WSBOOLbits such as dialog-sheet, automatic page-break, stijl-application, and outline-gutter display flags while still updating the existing fit-to-page and outline summary settings through the public API.
Versie 2.88.42
- Additional werkmap metadata records now survive .xls openen/opslaan round-trips. HotXLS behoudt nu geladen BIFF8
COUNTRY,BOOKBOOL,BACKUP,FNGROUPCOUNT,USESELFS, andRECALCIDrecord bodies instead of rewriting them with defaults, keeping werkmap-level compatibiliteit and calculation metadata stable.
Versie 2.88.41
- Multi-area selections and active pane focus now survive .xls openen/opslaan round-trips. HotXLS behoudt nu geladen BIFF8
SELECTIONrecords and thePANESactive-pane value unless the sheet selection or panes are changed through the API, so Excel split/frozen pane focus and multi-bereik selections are no longer collapsed during opslaan.
Versie 2.88.40
- External werkmap names now survive .xls openen/opslaan round-trips. HotXLS behoudt nu geladen BIFF8
EXTERNALNAMErecords attached to externalSUPBOOKentries, including DDE/OLE/link metadata and formule tails, so external names and link definitions are no longer dropped when saving.
Versie 2.88.39
- Password-protected BIFF8 .xls files now use and lezen RC4 CryptoAPI FILEPASS records. HotXLS now schrijft Excel 2007/2010-stijl
FILEPASSvMajor=2 metadata for encrypted .xls werkmappen and leest both legacy RC4 vMajor=1 and RC4 CryptoAPI vMajor=2/3/4 files, so password-protected werkmappen no longer fail or downgrade to the older encryption header.
Versie 2.88.38
- Excel-authored .xls hyperlink metadata now survives openen/opslaan round-trips. HotXLS behoudt nu the BIFF8
HLinkrecord body for geladen hyperlinks unless the hyperlink is edited, keeping sourcestreamVersion,hlstmfoption bits such asfIcon, moniker data, and related target metadata stable across saves.
Versie 2.88.37
- werkmap window state now survives .xls openen/opslaan round-trips. HotXLS now leest and behoudt the BIFF8
WINDOW1record's window position, size, visibility/iconic flags, first displayed sheet tab, geselecteerde-tab count, and tab-scrollbar ratio instead of rewriting them with defaults on every opslaan.
Versie 2.88.36
- BIFF8 WriteAccess saved-by users now survive .xls openen/opslaan round-trips. HotXLS now leest and behoudt the
$005C WRITEACCESSrecord body instead of replacing Excel's saved-by user withHotXLS, so werkmap audit metadata remains stable after saving.
Versie 2.88.35
- Excel comment authors now survive .xls openen/opslaan round-trips. The BIFF8
Noterecord'sstAuthorfield is now parsed and passed into the drawing note model instead of being replaced with an empty string, so the comment "Created by" author written by Excel is preserved when HotXLS saves the werkmap again.
Versie 2.88.34
- Shape OfficeArt FOPT options are now exposed through a low-level option bag.
TXLSShape.OfficeArtOptionslets advanced callers inspect, set, and delete any stored FOPT PID as aLongWordorWideString, while the existing high-levelLine,Fill, color, and visibility APIs remain unchanged.
Versie 2.88.33
- Additional OfficeArt solver-container rule records now rondreis. Beyond typed
msofbtConnectorRule($F012), HotXLS behoudt nu non-folder solver children such asOfficeArtFArcRule($F014) andOfficeArtFCalloutRule($F017) as raw OfficeArt records insidemsofbtSolverContainer($F005), so advanced Excel drawings no longer lose non-connector solver relationships during opslaan.
Versie 2.88.32
- OfficeArt ClientData markers are no longer duplicated after unknown-record preservation. MS-XLS defines
OfficeArtClientData($F011) as a zero-length marker whose followingObjrecord remains a separate BIFF record. v2.88.32 recognises that marker instead of capturing it as an unknown SpContainer leaf, so parsed shapes emit exactly one $F011 marker during opslaan while malformed container-stijl assumptions remain out of the XLS path.
Versie 2.88.31
- OfficeArt connector rules now rondreis. Excel-authored .xls drawings store connector-line bindings in
msofbtSolverContainer($F005) with childmsofbtConnectorRule($F012) records. v2.88.31 parses and emits that $F005/$F012 pair throughTMsoConnectorRules, preserving the start shape, end shape, connector shape, and connection sites across opslaan/reload. The earlier audit note listed $F121, but MS-ODRAW definesOfficeArtFConnectorRuleas $F012.
Versie 2.88.30
- Unrecognised OfficeArt SpContainer leaf records now rondreis. Excel-authored .xls files commonly embed leaf Fbts such as
msofbtClientTextbox($F00D),OfficeArtFPSPL($F11D), andOfficeArtUDefProp($F122) inside each shape SpContainer. v2.88.30 captures unknown shape-level leaves asTMsoFbtUnknownand re-emits them in parse order between the shapeClientAnchorand the trailing zero-bodymsofbtClientDatamarker. - Scope and follow-up. Other drawing-level unknown leaves remain deferred; the connector-rule solver-container case is handled by v2.88.31. Container-form unknowns, such as
msofbtClientData($F011) used as a container instead of a sibling marker, remain audit-round Slice 3.
Versie 2.88.29
- ComboBox and ListBox OBJ unknown subrecords now rondreis. TMSOShapeComboBox.ParseObj and TMSOShapeListBox.ParseObj already typed-parsed FtSbs ($000C), FtSbsFmla ($000E), and FtLbsData ($0013) into dedicated fields, but any other source-file subrecord (FtMacro $0004, ObjLinkFmla, FtNts $000D, etc.) appearing between CMO and FtLbsData was silently dropped at case fall-through. v2.88.29 voegt toe the same else-branch as v2.88.28 Picture, capturing the unknown subrecord's 4-byte header + body into
FObjTailRaw. Both AddObj methoden emit the captured bytes between the CMO body and the FtSbs subrecord to match the BIFF8 spec's subrecord ordering. - FtLbsData's swallow-all behaviour limits the scope. The existing
$0013case overridesRecLen := Len - offsto absorb all bytes after the FtLbsData header intoFObjRec_LBSData's blob, so subrecords appearing AFTER FtLbsData (typically just FtEnd) are still round-tripped through that mechanism unchanged. The new FObjTailRaw integration specifically targets the gap before FtLbsData where FtMacro and ObjLinkFmla typically live. Freshly authored combo / list boxes via the Drawing API have emptyFObjTailRaw→ byte-identical output to v2.88.28.
Versie 2.88.28
- Picture-shape OBJ unknown subrecords now rondreis. TMSOShapePicture.ParseObj already typed-parsed FtCf ($0007), FtPioGrbit ($0008), and FtPictFmla ($0009) into dedicated fields, but any other source-file subrecord (FtMacro $0004, FtNts $000D, etc.) was silently dropped at the case fall-through. v2.88.28 voegt toe an else-branch that appends the full 4-byte header + body of unrecognised subrecords into
FObjTailRaw; TMSOShapePicture.AddObj then emits those bytes verbatim after its typed subrecord output and before the FtEnd marker. Source-file picture objects with macro hooks survive the resave. - typed + raw coexistence pattern. Unlike PictureFrame (v2.88.27) which used an if/else swap between typed and raw emit, Picture combines both: the typed fields behouden the API surface (callers can still adjust
ftCfValueetc.), while the raw tail behoudt only the unknown bytes. Newly authored pictures via the Drawing API have emptyFObjTailRaw, so output is byte-identical to v2.88.27.
Versie 2.88.27
- OBJ trailing-subrecord rondreis extended to PictureFrame shapes. TMSOShapePictureFrame.AddObj previously emitted only the legacy hardcoded FtCf ($0007, body $FFFF) and FtPioGrbit ($0008, body $0000) subrecords between CMO and FtEnd. For freshly authored picture frames the new code still emits those defaults; for picture frames parsed from a source .xls the captured
FObjTailRawbytes are emitted verbatim instead, preserving any source-file FtPictFmla / non-default FtCf / non-default FtPioGrbit content across the opslaan cycle. - Investigation note — Flush auto-corrects sz.
TMsoShapeContainer.Flushrewrites the Obj record's size header at commit time viaData.SetWord(Data.DataLength - 4, 2), which means the hardcodedsz := $1Avalues that have lived in HotXLS AddObj implementations for years were not spec bugs after all — Flush corrects them automatically. v2.88.27 still computes sz accurately for source-code clarity, but the runtime behaviour is unchanged from that perspective.
Versie 2.88.26
- OBJ trailing-subrecord rondreis extended to Chart and CheckBox shapes. v2.88.25 introduced raw-byte preservation for the bytes between an Obj record's CMO ($0015) and its FtEnd ($0000) marker, but only TMSOShapeTextBox.AddObj emitted the captured tail. This release applies the same pattern to TMSOShapeChart.AddObj and TMSOShapeCheckBox.AddObj — both share the simple "CMO + FtEnd" emit structure of TextBox, so the change is a one-line variable substitution (
sz := $1A + Word(Length(FObjTailRaw))) plus a verbatim byte loop before the FtEnd marker. - Chart trailing subrecords (e.g. FtMacro for embedded chart object macros) and checkbox state subrecords (FtCbls + FtCblsData + ObjLinkFmla, MS-XLS §2.5.140-141 / §2.5.149) now survive HotXLS opslaan/reload. Freshly authored charts and checkboxes via the Drawing API still emit a default 26-byte CMO+FtEnd (byte-identical to v2.88.25), so existing callers see no behaviour change. Picture / ComboBox / ListBox / PictureFrame shapes have their own dynamic typed-subrecord emit that conflicts with FObjTailRaw — their integration is deferred to future commits.
Versie 2.88.25
- OBJ record trailing subrecords now preserved across the opslaan cycle for comments. The BIFF8 Obj record ($005D) chains a sequence of typed subrecords after the mandatory CMO ($0015), terminated by an FtEnd ($0000) marker, per MS-XLS §2.4.181. For Note (comment) shapes the trailing block is typically a 26-byte FtNts (§2.5.149) carrying a GUID and the fSharedNote flag — both essential when Excel later merges comments across users in shared werkmappen. HotXLS previously discarded every byte after CMO on lezen and emitted only an empty FtEnd on schrijven, so any source-file FtNts was lost on every HotXLS resave.
- Generic-base capture, TextBox-only emit (R5-3 first slice). TMsoShapeContainer.ParseObj now captures the byte bereik between CMO body end and FtEnd marker into a new internal
FObjTailRaw: TBytesfield; TMSOShapeTextBox.AddObj inserts those bytes between its CMO emit and the FtEnd marker, with the Obj record header size adjusted accordingly. Newly authored comments (no source bytes) keep byte-identical output to v2.88.24. Other shape classes (Picture / CheckBox / ComboBox / ListBox / Chart) inherit the capture but their typed AddObj overrides keep the legacy "synthesise from scratch" behaviour — raw-bytes emit for those shape types is deferred to future commits.
Versie 2.88.24
- Multi-font and multi-color cel comments now rondreis. The BIFF8 TXO record's formatting-runs block (
rgTxoRuns+TxOLastRunper MS-XLS §2.5.272) carries the per-run font and color overrides that give a comment its rich-text styling. HotXLS previously discarded the entire block on lezen and emitted a single empty default run + LastRun on schrijven — flattening any "Important!" highlighted in red, any bold word inside the comment text, into uniform default formatting on every HotXLS resave. - Raw-byte preservation in TMSOShapeTextBox. ParseTXO captures the post-text Continue bytes verbatim into a new internal
FFormatRunsRaw: TBytesfield; Store emits them back as the formatting-runs Continue and adjusts the base record'scbRunsheader to match. Newly authored comments (viaAddComment) keep the legacy single-default-run output unchanged, so byte-identical output is preserved for default werkmappen. Typed Excel-API access to individual format runs is still deferred — the existing single-WideString comment API is unchanged.
Versie 2.88.23
- Print resolution and copy count now rondreis — Setup record now fully covered. Three Setup-record Word fields (
iResat offset 12,iVResat offset 14,iCopiesat offset 32, per MS-XLS §2.4.257) carry Excel's "Page Setup → Page → Print quality" and "Number of copies" choices. HotXLS previously dropped all three on lezen and emitted hardcoded values (600 DPI / 600 DPI / 1 copy), so any user-tweaked resolution or copy count silently reverted on every HotXLS resave. - Three new TXLSPageSetup eigenschappen.
PrintResolution: LongWord,PrintVResolution: LongWord, andCopies: LongWord— all default to the values the writer previously hardcoded (600 / 600 / 1) so werkmappen that never touch them produce byte-identical output to v2.88.22. Setters clamp atHigh(Word)so an over-large caller value cannot wrap on emit. - Setup record rondreis work complete. With this fix every zichtbaar voor gebruikers field of the BIFF8 Setup record ($00A1) round-trips end to end — paper size / scale / first page number / fit-to-page width and height / orientation / print order / black-and-white / draft / print comments / cel errors / resolution / copies. Only the two spec-hint grbit bits (
fNoPls,fNoOrient) remain unexposed, both of which HotXLS schrijft as zero matching Excel's default behaviour.
Versie 2.88.22
- aangepaste Page Setup "First page number" now round-trips. The BIFF8 Setup record carries the werkmap's Page Setup → Page → "First page number" choice as two related fields: grbit bit 7 (
fUsePage) selects between Excel's "Auto" default and an explicit starting page number, and the signed Word at offset 4 (iPageStart) holds that aangepaste value, per MS-XLS §2.4.257. HotXLS previously dropped both on lezen and emittediPageStart = 1with the bit clear, so a user-typed "First page number: 100" silently snapped back to "Auto" on every HotXLS resave. - Two new TXLSPageSetup eigenschappen.
UseFirstPageNumber: Booleanmirrors the bit (False = "Auto", default);FirstPageNumber: Integercarries the iPageStart value (default 1, clamped to the spec's signed-Word bereik -32768..32767 by the setter). HotXLS round-tripsiPageStartverbatim even whenUseFirstPageNumberis False, so toggling between Auto and aangepaste in Excel behoudt the last user-typed value.
Versie 2.88.21
- "Print comments at end of sheet" choice now survives the opslaan cycle. The BIFF8 Setup record's grbit bit 9 (
fEndNotesper MS-XLS §2.4.257) carries the Page Setup → Sheet → Comments dropdown's distinction between "As displayed on sheet" (the default) and "At end of sheet". HotXLS already round-tripped PrintNotes (bit 5) to control whether comments print, but bit 9 was dropped on lezen and emitted as zero on schrijven — so a user-chosen "At end of sheet" silently reverted to "As displayed on sheet" on every HotXLS resave. - New TXLSPageSetup.PrintNotesAtEnd Boolean eigenschap. Defaults to
Falsematching Excel's UI default. The reader and writer rondreis the bit verbatim (even whenPrintNotes = False), so a werkmap with comments temporarily disabled retains the "at end of sheet" preference for when the user re-enables them — mirroring Excel's own behaviour.
Versie 2.88.20
- werkmap "Set precision as displayed" choice now round-trips. The BIFF8 CalcPrecision record ($000E) carries the werkmap-wide File → Options → Advanced → "Set precision as displayed" checkbox per MS-XLS §2.4.35. HotXLS previously had no dispatcher case for $000E and TXLSWorkbook.StorePrecision emitted a hardcoded
1(= full precision retained). A user-checked "Set precision as displayed" silently reverted to "full precision" on every HotXLS resave — hiding the user's deliberate intent that any subsequent recalc should permanently truncate cel values to their formatted decimal places. - New TXLSWorkbook.UseFullPrecision Boolean eigenschap. Defaults to
True(matches the BIFF8 default and Excel's UI default of unchecked). Setting it toFalsemirrors checking the destructive "precision as displayed" option — HotXLS itself does not truncate any cel value on the rondreis, but the flag is now faithfully written back so Excel's next recalc respects it. With this fix, every BIFF8 calc record (CalcCount / CalcMode / CalcPrecision / CalcDelta / CalcIter / CalcSaveRecalc) round-trips end to end.
Versie 2.88.19
- "Recalculate werkmap before saving" checkbox now round-trips. The BIFF8 CalcSaveRecalc record ($005F) carries the werkmap's File → Options → opslaan → "Recalculate werkmap before saving" boolean, per MS-XLS §2.4.37. HotXLS previously had no dispatcher case for $005F and StoreCalculationSettings emitted a hardcoded
1— so a user-disabled "recalc on opslaan" silently re-enabled itself on every HotXLS resave, which actually mattered for manual-calc werkmappen where the user had deliberately frozen the on-disk cel values. - New TXLSWorkbook.RecalcOnSave Boolean eigenschap. Defaults to
True(matches both Excel's UI default and the legacy hardcoded value), so werkmappen that never touch the eigenschap keep byte-identical output to v2.88.18. Setter accepts any Boolean; the reader normalises arbitrary non-zero source bytes toTrue.
Versie 2.88.18
- Iterative calculation settings (enable + max iterations + max change) now rondreis. The BIFF8 CalcIter ($0011), CalcCount ($000C), and CalcDelta ($0010) records together carry Excel's "Enable iterative calculation" trio of options (File → Options → formules), per MS-XLS §2.4.33 / §2.4.31 / §2.4.32. None of the three had a dispatcher case before, and StoreCalculationSettings emitted them with hardcoded values (off / 100 / 0.001). A user-configured 1000-iteration loop with a 0.0001 convergence delta silently reset to "iteration off, 100, 0.001" on every HotXLS resave — breaking circular-reference formules and convergence-sensitive financial models.
- Three new TXLSWorkbook eigenschappen.
EnableIteration: Booleanmirrors the checkbox;MaxIterations: LongWordis the iteration cap (clamped to the spec-legal 1..32767 bereik by the setter);MaxIterationChange: Doubleis the convergence delta (negative input snaps to the spec default 0.001). Defaults match the values the writer used to hardcode, so werkmappen that never touch the new eigenschappen produce byte-identical output to v2.88.17.
Versie 2.88.17
- werkmap calculation mode (Manual / Automatic / Auto except tabellen) now round-trips. The BIFF8 CalcMode record ($000D) carries the werkmap-level "formules → Calculation Options" choice per MS-XLS §2.4.36. HotXLS previously had no dispatcher case for $000D at all, so the source file's value was discarded on load, and the writer always emitted a hardcoded
$0001(Automatic). A user-geselecteerde Manual mode silently reverted to Automatic on every HotXLS resave — bad for large werkmappen where Manual is set deliberately for performance. The new ParseCalcMode handler stores the source value on the werkmap and StoreCalculationSettings now emits the stored value instead of the constant. - New TXLSWorkbook.CalculationMode eigenschap. lezen-schrijven
LongWordeigenschap acceptingxlCalcManual(0),xlCalcAutomatic(1, default), orxlCalcAutomaticExceptTables(0xFFFF) — three new constants exported fromlxTNC.inc. The setter clamps unknown values to the spec default so a corrupt source file cannot leave the werkmap in an undefined state. Existing code that never touches the eigenschap keeps the legacy "Automatic" default, so previous output is byte-identical for default werkmappen.
Versie 2.88.16
- Page Setup "cel errors as" choice now survives the opslaan cycle. The BIFF8 Setup record ($00A1) packs the Page Setup → Sheet tab "cel errors as: displayed / <blank> / <dash> / <N/A>" dropdown into bits 10-11 of its grbit word as
iErrors, per MS-XLS §2.4.257. HotXLS previously dropped these bits on lezen and emitted them as zero on schrijven, so a werkmap the user had configured to print#DIV/0!as#N/Asilently reverted to "displayed" after every HotXLS resave. The reader now decodesiErrorsinto a newTXLSPageSetup.PrintCellErrorseigenschap and the writer rebuilds the field from it. - New TXLSPageSetup.PrintCellErrors eigenschap. lezen-schrijven
LongWordeigenschap acceptingxlPrintErrorsDisplayed(0, default),xlPrintErrorsBlank(1),xlPrintErrorsDash(2), orxlPrintErrorsNA(3) — four new constants exported fromlxTNC.inc. Existing PageSetup callers that never touch the eigenschap keep the default ("displayed"), so the legacy print output is unchanged.
Versie 2.88.15
- cel comment alignment and orientation now rondreis. The BIFF8 TXO base record ($01B6) carries five typed flags in its
grbitword (hAlignment, vAlignment, fLockText, fJustLast, fSecretEdit) plus a separaterotword for text orientation, per MS-XLS §2.4.329. The reader previously dropped all of these and the writer pinnedgrbitto a hardcoded0x0012(left + top) with rotation always 0, so every opslaan reset a centered or rotated comment back to left+top+horizontal regardless of source. The reader now decodes the typed fields on load and the writer composesgrbitfrom them, so the layout survives the opslaan/reload trip. - Six new TMSOShapeTextBox eigenschappen for explicit comment styling.
HAlignment,VAlignment,Rotation,LockText,JustLastLine, andSecretEditare exposed as lezen-schrijven eigenschappen on each comment shape;AddCommentdefaults to left+top+horizontal+unlocked so callers that do not touch them keep the previous appearance. - TXO writer now lays out reserved4 / reserved5 along spec field boundaries. Previous code emitted offsets 2-9 of the base record as two long schrijft (rot + reserved4 then reserved5); the writer now splits them into
Wordrot,Wordreserved4,Longreserved5 — the byte content is unchanged (still all-zero for Note shapes) but the source structure now matches MS-XLS §2.4.329 field offsets, making future TXO herstelt harder to misalign.
Versie 2.88.14
- TXO cchText offset corrected — the v2.88.13 comment-length fix now actually fires. The previous release introduced a sanity check for the TXO base record by reading
cchTextat offset 8, but MS-XLS §2.4.329 putscchTextat offset 10 (after grbit, rot and the 6 reserved / controlInfo bytes). Offset 8 falls inside the reserved5 long, which is always zero on Note-shaped objects, so every comment quietly slid into the defensive fallback that simply restored the pre-v2.88.13 behaviour. The fix corrects the offset to 10 — long comments now genuinely stitch across Continue records and short comments no longer pick up trailing padding. No further behavioural change beyond what v2.88.13 was always supposed to ship.
Versie 2.88.13
- Long cel comments now lezen back at full length. The BIFF8 TXO record ($01B6) splits its text body across the base record and one or more Continue records, with the character count published in the base record at offset 8 as
cchText. The previous comment reader skipped the base record entirely, treated DataList[1] as the entire text, and stopped there — so a comment longer than about 4100 wide characters was silently truncated, and a shorter comment whose Continue record carried trailing padding picked up junk at the end. The reader now consumescchTextas the authoritative character count, walks each Continue segment per MS-XLS §2.4.329 (the rgb break sits on a character boundary so no partial-character bookkeeping is needed), and stops as soon as the budget is satisfied so the formatting-runs block that follows the text never bleeds into the string. Comments with corrupted / missing base records still fall back to the legacy "all remaining bytes" path.
Versie 2.88.12
- Cached strings longer than ~4100 characters from string-returning formules now rondreis across Continue records. v2.88.11 wired up the lezen side of the BIFF8 String record ($0207) but only consumed the first record body, so a cached string whose UCS-2 bytes overflowed the 8224-byte BIFF limit and spilled into one or more Continue records ($003C) was silently truncated. The handler now walks the entire dispatch-level DataList: it leest cch and fHighByte from the base record, copies the body that fits there, then concatenates every following Continue segment as raw bytes per the MS-XLS §2.5.293 character-boundary guarantee — XLUnicodeString never re-emits fHighByte mid-string. Each segment is bounded by the remaining character budget so a stray oversized Continue cannot make the result longer than cch. Single-record strings (the common case) take the exact same fast path as before.
Versie 2.88.11
- String-returning formules now rondreis the cached text Excel computed. The previous release covered the number, boolean, error and empty variants of the BIFF8 FormulaValue cache (MS-XLS §2.5.133), but left the string variant on the to-do list because its cached value lives in a separate String record ($0207) that immediately follows the formule record. ParseFormula now remembers the cel coordinates when it sees a string-variant formule, and the new ParseString handler decodes the trailing $0207 record per MS-XLS §2.4.268 and routes the WideString into
FCachedFormulaValue.GetCellValuekan nu fall back to the Excel-computed text whenever the HotXLS evaluator cannot reproduce it. A defensive reset at the top of ParseFormula drops any stale pending anchor so a malformed source file with a missing String record cannot misroute a later one. Records longer than 8224 bytes that overflow into Continue chunks still fall back to evaluator output as a known limitation.
Versie 2.88.10
- BIFF8 formule records now rondreis the cached value Excel computed. ParseFormula used to skip the 8-byte FormulaValue payload at offset 6 entirely, so the cached result of every formule in a geladen .xls (numbers, booleans, errors, empty) was thrown away and HotXLS had to re-evaluate every cel through its own formule engine. When that engine could not match Excel (unsupported XLM functions, broken external links, formules the engine has not yet implemented) the cel silently became blank or zero. The reader now decodes the four numeric / boolean / error / empty variants per MS-XLS §2.5.133 and stores them on a new
TXLSCellRef.FCachedFormulaValuefield;GetCellValuefalls back to that cache only when the evaluator fails, so freshly-authored formules still go through evaluation as before. The string variant continues to defer to the evaluator because the trailing String record ($0207) parser is not yet wired up.
Versie 2.88.9
- BIFF8 formule records with unresolvable values now flag fAlwaysCalc instead of the reserved1 bit. When the HotXLS evaluator could not calculate a formule at opslaan time, the writer used to set
grbit = 0x0002— bit 1, which MS-XLS §2.4.127 reserves and tells readers to ignore. Excel duly ignored it, treated the placeholder cached value of 0 as authoritative, and silently displayed 0 instead of recalculating. The writer now setsgrbit = 0x0001(fAlwaysCalc, bit 0), so Excel re-runs the formule on next recalc and the cel shows the correct result.
Versie 2.88.8
- PageSetup.PrintTitleColumns / PrintTitleRows now raise on bad input. Setting either eigenschap with a malformed bereik string (anything
ColDiapasonToValues/RowDiapasonToValuescould not parse) previously dropped the assignment silently — the werkmap kept whatever Print_Titles bereik was already set, or no bereik at all, and the caller had no way to find out something went wrong. The setters now raiseException.Createwith a descriptive message naming the offending value, matching the existing raise stijl onTXLSRangeinvalid-index paths.
Versie 2.88.7
- Row miyRw field now stays within the MS-XLS spec bereik. Pre-BIFF8 versions of Excel encoded "use the werkmap default row height" by OR-ing bit 15 into miyRw, and HotXLS carried that idiom forward in the BIFF8 writer even though MS-XLS §2.4.221 caps miyRw at 8192 twips. Modern Excel emits a plain 255 (12.75 pt default) in the same case and uses the fUnsynced grbit bit to signal manual overrides, so the bit-15 hack made HotXLS output diverge from authoritative .xls files (a value of 32 959 = 0x80FF for "default" was technically out-of-spec). The writer now drops the OR and schrijft 255 directly; the reader still strips bit 15 on the way in for backwards compatibiliteit with HotXLS v2.88.6 and earlier files plus rare third-party generators that copied the BIFF5 idiom.
- BIFF8 spec audit round 2 errata note toegevoegd. Re-checking the [MS-XLS] field boundaries clarified two findings flagged as P2 in the original report (
dev-notes/XLS-BIFF8-Spec-Audit-Round2.md) are not actual bugs: the bit-15 set in the BOF history flag $000080C9 belongs to the verXLHigh field (bits 14-17, value 2 = "Excel 2002"), not the reserved1 tail (bits 19-31); and ParseFormula's use of a leading PtgExp token to detect shared / array formules matches what the spec implies and disambiguates correctly via the following ShrFmla / Array record. Both items are now annotated as retracted.
Versie 2.88.6
- Macro sheets and VBA modules now keep their BoundSheet8 ordinal slot. The reader previously dropped BoundSheet8 records whose
dtfield was 1 (macro sheet) or 6 (VBA module), so the HotXLS Sheets collection ran short by those entries. Any XTI cross-reference in ExternSheet that pointed at a sheet position past a macro sheet by file order then resolved to the wrong HotXLS werkblad after a SaveAs. The reader now voegt toe a placeholder sheet for every BoundSheet8 record and stores the rawdtbyte on a newSheet.SheetTypeRaweigenschap; the writer emits the original byte back. Macro substream BOF records ($0040) are also treated as werkblad substreams during parsing so cellen inside macro sheets are preserved rather than silently absorbed into the previous sheet.
Versie 2.88.5
- BIFF8 Row record now round-trips fCollapsed, fExAsc, fExDes and fPhonetic. Previously the reader dropped fCollapsed (grbit bit 4) — the writer inferred it from outline-level transitions on neighbouring rows, which misclassified rows the source file had explicitly collapsed or marked as boundaries. The high three bits (fExAsc at 28, fExDes at 29, fPhonetic at 30) were never lezen either, and were always emitted as zero because the writer truncated the 4-byte grbit to a single 16-bit ixfe slot. The reader now consumes all four bits per MS-XLS §2.4.221 and pins fCollapsed as explicit so the writer-side inference no longer overwrites Excel-asserted values. The writer packs ExAsc / ExDes / Phonetic into bits 12-14 of the ixfe Word, masking ixfe to the spec-allowed 12-bit bereik to prevent an XF index ever colliding with the new flags. rondreis side effects: thick-top / medium-bottom borders driven by ExAsc / ExDes hints now survive HotXLS SaveAs, and phonetic info visibility on Japanese sheets stops resetting on every opslaan.
Versie 2.88.4
- BIFF8 Window2 fPaged bit now flags only the active sheet. Previous releases set
fPaged(MS-XLS §2.4.346 bit 10) on every visible sheet, which made HotXLS output diverge from what Excel itself schrijft (per spec the bit means "this sheet is currently displayed in the werkmap window", so only the active-sheet substream should carry it). Excel readers fell through toWindow1.itabCurto identify the real active sheet anyway, so the misuse was tolerated, but Apache POI strict mode and other tooling that trustsfPagedas a primary signal now see the correct sheet flagged.
Versie 2.88.3
- BIFF8 Window2 zoom and gridline color now rondreis. Previous releases dropped the WINDOW2 record fields past offset 6 on lezen and emitted hard-coded zeros on schrijven, so any Excel-saved sheet zoom (75 percent, 125 percent, etc.) and gridline color customisation reverted to defaults after a HotXLS SaveAs. The reader now consumes
icvHdr,wScaleSLVandwScaleNormalper MS-XLS §2.4.346: the active-view zoom feedsSheet.Zoomand the opposite-view value lands in a cached slot so switching between Normal and Page Break Preview in Excel restores the previous zoom. The writer emits the activeSheet.Zoomin the matching view slot and the cached value in the other, plus the preserved gridline color index.
Versie 2.88.2
- Fixed BIFF8 HFPicture record opcode. Saved .xls files now emit header / footer background-image records with the correct
rt = 0x0866per MS-XLS §2.4.138. Previous releases used0x086C— the opcode for CellWatch — so Excel tried to parse the embedded OfficeArt BLIP as a watched-cel reference and silently dropped the picture (sometimes refusing to openen the werkmap when the embedded image bytes happened to violate CellWatch’s expected 16-byte structure). werkmappen that rondreis a header / footer image through HotXLS now keep the image intact.
Versie 2.88.1
- Fixed BIFF8 Theme record opcode. Saved .xls files now emit the Theme record with the correct
frtHeader.rt = 0x0896per MS-XLS §2.4.326. Previous releases used0x0892— the opcode for StyleExt — so Excel interpreted the embedded OOXML theme payload as a cel-stijl extension and silently fell back to the built-in Office theme, losing any customised theme colors when round-tripping a werkmap through HotXLS.
Versie 2.88.0
- [MS-XLSX] cross-audit round 4 — theme part + sheet-name setter. Two follow-up herstelt targeting issues left after rounds 1–3 (v2.51.0 / v2.52.0 / v2.54.1). Neither breaks an existing call site; one extends behavior at a setter, the other voegt toe a new always-emitted part.
- Saved .xlsx packages now include an
xl/theme/theme1.xmlpart. stijlen.xml has always emitted<color theme="N"/>references for any font / fill / border / tab color set through the theme-index path (and for theme colors carried through from a parsed input .xlsx), but no theme part was written, so the references dangled. Excel tolerated the omission by falling back to its built-in “Office” theme silently, but Office File Validation flagged every reference as “theme part missing” and Apache POI strict mode rejected the werkmap on first lookup.SaveAsnow emits the canonical Office (2007+) theme: 12-slot color scheme (systemwindowText/window, four Excel default colors, six accents, two hyperlink colors), Calibri Light / Calibri font scheme, minimum-valid format scheme (three fill / line / effect / background-fill entries each perCT_StyleMatrix).[Content_Types].xmlgains a matchingOverride;xl/_rels/workbook.xml.relsgains atheme/theme1.xmlrelationship that lands at the tail of the rid bereik, so existingXlsxFirstExternalLinkRidoffsets for sheets / sst / stijlen / vba / externalLinks are unchanged. - Direct
Sheet.Name := '...'assignment now sanitises and dedupes too. Round 3 (v2.54.1) toegevoegd Excel naming-rule enforcement inTXLSXSheets.Add(AName), but theTXLSXWorksheet.Nameeigenschap setter was a rawwrite FName, so the most common mutation path that round didn’t cover —lxXlsxExport.pas:122 Target.Name := Source.Namein the XLS → XLSX rondreis — let through any name the BIFF8 source happened to carry (forbidden chars: \ / ? * [ ], length > 31, surrounding single quotes, reservedHistory, case-insensitive duplicates of an existing sheet). The eigenschap setter now routes through a newSetNamemethode that replays the sameXlsxSanitizeSheetName+' (N)'-suffix dedup logic (case-insensitive, exclude-self) against the parent werkmap’s sheet collection. Detached werkbladen (noFWorkbookback-pointer yet) skip the dedup step and just sanitise —TXLSXSheets.Addwill enforce uniqueness when the sheet attaches. Idempotent on already-valid names so reader-sideFSheets.Add(names[i])stays a pure rondreis.
Versie 2.87.4
- XLS shared formules now schrijven a valid
ShrFmlabody. BIFF8 shared-formule output bevat nu the requiredcUsebyte before the shared parsed formule, so werkmappen saved withUseSharedFormulasno longer shift the formule token stream by one byte. - XLS tabel stijl and filter metadata now matches the latest MS-XLS layout.
AddTablenow schrijftLIST12asList12TableStyleClientInfo, sets tabel and field AutoFilter flags inFeature11, and emits the empty per-columnFeat11FdaAutoFilterblocks Excel expects. - BIFF8 CF12 Data Bar / Color Scale / Icon Set rules now omit forbidden DXF payloads. HotXLS follows the MS-XLS rule that these CF12 types must carry an empty DXF block, while preserving their actual rule settings in the CF12 kind-specific tail.
Versie 2.87.3
- XLS werkblad tabel metadata now follows the MS-XLS
Feature11tabel layout.AddTableoutput for .xls files now schrijft aFeatHdr11tabel header plusFeature11TableFeatureType/Feat11FieldDataItempayloads, removes the legacy$0867 FeatHdrtabel marker, and stores tabel and column names asXLUnicodeStringvalues. - XLS tabel readback now understands the spec-correct field layout. HotXLS parses
TableFeatureTypetabel names, bereiken, totals-row state, and field captions, while keeping a fallback for older HotXLS-generated tabel records.
Versie 2.87.2
- XLS BIFF8 continuation records now carry correct base lengths. Oversize XLS records split by the writer now update the first record length to 8224 bytes instead of leaving the original oversized length in the BIFF header.
- Large XLS werkblad tabellen now use spec-correct
ContinueFrt11chunks. WideAddTableoutputs with largeFeature11payloads now opslaan with$0875 ContinueFrt11continuation records and reopen with tabel metadata preserved, matching the [MS-XLS]Feature11/ContinueFrt11layout.
Versie 2.87.1
- XLSX werkblad grid limit bevat nu the last Excel row and column.
TXLSXRange,RCRange,EntireRow, andEntireColumnnow allow row 1048576 and column 16384 (XFD), matching [MS-XLSX] row-number and column-number bounds. Earlier the internal clamp used zero-based maxima, soXFD1048576and bereiken touching the last row or last column were silently clipped to the previous row/column. - XLSX encryption docs and tests now match the implemented schrijven path. Help pages and the regression suite now state that
SaveAsEncryptedschrijft ECMA-376 Standard Encryption output for non-empty passwords, whileOpenEncryptedstill raises for encrypted packages and falls back for plain .xlsx files.
Versie 2.87.0
- XLSX password-protected opslaan now works (wave J phase 2, backlog #29).
TXLSXWorkbook.SaveAsEncrypted(FileName, Password)now schrijft a real ECMA-376 Standard Encryption-protected .xlsx file (Office 2007+ format). The complete [MS-OFFCRYPTO] §2.3.4 pipeline is in place: phase 1's SHA-1 50000-iteration password derivation + AES-128 verifier blocks + AES-CBC package body encryption + binaryEncryptionInfoserializer is now joined by phase 2's four\005DataSpacesmetadata streams (Version / DataSpaceMap / DataSpaceInfo / TransformInfo) and the OLE Compound File Binary writer that drops everything into a CFB container Excel opens with the user password. Workflow: caller invokesSaveAsEncryptedwith a non-empty password → HotXLS serialises the werkmap into an in-memory plaintext .xlsx zip → encrypts via AES-128 CBC with a fresh random 16-byte salt and verifier → schrijft the CFB output viaStgCreateDocfile. openen in Excel 2007+: enters password → content opens. Wrong password: rejected.OpenEncrypted(decrypt side) is still a separate backlog item and continues to raiseEXlsxEncryptionNotImplementedwhen handed an encrypted file.
Versie 2.86.1
- XLSX Standard Encryption — cryptographic foundation (wave J phase 1, backlog #29). Two new internal units land the cipher and key-derivation half of the ECMA-376 Standard Encryption schrijven path.
lxAES.paswraps Brian Gladman's AES (linked fromthirdparty/Win32/aes*.obj+thirdparty/Win64/aes*.obj) and exposes AES-128 ECB single-block and AES-128 CBC encryption entry points.lxXlsxStdEncrypt.pasimplements pure-Pascal SHA-1 (FIPS-180-4), the [MS-OFFCRYPTO] §2.3.4.10 50000-iteration password derivation, the §2.3.4.7 verifier blocks (EncryptedVerifier+EncryptedVerifierHash), AES-CBC package body encryption (8-byte LE size prefix + zero-pad to 16-byte boundary + IV-of-zeros), and the §2.3.4.6 binaryEncryptionInfoserializer.TXLSXWorkbook.SaveAsEncryptedstill raisesEXlsxEncryptionNotImplemented— wave J phase 2 will add the OLE Compound File Binary writer (\005DataSpacescontainer streams) and wire the pipeline toSaveAsEncrypted. Until then, the new units are library-internal scaffolding callers should not depend on.
Versie 2.86.0
- QueryTable and External Data Connection rondreis (wave I, backlog #28). Excel-created QueryTables and external data connections (Data → Get External Data from Web / SQL / OLEDB) now survive a HotXLS opslaan/openen cycle. Earlier the BIFF8 reader silently skipped
QsiSXTag($0802),QsiSXTagExt($0810), andDConn($0876), so the metadata that describes the upstream query was dropped on opslaan and the tabel degraded to plain cel values. The reader now captures these records as opaque bytes and the writer emits them back into the werkblad substream (alongside the PIVOTVIEW block per [MS-XLS] §2.1.7.20.5) and the werkmap globals (alongside the late globals block before EOF per §2.1.7.20.3). HotXLS still does not model the typed QSI / DConn structure programmatically — creating new QueryTables from caller code is deferred to a later wave — but werkmappen that already contain them no longer lose refresh metadata. BIFF8 (.xls) only; BIFF5 unaffected.
Versie 2.85.1
- Restore Win32 / Win64 library build. Two pivot-line-item hulp variables in the wave H5.3 multi-data-field SXLI emitter were declared as separate
array of array of Wordanonymous types, which the Delphi compiler treats as distinct unnamed types and rejects on direct assignment withE2008 Incompatible types. The HotXLS library has not built since v2.84.1 on RAD Studio 12.0 through 37.0. The two variables are now declared together so they share a single anonymous type, fixing the assignment and restoring the .dcu / .bpl output for both Win32 and Win64 targets. No runtime behaviour change — the emitted SXLI bytes are identical to v2.85.0.
Versie 2.85.0
- Typed pivot subtotal API (wave H5.4). The typed
TXLSPivotFieldnow exposes aSubtotals: TXLSPivotSubtotalsset eigenschap alongside the existing rawSubtotalMask: Word. Callers can assign e.g.Field.Subtotals := [xlpsSum, xlpsAverage];instead of bit-packing the SXVDgrbitSubfield by hand. Twelve subtotal types are exposed (xlpsDefault, xlpsSum, xlpsCount/CountA, xlpsAverage, xlpsMax, xlpsMin, xlpsProduct, xlpsCountNums, xlpsStdDev, xlpsStdDevP, xlpsVar, xlpsVarP), each mapping to a single bit per [MS-XLS] §2.4.279. The rawSubtotalMaskstays the rondreis source of truth — reserved bits 12-15 are preserved on lezen/schrijven. Closes the wave H4.3 known limit “row field subtotal SXVD.grbitSub configuration unavailable from API” and finishes the wave H5 pivot follow-ups.
Versie 2.84.1
- Multi data-field SXLI expansion (wave H5.3). When a pivot tabel has more than one data field AND the data-field axis matches a given SXLI axis (
DataFieldAxisIsRow = True&& row axis, orDataFieldAxisIsRow = False&& column axis), the writer now replicates each cartesian-product combinationDataFieldCounttimes withiData = 0 .. DataFieldCount - 1, plusDataFieldCountgrand-total lines so each data field gets its own total. The non-hosting axis is unchanged. Excel and other readers now render multi-data-field pivots in the layout the caller intended instead of falling back on the previous “singleiData = 0per combination” approximation. Single-data-field pivots emit bit-identical output to v2.84.0. Delta compression (H5.1) folds the repeated combinations down to ~8 bytes per replica, so the expansion voegt toe minimal byte overhead. Closes the wave H4.3 known limit “multi-data-field SXLI not correctly expanded”.
Versie 2.84.0
- Pivot page-axis pre-selection API (wave H5.2). The typed
TXLSPivotFieldnow carries aPageItemIndexeigenschap that programmatically-built pivots can set to pre-select a specific cache item on the page-axis filter. DefaultxlPageItemAll(= $7FFD) leaves the filter at “(All)” so callers that never assignPageItemIndexbehave bit-identically to v2.83.2. The SXPI ($00B6) writer leestField.PageItemIndexinstead of hardcoding $7FFD, and the typed reader now populatesPageItemIndexfrom SXPI on openen so callers can inspect the saved page selection. Closes the wave H4.3 known limit “page filter caller-pre-selection unavailable from API”.
Versie 2.83.2
- Smaller pivot SXLI records via delta compression (wave H5.1). The pivot writer now delta-compresses SXLI line items using the spec's cSic field — each line's leading cache-item indices that match the previous line in the same SXLI record are folded into a shared-prefix count, and only the trailing indices are emitted. Typical row-axis SXLI records (a few row fields × dozens of items) shrink by 30–60% with no change in semantics. Output is still chunked to stay under the 8224-byte BIFF record limit. The first line of every SXLI record always emits cSic = 0 (record-local, no cross-record back-reference), and the grand-total line is never delta-compressed.
Versie 2.83.1
- cel fill, font, and border colors set via RGB now rondreis through .xls opslaan/openen. The BIFF8 XFExt ($087D) writer was emitting each record's ixfe field using the in-memory XF array position, but the matching cel records on disk schrijven ixfe using the post-pruning SaveIndex order. Whenever any XF earlier in the tabel was pruned during opslaan (typical when one cel migrates from a transient XF to a final XF), every XFExt's ixfe ended up off by the number of pruned slots, and the rich color associated with each cel shifted to a neighbouring cel on reload. The writer now resolves SaveIndex for each rich-slot XF and emits the matching on-disk ixfe, so RGB cel colors saved by HotXLS — interior fill, font color, border colors — survive a opslaan / reload rondreis cleanly. XFExt records for XFs that got pruned entirely are now skipped rather than emitted with a dangling ixfe.
Versie 2.83.0
- Pivot line items + page item state (wave H4.3). Programmatically-built pivot tabellen now emit SXLI ([MS-XLS] §2.4.275, $00B5) for both row and column axes, plus SXPI ($00B6) for the page axis. This gives the pivot view layout-fidelity: non-Excel readers see the exact display order the writer intended, large pivots openen faster (Excel doesn't have to recompute line layout from scratch), and page filters persist with a default "(All)" selection per page field.
- Row + column SXLI enumeration. The writer enumerates the cartesian product of axis fields' cache items (innermost field varies fastest, matching Excel's nested-row layout) and emits one line per combination plus a trailing grand-total line marked with the SXLI nTypes fGrandTotal bit. Each line uses cSic = 0 (no delta-compression — simpler at the cost of a few extra bytes per line). Output is chunked into multiple SXLI records when the line count overflows the 8224-byte BIFF limit; a 16384-line safety cap prevents runaway expansion on pathological inputs.
- SXPI page-axis state. Emitted only when at least one field has Axis = xlpfaPageField. Each entry is 10 bytes (isxvd + iCache + ipos + objId) with iCache = $7FFD signalling "(All)" — the API surface for pre-selecting specific page items is deferred to wave H5. Pivots without page fields emit no SXPI (the werkblad ABNF lists it as optional).
- Closes wave H3 known limit "SXLI / SXPI not emitted". Combined with H4.1 (DataField number formats) and H4.2 (SXDBB per-record stream), wave H4 closes all three known limits in the H3 pivot-tabel writer. Pivot tabellen built via
IXLSWorksheet.AddPivotTablenow ship self-contained caches with full layout metadata.
Versie 2.82.0
- Pivot cache self-contained per-record stream (wave H4.2). Programmatically-built pivot caches now emit SXDBB records ([MS-XLS] §2.4.272, $00C5 in cache context) carrying the per-record field-value indices in the spec's bit-packed encoding. Without SXDBB, Excel had to refresh the cache from the source bereik on openen — which worked when the source data was present and unchanged, but broke when the source was renamed / deleted or had drifted since the pivot was built. The cache is now self-contained.
- Bit-packed encoding per spec. Each field uses
ceil(log2(itemCount + 1))bits per record (sentinel space included). Records are byte-aligned — every new record starts on a fresh byte boundary. The writer chunks the stream into multiple SXDBB records to stay under the 8224-byte BIFF size limit, so caches with tens of thousands of source rows still serialise cleanly. - rondreis path unchanged. Pivot caches lezen from disk (FromRawBlobs = True) continue to rondreis via the wave H1 raw-byte path — the new SXDBB writer only fires for typed caches built by
IXLSWorksheet.AddPivotTable. Mixed werkmappen (one round-tripped cache + one new cache) emit both paths cleanly.
Versie 2.81.0
- Pivot data field number formats (wave H4.1). Pivot data fields kan nu carry an Excel number format string so currency / percentage / date data renders with the right glyphs on openen instead of showing raw General-format values. New
IXLSWorksheet.PivotSetDataFieldFormat(DataField, FormatStr): Wordregisters the format in the werkmap's NumFormats tabel (auto-add or reuse) and schrijft the resulting ifmt index toTXLSPivotDataField.NumberFormat. The typed writer already emits SXDI.ifmt, so this closes the loop. - Public NumFormats hulp on TXLSWorkbook.
Workbook.RegisterNumFormat(FormatStr): Wordexposes the same auto-add behavior at werkmap level for callers who need ifmt indices in non-pivot contexts. Empty FormatStr short-circuits to index 0 ('General'). - Caller usage.
df := pivot.AddDataFieldByName('Revenue', xlpaSum); Sheet.PivotSetDataFieldFormat(df, '$#,##0.00'); df := pivot.AddDataFieldByName('GrowthPct', xlpaAverage); Sheet.PivotSetDataFieldFormat(df, '0.00%');
Versie 2.80.1
- Icon Set conditional formats rondreis cleanly through HotXLS opslaan/openen. The v2.49.0 audit changed the CF12 writer to emit
ct=$06for Icon Set rules per [MS-XLS] §2.4.43 (the spec-correct value;$05is reserved for Filter rules), but the matching reader path still only recognised the legacy$05value. As a result, .xls files written by HotXLS v2.49.0..v2.80.0 lost their Icon Set rules on reload — the rule kind degraded to a plain cel-is rule and the icon-set type / Reverse / ShowOnly flags reset to defaults. The reader now accepts both$05(legacy HotXLS pre-v2.49.0) and$06(spec / v2.49.0+) so werkmappen from either generation re-openen cleanly.
Versie 2.80.0
- Programmatic pivot tabel creation API (wave H3). New
IXLSWorksheet.AddPivotTable(SourceRangeA1, DestRow, DestCol, Name): TXLSPivotTablemethode walks the supplied source bereik, infers each column's data type from the cel values, auto-builds aTXLSPivotCache(or reuses an existing one bound to the same bereik), and creates a typed pivot tabel on the destination sheet with one TXLSPivotField per cache field (axes initially unset). - Caller wires axes / data via convenience methoden.
pivot.AddRowField('Region'),pivot.AddColumnField('Quarter'),pivot.AddPageField('Year'),pivot.AddDataFieldByName('Revenue', xlpaSum).SetFieldAxis+AddDataFieldare exposed for finer control. Field axis enum: xlpfaRowField / xlpfaColumnField / xlpfaPageField / xlpfaDataField / xlpfaNone. Eleven aggregation functions: Sum, Count, Average, Max, Min, Product, CountNums, StdDev, StdDevP, Var, VarP. - Typed writer emits SX* records + cache substream. When
pivot.FromRawBlobs = False(the default for programmatically created tabellen), the writer serialises the typed model into SXView ($00B0) + SXVD ($00B1) per field + SXVI ($00B2) per item + SXIVD ($00B4) row/col index arrays + SXDI ($00C5) per data field + SXEx ($00C6) into the werkblad footer. The matching pivot cache (cache.FromRawBlobs = False) emits a fresh BOF (dt=$0006) + SXDB ($00C6) header + SXFDB ($00C8) + SXFDBType ($00FB) + per-item SXSTRING / SXNUM / SXBOOLEAN / SXERR / SXDATETIME / SXEMPTY + EOF substream appended after the werkblad bodies. - rondreis safety preserved. Pivot tabellen and caches lezen from disk keep their wave H1
FromRawBlobs = Trueflag and continue to rondreis via the raw-byte path. Only the new programmatically created pivots flow through the typed writer. Mixed werkmappen (one round-tripped pivot + one new pivot via AddPivotTable) emit both paths cleanly. - Wave H3 limitations. Source bereik types other than rectangular A1 (named bereiken, external werkmap refs) are out of scope. SXLI / SXPI (line items / page items) are not emitted for typed pivots — Excel computes them on openen. Formatting customisation (data field number format beyond per-field NumberFormat) is exposed as a field but the writer treats it as 0 (general). Multiple pivots sharing a cache are supported but caller must wire the same source bereik string each time.
Versie 2.70.0
- Pivot tabel typed lezen model (wave H2). Building on the wave H1 raw-byte preservation, the reader now also populates a typed object model so callers can introspect pivot tabel structure without bytecode parsing. New types —
TXLSPivotTable,TXLSPivotField,TXLSPivotItem,TXLSPivotDataField,TXLSPivotCache,TXLSPivotCacheField,TXLSPivotCacheItem,TXLSPivotCaches,TXLSPivotTables— surface via the newIXLSWorksheet.PivotTablesandTXLSWorkbook.PivotCacheseigenschappen. - What the model captures. Per pivot tabel: position (FirstRow / Col / LastRow / Col / FirstDataRow / FirstDataCol), Name, DataCaption, CacheId, and an ordered list of
Fields(each with Name, Axis ∈ {xlpfaRowField,xlpfaColumnField,xlpfaPageField,xlpfaDataField,xlpfaNone}, Items[], SubtotalMask, CacheFieldIndex). Data axis emits a parallelDataFieldslist, each carrying anAggregationfrom the 11-valueTXLSPivotAggregationenum (xlpaSum / Count / Average / Max / Min / Product / CountNums / StdDev / StdDevP / Var / VarP). - Cache model. Each
TXLSPivotCacheholds CacheId, SourceRange (Sheet + 0-based row/col bounds), RecordCount, and a list ofFields. Each cache field carries its data type (xlpcftNumber / String / Boolean / Error / Empty / DateTime / Mixed), Name, NumberFormat index, and the unique-value Items[]. Per-record indices into each field's Items[] are exposed viaCache.RecordIndices[Record, Field]for programmatically-built caches; round-tripped caches lezen from disk leave per-record indices unpopulated and rely on the raw-byte path for fidelity. - rondreis safety. Pivot tabellen that came from raw bytes have
FromRawBlobs = True— the writer continues to replay the wave H1 raw blobs verbatim. The typed model is populated as a best-effort projection for caller introspection. The typed-model writer that produces wire bytes from the model is scoped to wave H3 (programmatic AddPivotTable API). - New lxPivot.pas unit. All pivot types live in their own unit alongside lxChart / lxFormula / lxNames. lxHandle re-exporteert the public types so existing imports keep working.
Versie 2.69.0
- Pivot tabel rondreis preservation (wave H1). HotXLS now keeps every record that makes up a pivot tabel when an Excel-created .xls travels through openen → opslaan. Before this release, the reader silently dropped unrecognised SX* records (SXView, SXVD, SXVI, SXIVD, SXLI, SXPI, SXDI, SXAddl, etc.) and skipped the entire Pivot Cache substream, so re-saving an Excel pivot file left Excel with broken pivot tabellen on next openen. The reader now captures all of these as opaque bytes and the writer replays them verbatim, so the pivot tabel on the cover sheet still renders correctly in Excel after a opslaan / reload cycle.
- werkblad PIVOTVIEW block. SX* view records ($00B0–$00B2, $00B4–$00B6, $00C5–$00C8, $00D0–$00D2, $00D5, $00E3, $00F0, $00FB, $0100, $0864) are captured in stream order and emitted in the writer's per-sheet footer (between the tabellen block and the trailing EOF), matching the [MS-XLS] §2.1.7.20.1 werkblad ABNF position for PIVOTVIEW. Oversize SXAddl payloads ride through the existing Continue ($003C) splitter the same way HFPicture does.
- Pivot Cache substreams. BOF (dt=$0006) followed by SXDB / SXFDB / SXFDBType / SXSTRING / SXNUM / SXBOOLEAN / SXERR records up to the matching EOF is captured as one cache bucket; multiple caches in the same werkmap each get their own bucket. On opslaan the writer rebuilds the full BOF / records / EOF substream for each captured cache and appends them to the werkmap OLE stream after the per-sheet bodies, where [MS-XLS] §2.1.7.20 expects them.
- Scope: raw-byte preservation only (H1). Wave H1 deliberately does not parse pivot data into a typed model — TXLSPivotTable / TXLSPivotField / TXLSPivotCache and a programmatic AddPivotTable API are scoped to future waves H2 / H3. Until then HotXLS callers can't introspect or modify pivot tabel structure, but the existing Excel-built pivot tabellen rondreis through HotXLS without loss.
Versie 2.68.0
- Chart backlog wave F sub-feature 3: Series error bars.
TXLSChartSeriesInfogrew anErrorBars: array of TXLSChartErrorBarsInfofield. Each entry produces a SerErrBar record ([MS-XLS] §2.4.105, $105B) inside the parent Series block, after Trendlines and before the Series End, in caller order. A typical column chart with Y error bars uses two entries (Sertm=1 Y+ and Sertm=2 Y-); scatter / bubble charts add X+/X- pairs (Sertm=3 / 4). - Five value sources.
Ebsrcselects 1=percent, 2=fixed value, 3=stddev, 4=stderr, 5=aangepaste.NumValuecarries the magnitude (10.0 = 10% when Ebsrc=1, raw scalar for fixed value, multiplier for stddev). For aangepaste (Ebsrc=5) theCnumfield carries the count of aangepaste data points; spec says MUST=0 for the other sources, so the builder forces non-aangepaste entries to Cnum=0 regardless of caller input. - T-cap rendering toggle.
FTeeTopcontrols whether Excel renders T-shaped caps on the bar ends (Excel's visual default = on). Useful when caller wants the more minimal "tick-only" stijl. - aangepaste value series (Ebsrc=5) caveat. The minimal builder emits the SerErrBar record with the chosen Cnum but does not yet emit the supporting BRAI cluster that points at the aangepaste value array. aangepaste error bars therefore render with default magnitude until a future phase wires up the BRAI follower. Percent / fixed / stddev / stderr (Ebsrc 1..4) are fully functional in this release.
Versie 2.67.0
- Chart backlog wave F sub-feature 2: Series trendlines.
TXLSChartSeriesInfogrew aTrendlines: array of TXLSChartTrendlineInfofield. Each entry produces a Trendline record ([MS-XLS] §2.4.328, $2050) inside the parent Series block, after SerToCrt and before the Series End, in caller order. Multiple trendlines on a single series are legal and Excel renders them all. - Six regression types.
Regtselects 0=polynomial, 1=exponential, 2=logarithmic, 3=power, 4=moving-average, 5=linear. For polynomial theNOrderfield sets the degree (2..6); for moving-average it sets the period (2..N). For the other typesNOrderis ignored but spec requires 1..6, so the builder defaults zero/out-of-bereik values to 1 / 6 respectively. - Equation and R² display + forecasting.
FDispEq/FDispRSqrtoggle the on-chart equation and R² labels.NumForecast/NumBackcastset the forward / backward extrapolation periods (Double, ≥ 0).NumInterceptsets the y-intercept; pass NaN ($7FF8000000000000) for "automatic". - Trendline label as inline LPWideString. The
Namefield is written into the Trendline record's sName slot ([MS-XLS] XLUnicodeString: cch:2 + grbit:1 + UTF-16 body). Empty Name leaves Excel to auto-generate a legend entry like "Linear (Series1)". - AddSeries internal refactor. The internal
AddSerieshulp now takes a singleTPreparedSeriesInforather than the previous (Name, CatArea, ValArea) triple, so future Series-attached records (next phase: error bars) can flow through one parameter without further signature churn.
Versie 2.66.0
- Chart backlog wave F sub-feature 1: 3D chart types. Programmatically built chart sheets kan nu request
xlsChartType3DColumn,xlsChartType3DBar,xlsChartType3DLine, orxlsChartType3DPieviaAddChartSheet(Name, ChartType, ...). The 3D variants reuse the same on-the-wire BARCHART / LINECHART / PIECHART chart-type record as the 2D variants but the surrounding CHARTFORMAT block now also emits a Chart3d record per [MS-XLS] §2.4.46 to switch Excel into its 3D rendering pipeline. - Default 3D geometry mirrors Excel's "Insert > 3D Column". 20° rotation, 15° elevation, perspective off, cluster on, autoscale on, height and depth both 100% of width, gap 150%. Walls and right-angle axes match Excel's default. The geometry is hard-coded for now (no caller knob); the next phase can promote it to a record-stijl override.
- Chart3DBarShape ($105F) restored conditionally. v2.55.0 removed the unconditional Chart3DBarShape emission because [MS-XLS] §2.4.47 mandates "MUST be ignored if the current substream does not contain a Chart3d record" and 2D charts don't have one. Wave F restores it for 3D Bar / 3D Column only (riser=rectangle, taper=none), emitted adjacent to Chart3d inside CHARTFORMAT so the spec relationship is visible from the wire layout. 3D Line and 3D Pie still skip it (no riser/taper concept).
- 3D Pie skips both axes. The axes-used count and axis emission paths now treat
xlsChartType3DPiethe same asxlsChartTypePie— axes-used = 0, no category / value axis emitted. Without this gate Excel rendered a 3D pie with stray axis lines bleeding through the chart.
Versie 2.65.0
- formule array constants rondreis with their data.
PtgArraytokens ($20 / $40 / $60 — V / R / A class) in formule streams now carry theirPtgExtraArraypayload through both lezen and schrijven paths.SUM({1,2,3}),=MMULT(...),{=COUNTIF(...)}and other array-literal formules behouden the literal values in.xlsfiles written by HotXLS instead of round-tripping with empty rgcb sections. - Array data hangs off the syntax tree.
TXLSSyntaxItemgrewArrayCols/ArrayRows/ArrayValueseigenschappen (with the matchingTXLSArraySerValrecord describing num / str / bool / err / empty cellen per [MS-XLS] §2.5.198.122 SerAr). Tools that walk the syntax tree can introspect array constants directly without needing the separate external-data container. - Programmatic array-literal construction. Code that builds
TXLSSyntaxItemtrees via the API can populateSA_ARRAYitems withSetArrayDimensions+ArrayValues[i]and HotXLS emits the matching PtgExtraArray in the rgcb section automatically. The wire ordering matches the [MS-XLS] §2.5.198.59 rule that PtgExtraArray entries are sequenced by the position of their PtgArray token in the rgce stream. - Existing lezen path stays correct for mixed rgcb. The new code only consumes PtgExtraArray entries that correspond to PtgArray tokens it parsed; any other extra data (e.g. PtgExtraMem from PtgMemArea / PtgMemFunc, still unsupported) is left alone for downstream handling, and a malformed rgcb falls back to leaving array values empty rather than discarding the parsed tree.
Versie 2.64.0
- Chart backlog wave D phase 7: drawing theme color get / set rondreis within a process. Phase 5 introduced
XlsApplyThemeColorToDrawingas a set-only hulp because BIFF8 OfficeArt is a pre-Office-2007 binary format with no theme color slot on disk. The setter still down-casts to RGB for the on-disk OfficeArt opt blob, but the werkmap now also keeps an in-memory side-tabel that remembers the original theme idx + tint per(TMsoShapeContainer, OfficeArt property id)pair. A newXlsGetDrawingThemeColorreader consults that side-tabel so the same process can pull back the theme intent it just wrote — useful for in-app render code that wants to highlight theme-driven colors or expose them in eigenschap panes. After opslaan / openen the side-tabel starts empty again and the getter returns False, falling through toColorFormat.RGB. - New caller API.
XlsGetDrawingThemeColor(ColorFormat, Workbook, out ThemeIdx, out Tint): Booleanjoins the existingXlsApplyThemeColorToDrawing. The setter signature is unchanged; it now also records the entry intoTXLSWorkbook.FDrawingThemeColors(a dynamic array of records keyed by container pointer + eigenschap id). SubsequentXlsApplyThemeColorToDrawingcalls on the same slot overwrite the entry, so the tabel tracks the latest intent rather than accumulating history. - Stable identity through new internal eigenschappen.
TXLSColorFormatgrew lezen-only_Containerand_Pidaccessors so the hulpen can compose the side-tabel key without the caller fishing private fields out of the class. Underscore prefix marks them as the same internal-API tier as_StringTable/_XFList/_BiffTheme: stable enough for library glue code, not part of the public contract. - Why this is "single-process rondreis" only. The BIFF8 OfficeArt format only stores indexed / RGB / scheme / sysColor in its 4-byte ColorRef; there's no extension record analogous to XFExt $087D where the theme idx + tint could live. So the disk rondreis cap is structural, not a HotXLS gap. The Phase 7 side-tabel bridges the in-process gap so app-internal code can pretend the format ondersteunt theme colors as long as it lives within one werkmap session.
Versie 2.63.0
- Chart backlog wave D phase 6: compound border selectors rondreis RGB / theme through XFExt. The last theme-color known-limit is closed:
Border[xlAround],Border[xlInsideVertical],Border[xlInsideHorizontal], andBorder[xlInsideAll]now register the same RGB or theme color against every physical edge slot they target instead of falling back to the indexed-palette path. The newTXLSXfRichSlotSet(set ofTXLSXfRichSlotID) lifts the pending-rich stash from a single slot to a set, so one cel-loop pass onSetRangeXFBordersPropertyregisters up to four XFExt slots in one go. - Compound selector mapping. The new
BorderEdgeSlotSet(BorderIndex): TXLSXfRichSlotSethulp centralises the selector → slot translation:xlEdgeLeft / Right / Top / Bottom→ singleton sets (unchanged from phase 2).xlDiagonalDown / Up→[rsDiag](BIFF8 FullColorExt only carries a single diagonal color).xlAround→[rsTop, rsBottom, rsLeft, rsRight](outer border).xlInsideVertical→[rsLeft, rsRight](cel-to-cel vertical separators).xlInsideHorizontal→[rsTop, rsBottom](horizontal separators).xlInsideAll→[rsTop, rsBottom, rsLeft, rsRight].
Border.SetColorandBorder.SetThemeColorshare the same mapping, so RGB and theme paths behave identically across all selectors. - TXLSBorders.SetColor restored to a single dispatch. Phase 2 had to fan
Borders.Color := Vout to four per-edgeGetBorder(edge).Color := Vcalls because the pending-rich stash only carried one slot at a time. With the set form,Borders.SetColornow stashes the full{rsTop, rsBottom, rsLeft, rsRight}set and callsSetColorIndexonce —SetBordersColorIndextakes the optimal wire path (single cellen loop with BorderMask=15), andConsumePendingRichSlotregisters all four XFExt slots on each touched XF in the same pass. ~4x fewer cel-loop iterations than the phase-2 fan-out, byte-identical XFExt result. - ConsumePendingRichSlot iterates the set. The slot-registration loop walks the eight enum members and dispatches each one present in
FPendingRichSlotthroughRegisterXFExtSlot. Boundary cellen whose XF didn't actually change during a compound-selector update still fire the callback — that's harmless because the XFExt slot is only visually relevant when the cel genuinely has the matching border line, and the indexed wire is set by the per-celBorderMaskExcel already understands.
Versie 2.62.0
- Chart backlog wave D phase 5: aangepaste theme XML rondreis + drawing theme hulp. Three pieces close the last theme-color gaps that phase 4 left openen. aangepaste theme palettes set in Excel via Page Layout → Colors now survive the load cycle: the parser walks the OOXML
<a:clrScheme>embedded in the BIFF8$0892Theme record and updates the werkmap's 12-slotFBiffThemein place. The matching writer emits the same record when the palette has drifted from the default Office scheme, so caller-customised themes rondreis through HotXLS without falling back to defaults. A newXlsApplyThemeColorToDrawinghulp lets chart / shape callers address drawing colors with the same theme idx + tint vocabulary that cellen already use. - Reader: OOXML theme XML parsing.
ParseThemestitches the record body (frtRefHeaderU + dwThemeVersion + variable-length XML payload, may span Continue records) into a single byte buffer and runs a targeted substring scan for the twelve<a:clrScheme>children (dk1, lt1, dk2, lt2, accent1..6, hlink, folHlink). For each slot it prefers<a:srgbClr val="RRGGBB"/>and falls back to<a:sysClr ... lastClr="RRGGBB"/>, then convertsRRGGBBto the HotXLS COLORREF layout and callsFBiffTheme.SetThemeRGBColor. Bodies that don't look like OOXML (missing<a:clrScheme>sentinel, ZIP-compressed variants, etc.) leave the palette at its default scheme so common renderings stay correct. - Writer: Theme record emission with skip-when-default.
TXLSWorkbook.StoreThemeemits a$0892record only whenIsBiffThemeDefaultreports the palette has drifted from the Office default scheme. The OOXML body is built from a deterministic template: twelve<a:srgbClr>entries (chosen over the Excel-native sysClr form for dk1/lt1 because it round-trips through the same parser without needing a sysColor name resolver), plus the minimal legal<a:fontScheme>/<a:fmtScheme>stanzas the schema requires. Untouched werkmappen emit no record and stay byte-compatible with pre-Phase-5 output. - Drawing theme color hulp. The new free function
XlsApplyThemeColorToDrawing(ColorFormat, Workbook, ThemeIdx, Tint)resolves a theme idx + tint through the werkmap palette and schrijft the resulting RGB onto aTXLSColorFormat(shape fill / line / chart color). BIFF8 OfficeArt is a pre-Office-2007 binary format with no native theme color encoding, so this is set-only: lezen-back returns the resolved RGB rather than the theme slot, and the rondreis theme reference is lost on disk. For full theme rondreis useIXLSInterior.SetThemeColor/IXLSFont.SetThemeColor/IXLSBorder.SetThemeColoron cellen, which leverage XFExt $087D. - Wave D fully closed in five phases. Phase 1 (v2.58.1) toegevoegd the case-tabel acknowledgement, Phase 2 (v2.59.0) wrote XFExt for RGB cel colors, Phase 3 (v2.60.0) closed the RGB reader loop, Phase 4 (v2.61.0) shipped the theme color path on cellen, and Phase 5 (this) completes the picture with aangepaste theme XML rondreis plus the drawing-side hulp. cellen now match Excel's rendering pixel-for-pixel when round-tripping any combination of palette / RGB / theme colors that the BIFF8 spec can express; drawings carry the visual intent forward through the hulp but pay the OfficeArt format's RGB-only price on lezen-back.
Versie 2.61.0
- Chart backlog wave D phase 4: BIFF8 theme color ondersteuning (theme idx + tint via XFExt $087D). Office's 12-slot theme palette (lt1, dk1, lt2, dk2, accent1..6, hlink, foHlink) now round-trips on the .xls side: callers can address theme colors directly with the new
Interior.SetThemeColor(themeIdx, tint)/Interior.SetPatternThemeColor/Font.SetThemeColor/ per-edgeBorder.SetThemeColorAPIs, and the cel color getters resolve the same theme idx + tint back through the werkmap's BIFF theme palette when reading. The XF record still receives a best-match indexed icv (so legacy readers like Excel 2003 keep rendering an approximate color), while Excel 2007+ recovers the exact theme intent through the XFExt FullColorExt (xclrType=3) future-extension record — same backward-compatibiliteit trick Microsoft uses when "opslaan As" downgrades a theme-styled .xlsx to .xls. - New caller API. Five new
SetThemeColorentry points join the existing RGB / index setters:IXLSInterior.SetThemeColor(ThemeIdx, Tint),IXLSInterior.SetPatternThemeColor(ThemeIdx, Tint),IXLSFont.SetThemeColor(ThemeIdx, Tint), andIXLSBorder.SetThemeColor(ThemeIdx, Tint)on each border edge.ThemeIdxis the 0-based theme slot (0=lt1, 1=dk1, 2=lt2, 3=dk2, 4..9=accent1..6, 10=hlink, 11=foHlink);Tintis the spec-stijl -1.0..+1.0 lighter/darker adjustment that gets encoded into FullColorExt.nTintShade as Q15 signed integer. - werkmap BIFF theme palette.
TXLSWorkbooknow carries anFBiffTheme: TXLSThemeColorsinitialised to the default Office theme scheme that the XLSX side has used for years throughTXLSColorManager.FTheme. cel color getters resolve theme idx + tint through this palette viaGetThemeRGBColor(idx, tint)(which already applies HSL-based tint adjustment inlxRgb.GetRGBTInt). Internal_BiffThemeeigenschap exposes the palette for parser-side updates. - Theme record ($0892) acknowledged on lezen.
lxRead.ParseThemetakes$0892out of the default-skip path so the werkmap-globals case tabel treats it as a known record. The embedded OOXML theme XML body itself is left unparsed for now — the 12 default Office theme colors already match the most common source and Excel-set theme cellen render correctly through them. werkmappen with a fully customised theme will surface theme cellen through the default palette here (documented known limit; XML-based theme parsing is a follow-up wave). - Why no Theme record on schrijven. HotXLS-saved .xls files don't emit a Theme record. Excel 2007+ falls back to the default Office theme when no $0892 is present, which exactly matches HotXLS's
FBiffThemedefault scheme, so cellen usingSetThemeColorrender with the right color in Excel without us having to ship the embedded XML. Files therefore stay smaller and the writer side has no XML-emit dependency.
Versie 2.60.0
- Chart backlog wave D phase 3: XFExt ($087D) lezen-side RGB / theme recovery closes the rondreis. The Phase 1 acknowledgement and Phase 2 emitter are now joined by a parser that actually consumes each
$087Drecord into the werkmap XF rich-color side-tabel. Files saved by Excel with RGB cel colors (fill, font, individual borders) now surface throughcell.Interior.Color/Interior.PatternColor/Font.Color/ per-edgeBorder.Colorat the exact RGB Excel wrote, instead of the indexed-palette approximation HotXLS used to return for the same cellen. Wave D is now fully closed in both directions. - Reader:
ParseXFExtwalks ixfe + cexts + rgExt. The parser handles the eight color ExtProp extTypes ($0004 fillFg, $0005 fillBg, $000D font, $0007/$0008/$0009/$000A/$000B for top / bottom / left / right / diagonal borders) and decodes each one's FullColorExt body (xclrType, nTintShade as signed Q15, xclrValue). xclrType 2 (RGB) and 3 (theme) get registered on the werkmap side-tabel against the record'sixfe; other extTypes ($0006 FillGradient, $000E FontScheme, $000F TextIndent) skip cleanly so a future wave can add them without disturbing this code path. Defensive bounds checks oncbmean a malformed record terminates parsing of its tail without reading past the declared length. - cel color getters consult the side-tabel first. The eight color getters that previously routed straight through the indexed-palette path (
GetCustomColor(GetColorIndex)) now resolve their XF index, queryTlxFormatList.TryGetRichSlotfor the matching rich-color slot, and applynTintShadevia the existingGetRGBTInthulp when the slot carries an RGB value. xclrType=3 (theme) falls through to the indexed path: the BIFF werkmap has no theme model on this call chain, so the palette approximation remains the best available answer for theme cellen. cellen whose XF was never touched by a Phase 2 setter or a parsed XFExt produce the same byte-identical lezen result as before. - Wave D is closed. opslaan behoudt caller-set RGB (Phase 2). Load behoudt Excel-set RGB (Phase 3). werkmappen with no rich color information emit the same byte stream as before. The only remaining caveats stay documented as known limits: theme colors still down-grade through the BIFF palette because there is no theme color manager on this side of the codebase, and compound border selectors (
xlAround/xlInside*) tag a single ambiguous side-tabel slot rather than per-edge — both rare enough to leave for a future wave.
Versie 2.59.0
- Chart backlog wave D phase 2: XFExt ($087D) emission for BIFF8 cel colors. When application code sets
cell.Interior.Color := $00FF6633(or any other RGB) on the BIFF8 path, the writer now emits a$087DXFExt record alongside the indexed-palette XF entry so Excel reopens the werkmap with the exact RGB the caller passed in, rather than the closest 56-color palette approximation HotXLS used to fall back to. Covers all four cel color surfaces:Interior.Color/Interior.PatternColor/Font.Color/ per-edgeBorder.Color(top / bottom / left / right / diagonal) and the convenienceBorders.Colorwhich now distributes to the four primary edges so each gets its own XFExt slot. - How the rondreis stays safe. The BIFF8 cel setter chain still produces the indexed-palette XF wire output it always did — readers (HotXLS or anything else) that ignore
$087Dsee the legacy approximation. The XFExt record sits next to the XF and carries the original RGB as a 16-byte FullColorExt (xclrType=2, xclrValue=$00BBGGRR, nTintShade=0) wrapped in an ExtProp with the spec-correct extType for each slot ($0004 fillFg, $0005 fillBg, $000D font, $0007/$0008/$0009/$000A/$000B for top/bottom/left/right/diagonal borders). cellen that never took the color-setter path still emit no XFExt — werkmappen with no rich colors produce the same byte stream as before. - Storage and bookkeeping. A new per-XF rich-color side-tabel in
TlxFormatListholds the original RGB / theme info the cel setter passed in, keyed by the werkmap's hash-resolved XF index.TXLSRange.SetXFProperty/SetRangeXFBordersPropertygrew an optionalOnNewIndexcallback so the cel setter can register the rich color against every XF index the cel ends up on (multi-cel bereiken that hash to multiple distinct XFs all get tagged). The side-tabel is consulted inStoreWorkbookright after stijlen and before PALETTE, matching the*XFExtposition in [MS-XLS] §2.1.7.20.3 werkmap Globals ABNF. xlExcel5 output is untouched (BIFF5 has no XFExt record). - Known limit. The reader side stays at the wave-D-phase-1 acknowledgement:
ParseXFExtconsumes$087Drecords from the input stream but does not yet feed the recovered RGB back into the werkmap's stijl objects, because doing so in the hash-keyed stijl model risks invalidating existing XF entries. Files saved by HotXLS now look correct in Excel; files coming in from Excel still surface the indexed-palette approximation when lezen back throughcell.Interior.Color. Closing that lezen-side gap is a separate follow-up (Phase 3) that requires reworking the stijl hash to admit per-XF rich color before the first hash anchor.
Versie 2.58.1
- Chart backlog wave D (lezen-side acknowledgement only): XFExt ($087D) no longer routed through the default-skip path. A new
ParseXFExtbranch in the BIFF8 werkmap-globals case tabel consumes$087Drecords that Excel schrijft alongside RGB and theme-colored cel stijlen. The reader still leaves the indexed-color XF record unchanged — full RGB / theme precision recovery onto the werkmap's hash-key stijl model is deferred to a separate wave because it would require the BIFF writer-side stijl classes to grow an RGB / theme color field that doesn't exist today. Files coming from Excel with rich colors continue to load with the indexed approximation HotXLS has always produced, but the spec-conformance gap of "treating$087Das unknown" is closed. - Why not the full wave-D scope. The plan envisioned a paired schrijven + lezen implementation, but exploration found that the BIFF schrijven pipeline (
TXLSWorkbook.FXFList: TlxFormatList) encodes XF stijl data as a string-key with hex-packed indexed color slots and has no analogue of the XLSX-sideTXLSStyleColor(which carriesColorType/ColorValue/TintAndShade). Adding XFExt emission would mean either bridging the two stijl models or extendingTlxFormatListwith per-XF rich color side-tabellen, both of which are larger refactors than a single wave can absorb. The change here therefore stays surgical: lxRead recognises the record, lxStyleXf and lxHandle are unchanged.
Versie 2.58.0
- Chart backlog wave C: SST rich-text and phonetic rondreis (BIFF8 XLUnicodeRichExtendedString). Rich-text formatting set in Excel (a cel whose individual characters carry their own font / color, the "two colors in one cel" effect from the Format cellen dialog) sits in the shared string tabel as an
XLUnicodeRichExtendedStringwith an attachedrgRunFormatRun array. Far-East phonetic info (the furigana / hiragana annotation above kanji) attaches as anrgExtRstblock on the same record. HotXLS previously dropped both on load and re-emitted the string as plain text on opslaan, so opening then resaving a werkmap flattened every multi-format cel to a single font / color. The shared-string parser behoudt nu both trailing blocks per unique string, and the writer re-attaches them when the string fits a single SST record. - Reader walks Continue boundaries without re-reading flag bytes. A new
CollectRawTailhulp insideParseSSTpulls the rawrgRunbytes (cRun × 4 bytes per FormatRun) followed by the rawrgExtRstbytes, spilling across Continue ($003C) records as needed — neither block is re-prefixed with the string’s flag byte at a Continue boundary per [MS-XLS] §2.4.58, which the old per-byte skip logic could not behouden correctly whenrtorszovershot the current record. The preserved tails are registered against the werkmap SST through the newTXLSStringTable.AddWithExtras, which deliberately does not bump the cel-reference counter so subsequentLabelSSTparsing still produces correctcstTotalon opslaan. - Writer attaches fRichSt / fExtSt + cRun / cbExtRst + rgRun + rgExtRst when the whole record fits in one BIFF chunk.
AddSSTItemnow factors the rich / phonetic tail size into its overflow check; strings whose body + tails fit a single 8224-byte SST chunk emit the full preserved layout, and Excel re-opens the werkmap with the original formatting intact. Strings that overflow fall back to plain text without formatting (the splitter would otherwise need to interleave Continue flag bytes with the still-running rgRun byte stream, a state machine the current writer doesn't have); this is the explicit known limitation documented in the wave-C plan and affects only very long rich-formatted strings (> ~4000 wide chars). - Continue flag byte corner case fix (carried over from the v2.54.0 SST audit). Per [MS-XLS] §2.4.58 the leading flag byte of an SST Continue record carries only the
fHighBytebit (bit 0); bitsfExtSt(bit 2) andfRichSt(bit 3) MUST be ignored because those structures exist exactly once at the head of the first record.ParseSSTnow masks the Continue flag byte with$01, preventing a stray high bit from making the reader skip ahead 2 or 4 bytes looking for cRun / cbExtRst fields that aren’t there and misaligning every byte that follows.
Versie 2.57.0
- Chart backlog wave G: Header / Footer pictures survive the rondreis (BIFF8 HFPicture). When Excel saves a werkblad with a header or footer background image (Insert → Header & Footer → Picture, then the company logo stijl), the picture sits in an
HFPicture($086C) record that embeds an OfficeArt BLIP. HotXLS previously had no case branch for this record so the entire payload was dropped on load; saving the werkmap again therefore lost the header/footer image. The reader behoudt nu the full record body (every Continue chunk concatenated) per sheet, and the writer re-emits it in the spec-correct position so Excel reopens the file with the original images intact. - Reader concatenates all Continue chunks before storing the payload. The new
ParseHFPicturebranch inParseWorksheetRecordwalks every entry of the collatedDataList(the $086C body in slot 0 plus any number of $003C bodies that follow) and stores the joined bytes as a singleTByteson the werkblad. A sheet may carry several entries — up to six in Excel's UI (default / first / even pages × left / center / right) — so the storage is an array rather than a single field. - Writer emits HFPicture records right after PageSetup, then lets the existing Continue splitter handle the BLIP overflow. A new
StoreHFPicturesstep inserts itself into the per-sheet store sequence immediately afterStoreSetup, matching the*HFPictureposition in [MS-XLS] §2.1.7.20.2 werkblad ABNF. Each preserved body is wrapped in a fresh $086C header and routed throughAppendData— the existingAddContinuehulp takes over when the BLIP exceeds the 8224-byte BIFF limit, so a 30-50 KB JPEG ends up spread across one $086C plus four to six $003C records exactly the way Excel schrijft it. - No new public API surface. Wave G is a rondreis preservation feature; HFPicture content is opaque to application code (no caller-facing setter to inject a new header image). werkmappen that never carried an HFPicture record produce byte-identical output as before. The internal hulp
TXLSWorksheet._AddHFPictureBlobis reserved for the reader; the underscore prefix flags it the same way as_Drawing/_Autofilter.
Versie 2.56.0
- Chart backlog wave B: werkblad tab color rondreis (BIFF8 SheetExt). Sheet tab colors set in Excel via right-click Tab Color are now both readable and writable through the BIFF8 path.
TXLSWorksheet.TabColoris a new public eigenschap that takes a HotXLSLongWordcolor (low byte=R, mid=G, high=B, top byte=0, same convention asFont.Color/Interior.Color); the default value0means "automatic / no tab color" and suppresses the record entirely. - Writer emits a per-sheet
SheetExt($0862) record. One 48-byte record is appended to the werkmap globals stream just before EOF for every sheet whoseTabColoris non-zero. Layout follows [MS-XLS] §2.4.282 SheetExt v1 + §2.5.108 FullColorExt: the 12-bytefrtRefHeaderU+ 4-bytecb+ 4-byte reservedflagsTab1+ 16-byte FullColorExt block (xclrType=2 RGB, nTintShade=0, xclrValue=tab color) + 4-byteiTabId(0-based stream order of the matching BoundSheet8) + 4-byte reservedflagsTab2.iTabIduses the same iteration order as the BoundSheet block so the two stay aligned across multi-sheet werkmappen. xlExcel5 output is untouched (no SheetExt record in BIFF5). - Reader restores the tab color on openen. A new
ParseSheetExtbranch inParseWorkbookRecord's case tabel leestiTabIdand the FullColorExt block and schrijft the resolved RGB value back toSheets[iTabId + 1].TabColor.xclrType=2(RGB) stores the raw value;xclrType=1(indexed icv) resolves through the werkmap palette (Colors[icv, 0]) so the application sees a concrete RGB regardless of how Excel happened to encode it;xclrType=0(auto) andxclrType=3(theme) leaveTabColorat its default0, matching the writer-side "no tab color" semantics. - rondreis example. Setting
Workbook.Sheets[1].TabColor := $00FF00(green: B=0, G=$FF, R=$00) before SaveAs to .xls produces a werkmap that opens in Excel with a green tab; saving that same werkmap back out and re-opening it returns the eigenschap to$00FF00. Files coming from Excel with one or more tab colors are now opened without losing the colors, instead of having every tab default to automatic.
Versie 2.55.1
- Restore main-branch build. Two pre-existing identifier errors that left HotXLS unable to compile on RAD Studio 12+ are now fixed. Both came in with earlier bug-fix releases but had no compile gate, so the regressions only surfaced when the next contributor tried to rebuild the package.
- Shared-formule multi-column writer no longer references a missing record field. The v2.50.0 SHRFMLA wire-format fix toegevoegd
Data.AddByte(Group.LastCol)inWriteShrfmlabut did not extendTXLSShrfmlaGroupwith the new field, so the package failed to compile with "Undeclared identifier: LastCol". The record now carriesLastColalongside the existingFirstCol, andCollectSharedFormulas.OpenGrouppopulates it with the group's anchor column. Behaviour on single-column shared-formule groups (the only kind the collector currently produces) is unchanged; the spec-correctcolLastbyte is now real instead of an alias ofcolFirst. - XLSX cel writer references
XlsxFloatToStrthrough a forward declaration. The v2.51.0 locale-safety fix introduced an XlsxFloatToStr call in the cel-value branch (line 2718) but the hulp is defined a few hundred lines below (line 2910). Without a forward declaration, Delphi's single-pass compiler reported "Undeclared identifier: XlsxFloatToStr". A forward declaration is now placed at the top oflxHandleX's implementation block so both the early call site and the existing definition compile cleanly.
Versie 2.55.0
- Chart backlog wave A: multi-series cache wiring + chart / axis title captions. Two long-standing chart-builder limitations are now fixed; both come from the v2.54.0 audit backlog. The first emit-side change is wire-format only (no API change); the second wires through existing
AddChartSheetTitle / CatAxisTitle / ValAxisTitle parameters that previously had no effect. - Per-series values cache, no longer truncated to Series[0]. [MS-XLS] §2.1.7.20.1 chart-sheet ABNF allows
*(SIIndex *NUMBER)— oneSIIndex(1) + N×NUMBERblock per series. The Phase-1 builder emitted only one cache block sized bySeries[0].ValArea, so any later series with a longer value bereik had its cache slots silently cut short. The builder now (a) computes the maximum point count across all series for theDIMENSIONSrow bereik, and (b) loops over every prepared series emitting an individualSIIndex(1)block whose NUMBER count matches that series'AreaPointCount(ValArea). Cache slots stay zero-valued (BRAIPtgArea3dreferences still resolve to the live source cellen at draw time); the change is purely about giving Excel's strict parser a complete cache footprint. - Chart Title / CatAxisTitle / ValAxisTitle captions are written through. The Phase-1 implementation accepted three Title parameters on
AddChartSheetoverloads and silently discarded them ("Junk := Length(...)" placeholder). They now emit a proper attached-label block —TEXT($1025) +POS+BRAI-literal-tStr +SeriesText($100D) +OBJECTLINK($1027) + End — at the spec-correct position just before theCHARTcontainer's End record per [MS-XLS] §2.1.7.20.1 CHARTTITLES ABNF.OBJECTLINK.wLinkObjuses 1 for chart title, 2 for value-axis title, 3 for category-axis title per [MS-XLS] §2.4.182. Callers passingTitle := 'Quarterly Sales'finally see "Quarterly Sales" rendered above the plot area in Excel.
Versie 2.54.1
- [MS-XLSX] cross-audit follow-up. Two targeted herstelt from the v2.52.0 audit’s "deferred" list. Both are user-observable; neither breaks existing call sites.
- Date cellen keep their date format when combined with any single non-numFmt stijl. A
TDateTimecel withFontIndex/FillIndex/BorderIndex/AlignmentIndex/ProtectionIndexset but no explicitNumberFormatIndexused to route through a single-dim cellXf whosenumFmtIdwas 0 (General), so Excel rendered the cel as a raw serial number (e.g.46038) instead of1/15/2026. The XLSX stijl engine now treats the implicit date as a virtual dim: any other styled dim promotes the cel into a composite cellXf that carriesnumFmtId=14alongside the real dim. Pure-date cellen with no other styling still route toXlsxXfIndexDateas before. New public surface:TXLSXWorkbook.RegisterCompositeXf/GetCompositeXfgain 7-arg overloads that accept an OOXML built-innumFmtIdoverride (the existing 6-arg signatures are unchanged and forward to the new variant with the override disabled). - Sheet names that violate Excel’s naming rules are auto-sanitised. Excel rejects sheet names that exceed 31 characters, contain
: \ / ? * [ ], start or end with a single quote, equal the reserved nameHistory(case-insensitive), or collide with another sheet name (case-insensitive). HotXLS used to pass the raw user input straight through, so calls likeWorkbook.Sheets.Add('Q1:Q2 Sales')produced a werkmap that failed to openen with the “The name you entered is not valid” dialog.TXLSXSheets.Addnow normalises the name via the newXlsxSanitizeSheetNamehulp (forbidden chars become_, surrounding single quotes drop, length caps at 31, empty / reserved fall back to'Sheet') and appends a' (2)'/' (3)'suffix on case-insensitive collisions. Idempotent on already-valid names, so sheets parsed out of conforming .xlsx files rondreis unchanged.
Versie 2.54.0
- Deep spec-audit round 2 against [MS-XLS] v20250520 / [MS-OFFCRYPTO] v20240820. Eight independent corner-case / wire-format defects found by eight parallel code-reviewer agents auditing werkblad shell records, SST/Continue edges, formule PTG depth, encryption padding, chart records, drawing/comment writer, and Pivot/tabel ondersteuning. Public API unchanged; existing code recompiles untouched.
- Comment Note record now spec-conformant. Two distinct herstelt in
TMsoDrawing.StoreNotes(per [MS-XLS] §2.4.179 Note): (1)idObjis now written as a Word (2 bytes) instead of a LongWord (4 bytes), correcting a 2-byte offset slide that misaligned every byte after idObj; (2) the previously absentstAuthorXLUnicodeString field is now serialized (cch + flags + UTF-16 body) fromFAuthorinstead of being replaced by a bareWord(0). Excel's strict reader terminates Note parsing atstAuthor, so omitting it corrupted comment metadata on rondreis even when Excel still opened the file. - Comment
Visibleeigenschap no longer inverts intent.TMSOShapeTextBox.GetVisible/SetVisiblereturned True whenfHiddenwas set and storedfHiddenwhen callers asked for the comment to be visible — the bit's meaning is the inverse ([MS-XLS] §2.4.179 grbit bit1: 1 = hidden). Callers usingComment.Visible := Truepreviously got hidden comments; now the eigenschap matches its name in both directions. - RC4 password derivation correct for 16-character or longer passwords. [MS-OFFCRYPTO] §2.3.6.1 stores the MD5 single-block message-length field as a 64-bit little-endian bit count in bytes 56–63. The previous reader (
lxDecryption) and writer (lxEncrypter) both wrote only the low byte viaSetByte, silently dropping the high byte for passwords of 16+ characters (length-in-bits ≥ 256). Long-password files now derive the same ValDigest on both sides; previously long passwords were rejected even when correct, and HotXLS-encrypted files with long passwords could not be re-opened. - formule
tFuncVartoken now masks thefCeFuncbit out of the function-name lookup. [MS-XLS] §2.5.198.63 splits the trailing Word intotab(15 low)+fCeFunc(1 high); the reader stored the full Word intoItem.IntValueas the hash-tabel key, so functions emitted with the user-prompt flag (macro/UDF callers) hashed to$8000 | iftaband produced an empty function name, killing the entire formule. Now masked with$7FFF. - Multiple FILEPASS records are now ignored after the first. [MS-XLS] §2.4.117 allows at most one FILEPASS; a hostile or malformed werkmap with a second FILEPASS used to free the live decrypter and re-derive a fresh keystream mid-stream, putting it out of sync with the data already consumed. Subsequent FILEPASS records are now silently dropped while encryption stays armed.
- PtgArray V-class opcode emitted correctly.
GetArrayData(aClass=0)previously fell through to the A-class opcode ($60); per [MS-XLS] §2.5.198.32 the opcode is$20for V-class,$40for R-class,$60for A-class.aClass=0now correctly maps to$20. - Chart3DBarShape no longer emitted on 2D charts. [MS-XLS] §2.4.47 specifies that Chart3DBarShape "MUST be ignored if the current substream does not contain a Chart3d record". HotXLS doesn't yet ondersteuning 3D chart types (no Chart3d record emitted), so writing an empty Chart3DBarShape inside every DataFormat block was both redundant and non-spec (the empty payload also failed the 2-byte riser+taper layout). The record is now omitted entirely.
- Audit backlog captured in
TechnicalNotes.md. Larger spec gaps surfaced by the round 2 audit (XFExt records not emitted, PtgArray constant data not serialized, Chart Title/CatAxisTitle/ValAxisTitle parameters dropped, per-series chart cache, Pivot tabel / QueryTable / DConn unsupported) are documented as known gaps for future feature work rather than silent omissions.
Versie 2.53.0
- OpenOffice excelfileformat.pdf cross-audit round 2. Three additional BIFF8 wire-format herstelt uncovered by re-running the spec sweep after v2.50.0, this time targeting modules the first pass had touched only lightly: the formule token decoder, the XF alignment byte, and the ROW outline-collapse boundary check. Public API unchanged.
- Macro-command formules with the user-prompt flag no longer corrupt the parser (§3.7.2 tFuncVar). The reader pulled the byte at offset+1 of a
tFuncVartoken straight into the argument count, but bits 6-0 ($7F) carry the argument count and bit 7 ($80) is the "user prompt for macro commands" flag. Any tFuncVar with the prompt bit set was lezen as 128 + N arguments, blowing the formule stack and yielding nil for the whole expression. The reader now masks with$7Fper spec. - JustifyLastLine alignment flag round-trips correctly (§5.115 XF). The XF BIFF8 body's alignment byte (offset 6) packs HorAlign + WrapText + VerAlign + JustifyLastLine. Previous code wrote three of those four fields but omitted bit 7 (
$80, JustifyLastLine). cellen withJustifyLastLine = Trueopslaan with the bit cleared, so the distributed / justified last-line rendering reverts to the Excel default after a opslaan / reopen. - Row 0 / row 65535 no longer mis-flagged as outline-group boundaries (§5.88 ROW). The fCollapsed (
$10) bit is set when a row's outline level differs from its neighbours. For the boundary rows the "neighbour" doesn't exist, butOutlineLevel[-1]andOutlineLevel[65536]returned the default level 1, which made every row 0 / row 65535 with an explicit outline level > 1 falsely register as a collapsed outline group edge. The check now treats absent neighbours as matching the row's own level so the transition fires only for genuine outline boundaries.
Versie 2.52.0
- [MS-XLSX] cross-audit — round 2. Three follow-up refinements to the XLSX writer after the v2.51.0 audit. Each item is independently grounded in an ECMA-376 or W3C XML clause; combined effect is better OOXML consumer interop and quieter validation output.
- cel strings with leading / trailing whitespace rondreis. The inline-string fallback in
XlsxFormatCellValueemitted<is><t>...</t></is>withoutxml:space="preserve"; XML 1.0 §3.3.3 normalization stripped the surrounding spaces on load, so a cel whose value was “ Pending ” came back as “Pending”. The SST, rich-text run, and comment-text paths already carried the attribute; the inline-string fallback now matches. - Every werkblad now carries a
<dimension>hint. ECMA-376 §18.3.1.35 marks the<dimension ref="..."/>element optional but every Excel-written .xlsx contains it; consumers that lezen it (Apache POI / NPOI / OOXML SDK) pre-size their cel buffers from the hint instead of growing dynamically. The writer now computes the bounding rectangle of populated cellen during the row-grouping pass and emits the element as the second child of<worksheet>(after<sheetPr>if present, before<sheetViews>). Empty werkbladen collapse to<dimension ref="A1"/>. <sst count="...">reports total cel references, not unique strings. ECMA-376 §18.4.8 definescountas the total reference count anduniqueCountas the distinct-string count; the writer used to emit both asFStrings.Count(always equal), misleading OOXML consumers about reference density.TXLSXSharedStringsnow tracks a separateRefCountthat increments on everyAdd/AddRichcall regardless of dedup, and the attribute reports the real reference total.
Versie 2.51.0
- [MS-XLSX] cross-audit pass. Five wire-format and locale-safety herstelt across the XLSX writer uncovered by validating against the Microsoft [MS-XLSX] — Excel (.xlsx) Extensions to the Office openen XML SpreadsheetML File Format documentatie (v20260108) and the underlying XML 1.0 / OOXML schema requirements. Public API is unchanged; existing applications recompile and re-opslaan without modification.
- Saved .xlsx files now openen on every Windows region. Page margins, column widths, row heights, font sizes, color tints, theme tints, aangepaste-font rich-text run sizes, and the
<v>-wrapped numeric value of every cel were being serialised through Delphi’s locale-awareFloatToStr. On Windows configured for a region whose decimal separator is ',' (most of continental Europe and parts of Asia / Latin America) the writer emitted attribute values likewidth="8,43"andtop="0,75", which the OOXML schema rejects — Excel surfaced “We found a problem with some content in <file>.xlsx” and offered a recovery pass that wiped page setup, column widths, and the numeric cel values. Every double-valued OOXML attribute now uses an invariant '.' separator regardless of the active region. The same fix also patches the in-memory column-width / row-height cache that previously stored locale-formatted strings;GetColWidth/GetRowHeightreturned0.0right after aSetColWidth/SetRowHeightcall on the same werkmap in those regions. - cellen containing control characters no longer break the werkmap. XML 1.0 §2.2 forbids ASCII codes 0x00–0x08, 0x0B, 0x0C, 0x0E–0x1F (and U+FFFE / U+FFFF) anywhere in an XML document — they cannot be encoded as numeric character references either. cel values that happened to contain those bytes (legacy data feeds, log dumps, escape-key sentinels) used to be written into
<t>...</t>verbatim, producing an .xlsx Excel refuses to openen with no path back to the data. The writer now silently strips the forbidden code points; valid whitespace (TAB / LF / CR) is preserved. - Newlines inside attribute values rondreis correctly. XML §3.3.3 normalises raw TAB / LF / CR inside an attribute value to a single space before handing the value to the application. Multi-line headers / footers, defined-name comments, multi-line data-validation prompts, hyperlink display strings, and any other attribute that carried a newline used to collapse to a single space on load.
XlsxEscapeAttrnow emits those characters as	/
/
numeric character references so Excel leest them back as the original whitespace. - <col> entries emitted in ascending column order. ECMA-376 18.3.1.4 / 18.3.1.13 expects every
<col min="..."/>entry to appear in ascendingminorder. The previous TStringList(Sorted=True) dedup sorted the integer column indices lexically ("10" before "2"), so a sheet that customised both column 2 and column 10 produced<col min="10"/>before<col min="2"/>. Excel tolerated the layout but Office File Validation flagged the file and strict OOXML consumers (Apache POI strict mode, LibreOffice with strict-validation enabled) rejected it. Column entries are now sorted numerically before emission.
Versie 2.50.0
- OpenOffice excelfileformat.pdf cross-audit pass. Eight follow-up wire-format and lifetime herstelt uncovered by re-validating the BIFF8 writer / reader against the OpenOffice Microsoft Excel File Format documentatie after the v2.49.0 [MS-XLS] pass. Public API is unchanged; existing applications recompile and re-opslaan without modification.
- Shared formules now span the full column bereik (§5.94 SHAREDFMLA). The
SHRFMLArecord body wrotecolFirstinto thecolLastbyte, collapsing every multi-column shared formule group to a single-column group in Excel. Fill-down formules across two or more columns now expand to the correct cellen when the werkmap is reopened. The reader-sidecolLastwidth was also corrected (was reading a 16-bit value that pulled in the adjacent reserved byte). - Shared formule Boolean / Error results rondreis correctly (§5.50 formule). The same
FormulaValuebyte-layout bug fixed in v2.49.0 for standalone formules was still present in the shared-formule writer (cellen that carry atExptoken pointing at aSHRFMLAmaster). CachedTRUE/FALSEand#REF!/#DIV/0!/etc. values now appear as written instead of always reading back asFALSE/#NULL!. - formule option flags identify shared-formule members (§5.50 formule). cellen inside a shared-formule group now set the
fShrFmlabit (0x0008) in the formule record option flags so strict parsers recognise thetExptoken as a back-reference instead of attempting to evaluate it as an opaque opcode. - Bold and underlined fonts identified correctly by strict readers (§5.45 FONT). The FONT option-flags word now sets bit 0 (bold) and bit 2 (underlined) in addition to the dedicated
bls/ulsfields. LibreOffice import paths and Office File Validation that check the option flags rather than the standalone fields no longer mis-classify bold or underlined fonts as plain. - CFRULE option flags carry spec-mandated constant bits (§5.16 CFRULE). When at least one formatting block is present the option-flags DWORD now ORs in bit 7 (
0x00000080, "Always 1") and bits 21-19 (0x00380000, "Always 111"). Conditional-formatting rules survive a opslaan / load rondreis on strict CFRULE parsers; the "no format blocks" special case (all-zero option flags) is preserved. - CHOOSE() formules lezen back correctly (§3.10.5 tAttrChoose). The
tAttrparser previously skipped a fixed 4 bytes for every subtype;tAttrChoose($04) is variable-length (header + per-choice jump tabel + error jump), so the decoder walked into the jump-tabel contents and corrupted every following token. The decoder now leestncand advances by6 + 2·ncbytes, matching the spec layout. - Data-validation and conditional-formatting teardown no longer dereferences past the tail. Two
Destroydestructors (TDataValidator,TCondFormatter) walked0..cnton lists whose valid indices are0..cnt-1, accessing one element past the end during werkmap teardown. Long-running applications that build and discard many CF / DV containers no longer occasionally AV at shutdown.
Versie 2.49.0
- Spec-audit pass against [MS-XLS] v20250520. Sixteen wire-format and behaviour herstelt across the BIFF8 writer, formule decoder, encryption path, chart builder, conditional-format and data-validation runtime, SST/ExtSST index, VBA storage reader and OLE stream openen path. Public API unchanged; existing code recompiles untouched. Highlights below.
- BIFF8
Formularecord Boolean and Error results now rondreis correctly. [MS-XLS] §2.5.133FormulaValuepacks the type tag into byte[0] and the bool/error code into byte[1]; the writer used to emit$0001/$0002as a Word and put the value into byte[2], so cached Boolean formules lezen back as False and Error formules as #NULL! in every consuming application. - cel colours set via
SetColorRGBrender correctly. The colour manager wrote ColorType=1 (theme) for RGB values and ColorType=2 (RGB) for theme values, swapping the two code paths. Both setters now route through the matching ColorType bucket so RGB values feed the RGB resolver and theme indices feed the theme resolver. - XOR Obfuscation and RC4 decryption fixed. The XOR methode-1 decrypt loop now matches [MS-OFFCRYPTO] §2.3.7.3 (XOR first, then rotate-right 5; seed XorArray index from the entry stream position, not the post-process position). RC4
Skipnow walks every 1024-byte boundary continuously instead of jumping straight to the destination block, keeping the keystream state aligned with the file position for every subsequentDecryptcall. - Chart sheet wire format aligned with the spec. SIIndex records emit in numIndex=1 → 2 → 3 order ([MS-XLS] §2.4.262; was 2 → 1 → 3, which strict parsers reject), DEFAULTTEXT count clamped to the spec maximum of 2 ([MS-XLS] §2.1.7.20.1; was 4), Chart3DBarShape placeholder uses the correct id
$105F(was$1066). - HLink tooltip records load correctly. The
HLinkTooltip($0800) body decoder used to lezen FrtRefHeader anchor fields at offsets 2/4/6/8 instead of 4/6/8/10, so the anchor-bereik comparison never matched and per-cel tooltips were silently discarded; tooltips now associate with their hyperlinks. BIFF8 bereik-reference decoder also fixed aFFirstColRel/FLastColReltypo in the BIFF5/7 fallback sign-extension path that mis-decoded bereiken with negative last-column relative offsets. - Conditional formatting and data validation runtime herstelt.
IsContainRowin bothTCondRangeandTDVRangereturned true only when the bereik degenerated to a single row (the comparison was inverted); per-row clearing of CF / DV rules now works on multi-row bereiken. Three destructors (CondFormat, formatter, DVRangeList) usedfor i := 0 to cnton lists whose valid indices are 0..cnt-1; the off-by-one is fixed and long-running workloads no longer occasionally AV during teardown. CF12 icon-set rules emit ct=$06(IconSet per [MS-XLS] §2.4.43) instead of ct=$05(Filter), so werkmappen containing icon-set rules openen with the rules intact. - ExtSST quick-find index spec-conformant for large werkmappen. The
dsstfield is now computed asmax((cstUnique / 128) + 1, 8)per [MS-XLS] §2.4.107 instead of the static default of 8; werkmappen with more than ~900 unique strings now build a correctrgISSTInfbucket array and Excel's quick-find SST lookup works. - WriteAccess record honours [MS-XLS] §2.4.349 cch <= 54. The
userName.cchfield now carries the actual user-name length (6 for "HotXLS") with the remaining bytes filled by the spec-defined "unused" trailer. Previously the field carried cch=109, which Office File Validation flags as a hard format violation. - BIFF8 werkmap stream openen path matches the spec spelling. The first OLE
OpenStreamattempt uses 'werkmap' (capital W per [MS-XLS] §2.1.7.20) instead of all-lowercase, so compound-file containers on case-sensitive OLE implementations openen the stream on the first try. - VBA module reader no longer drops the last byte of each stream. The seek-to-end length used
trunc(l) - 1instead oftrunc(l), truncating the compressed-source tail and causing the RLE container decompressor to terminate early on certain modules.
Versie 2.48.10
- HotXLS-saved .xls files now include the two OLE compound-file eigenschap-set streams Excel expects on every werkmap:
\005SummaryInformationand\005DocumentSummaryInformation. Pre-v2.48.10 only TRIAL builds wrote them (as a banner-stamping mechanism); release builds produced .xls files whose werkmap stream was valid BIFF8 but whose OLE container was missing the standard Office metadata streams. Excel 2003's strict parser treats this as the "File error: data may have been lost" condition (modern Excel keeps the Protected View "this file has problems" banner). Adding the streams resolves the dialog on chart werkmappen without changing any BIFF8 record. - The two streams are emitted via Win32's
StgCreatePropSetStg+IPropertySetStorage.Create+IPropertyStorage.WriteMultiplepath — the same code Microsoft Office uses, so Office File Validation accepts the byte layout. The SummaryInformation stream is created with defaultAppName="HotXLS"and empty Author; TRIAL builds still overwrite the Author / AppName values with the trial banner vialxTrial.XlsTrialStampXlsSummaryafter the default stamp, so trial files remain identifiable in Excel's File > Info > eigenschappen pane. The DocumentSummaryInformation stream is created empty (Win32 still emits the eigenschap-set header + CODEPAGE eigenschap — enough for Excel's strict parser to consider the metadata "present and well-formed"). - This fix is universal — every HotXLS-saved .xls now carries the standard OLE metadata, not just chart werkmappen. werkblad-only outputs from earlier releases happened to escape the symptom because Excel is more lenient with metadata-less werkblad werkmappen than with chart-sheet werkmappen, but they were also technically missing the streams. New
Lib/lxXlsSummary.pasunit holds the two hulp procedures; lxHandle.pas calls them unconditionally insideTXLSWorkbook.SaveWorkbookafterStoreWorkbookpopulates the werkmap stream and beforeFDocStorage.Commit. - This release closes the eight-version chart-Phase-2 follow-up sequence (v2.47.0 — v2.48.10): from
tArea3Dseries binding, through BRAI id realignment, sdtX/cValx Excel-observed values, SERIESTEXT placement, werkmap stream padding removal, sheet-level shell records, and now OLE metadata streams. The result is a chart .xls that opens in Excel 2003 and modern Excel without any "file has problems" warnings, byte-aligned with what Excel itself schrijft for the same data.
Versie 2.48.9
- BIFF8 chart sheets now carry the full set of sheet-level shell records that Excel 2003+ requires. v2.48.8's chart_phase2_demo.xls rendered the column chart correctly but Excel 2003 still surfaced a "File error: data may have been lost" dialog (newer Excel versions kept the Protected View banner) because the chart substream was missing the same sheet-level records a werkblad substream carries. Real Excel files (both from-scratch and re-saved variants of HotXLS output) wrap the chart records in this shell:
- Before the chart records (between BOF and UNITS):
HEADER($0014, empty),FOOTER($0015, empty),HCENTER($0083, value 0),VCENTER($0084, value 0),SETUP($00A1, 34-byte page setup),PRINTSIZE($0033, value 3). - After the chart records (after the outermost CHART END, before EOF):
DIMENSIONS($0200, 14 bytes) declaring the cached data bereik, threeSERIESINDEX($1065) markers for categories / values / bubble-size cache slots, aNUMBER($0203, 14 bytes) per cached value point, andWINDOW2($023E, 10-byte chart-sheet variant) at the end.
dev-notes/biffview-refs/excel_column_chart_resaved.xls(the Excel-saved column-chart reference, kept local). - Before the chart records (between BOF and UNITS):
- The values cache currently emits zero placeholders (
0.0for every data point), matching what Excel itself schrijft when re-saving a chart whose source cache wasn't pre-populated. The chart still plots the real data because the BRAIPtgArea3dreferences resolve to the source werkblad cellen at draw time — the cache is what lets Excel parse the chart sheet without warnings, not what feeds the plot. A future release can populate the cache with the actualValuesbereik numbers; the wire format is in place. - End-to-end smoke test: openen the regenerated
Demo/Delphi/XlsCreateChart/chart_phase2_demo.xlsin Excel 2003 — the "File error: data may have been lost" prompt no longer appears, and the column chart renders identically to before. The same file opens cleanly in modern Excel without the Protected View banner.
Versie 2.48.8
- BIFF8 (.xls) writer no longer pads the werkmap stream with trailing zero bytes.
TXLSWorkbook.StoreOleFileused to callStoreExtraSpace(Book)after the last sheet's records, padding the stream length up to the next 512-byte (OLE sector) boundary. Excel's strict parser treats those trailing zero bytes as a bogus stream of0x0000-id records and surfaces a "this file has problems" Protected-View prompt — visible on the v2.48.7 chart_phase2_demo.xls even after the BRAI / sdtX / SERIESTEXT wire format was fixed and the chart itself rendered correctly. Removing the call drops the padding from the werkmap stream content; OLE sector padding still happens, but in the CFB container layer below the stream where Excel itself puts it (every Excel-saved .xls has a non-sector-aligned werkmap stream length). - Symptom history: any HotXLS-saved .xls whose total valid-record byte length didn't already happen to land on a 512-byte boundary carried the trailing-zero stream. The bug existed from the repository bootstrap commit forward but rarely surfaced — most werkmappen happen to have enough records that the padding ended up small (≤ 4 zero bytes that Excel tolerated). Chart-sheet werkmappen happen to land far short of a sector boundary (the v2.47.0 — v2.48.7 demo padded 420 zero bytes), so this is where the Protected-View prompt became consistent.
StoreExtraSpacethe methode survives as private dead code inlxHandle.pasin case a future code path legitimately needs sector-rounded streams; the call site inStoreOleFileis removed. werkmap stream length now equals exactly the byte length of all valid records (chart demo: 3164 bytes; Excel from-scratch reference: 4419 bytes — both non-sector-aligned). Reader code paths are unaffected — HotXLS has always lezen non-sector-aligned werkmap streams from Excel-saved files correctly.
Versie 2.48.7
- BIFF8 chart series records finally render correctly in Excel. The fix is realigning BRAI id assignments with [MS-XLS] §2.4.51 — the parent implementation plan documented them inverted, propagating the bug through every chart release from v2.41.0 to v2.48.6. The correct id semantics are:
id = 0— series name / legend label (plan said: categories)id = 1— values (correct)id = 2— categories (plan said: name)id = 3— bubble sizes (plan said: errBars)
- Also realigned to match Excel-saved column-chart wire format:
SERIES.sdtXis now0x0003(Excel's observed value for text categories, not the [MS-XLS] §2.4.252 documented0x0001), andcValxcarries the actual category count instead of0. The "cValx MUST = 0whensdtX∈ {1, 3}" spec rule is contradicted by every Excel-saved sample examined. - The
SERIESTEXT($100D) literal-name carrier returns, but in the right place: immediately after theid = 0BRAI, still inside the SERIES BEGIN/END block. This is what real Excel files do — the v2.48.5 emit point (after the whole BRAI cluster, beforeDataFormat) was wrong and broke chart parsing; the correct position is right next to the series-name BRAI. - v2.41.0 — v2.48.6 saved chart files all carry the inverted-BRAI wire format. They openen in Excel without error but show the legend / X-axis symptoms above. Re-opslaan through v2.48.7+ to migrate; no API change — the same
AddChartSheetcall now produces a chart that renders identically to what Excel itself would schrijven for the same data. - New byte-level inspection tool
dev-notes/biffview-refs/dump_chart_substream.pydumps the chart substream of any BIFF8 .xls with per-record decoding (SERIES / BRAI / SERIESTEXT / AXIS / CATSERRANGE / LEGEND / OBJECTLINK / POS / TEXT). Used during this release to byte-diff HotXLS output against the Excel-saved reference samples; available for future chart-spec follow-ups.
Versie 2.48.6
- BIFF8 chart-sheet substream retracts the v2.48.5 changes. Excel testing on the regenerated v2.48.5 demo did not render the chart at all — worse than the v2.47.0 baseline (where the chart drew but with wrong X-axis labels). The two v2.48.5 changes were the cause:
SERIES.sdtX = 4is not actually accepted by Excel even though Apache POI exposesCATEGORY_DATA_TYPE_TEXT = 4. [MS-XLS] §2.4.252 strictly requiressdtXto be0x0001or0x0003.- The toegevoegd
SERIESTEXT($100D) record inside the SERIES BEGIN/END block is a structural violation —SERIESTEXTbelongs in TEXT blocks (chart title / axis title / data label contexts), not inside the SERIES block. Embedding it there confused Excel's chart parser into rejecting the whole substream.
- v2.48.6 restores the v2.47.0 wire format AND voegt toe one spec-compliance fix:
SERIES.cValxis now0whensdtX = 1([MS-XLS] §2.4.252 spec MUST rule). Pre-v2.48.6 wrotecValx = count(4 in the demo) which violated the rule and may have contributed to Excel's "document has issues" Protected-View prompt.cValystill carries the actual value count (sdtY=1 has no zero-rule). - New XlsCreateChart Delphi demo under
Demo/Delphi/XlsCreateChart/creates a two-sheet werkmap: a "Data" werkblad with four (Region, Sales) rows and a "Chart1" column-chart sheet whose series bindsData!$A$2:$A$5/Data!$B$2:$B$5as Categories / Values. The demo is the permanent successor to the ad-hocchart_phase2_demo.xlsthat v2.47.0 — v2.48.5 placed in the repo root for BiffView testing; the root file has been removed, and the new demo schrijft its output alongside its own .exe. - Known unresolved: with v2.48.6's wire format, Excel still renders the column chart's X-axis labels as zeroes and falls back to concatenating category cel text for the legend (instead of using the BRAI id=2 PTG tStr literal
'Q1 Sales'). This is a real wire-format gap that needs an Excel-saved reference column chart to diff against — tracked as a follow-up. The 4-bar plot area itself renders correctly (heights 100/150/200/175 match Values).
Versie 2.48.5
- BIFF8 chart series records now render correctly in Excel. v2.47.0 toegevoegd
tArea3Dbinding for Categories / Values bereiken, but Excel still drew the wrong X-axis labels (every category became0) and used the concatenated category text ("North South East West") as both legend label and auto-title instead of the user-supplied series name. Two herstelt restore the intended rendering: - The
SERIESrecord'ssdtXfield is now4(text categories), not1. [MS-XLS] §2.4.252 documents only1(dates) and3(BIFF7 sequence) but real Excel-saved column / bar / line chart files schrijven4for text-axis categories (matching Apache POI'sCATEGORY_DATA_TYPE_TEXTconstant). WithsdtX=1Excel tried to coerce'North'/'South'cellen to numbers, so the X axis showed four zeroes;sdtX=4lets the labels through verbatim. The pre-v2.48.5 wire form also violated the spec rule thatcValxmust be zero whensdtX=1. - A
SERIESTEXT($100D) record is now emitted inside the SERIES BEGIN/END block (after the BRAI cluster, beforeDataFormat) whenever a literal series Name is supplied. The Phase 2 first-half mechanism (BRAI id=2 + PTGtStr) is kept for completeness but Excel actually surfaces the legend label and the auto-title fromSERIESTEXT; with only the BRAI variant present, Excel fell back to concatenating category cellen. After this fix the legend shows the real Name (e.g.'Q1 Sales') and an empty chart title leaves the auto-title slot blank rather than dragging category text into it. - Migration: v2.42.0 — v2.47.0 chart-sheet outputs still openen in Excel without error but rendered the symptoms above. Re-opslaan through v2.48.5+ to get the corrected wire format; no API change is required, the same
AddChartSheetcall now produces the correct chart.
Versie 2.48.4
- BIFF8 CFEX ($087B) emit is retired. HotXLS no longer schrijft the paired CFEX after every CF12 ($087A) record — all Data Bar / Color Scale / Icon Set configuration now travels inline in the CF12 kind tail (v2.48.1 — v2.48.3). HotXLS-saved .xls files become smaller and exactly match Excel's own output (Excel-saved samples like
poi_ConditionalFormattingSamples.xlscontain zero CFEX records). Apache POI / NPOI already ignore CFEX, so this is a pure simplification with no readability loss. - BIFF8 CF12 lezen path now consumes the kind tail directly from CF12 instead of falling back to CFEX.
ParseCfExbecomes a no-op; the lxRead dispatch entry for $087B stays so HotXLS-saved v2.34..v2.47 files don't crash, but their CFEX content is ignored (those files also have a pre-v2.48.0 CF12 header layout and would not rondreis correctly — re-opslaan through Excel or HotXLS v2.48.x to migrate). - This completes the 5-PATCH Gap #6 wire-format rewrite (v2.48.0 header + v2.48.1 data_bar + v2.48.2 color_gradient + v2.48.3 multistate + v2.48.4 CFEX retire). HotXLS-saved Excel 2007+ conditional formatting records now match Excel's own wire format byte-for-byte (modulo formule content), making them interoperable with Apache POI / NPOI and any other spec-compliant BIFF8 reader.
Versie 2.48.3
- BIFF8 CF12 ($087A) Icon Set rules now emit the NPOI-compatible
multistatesub-record inline so Apache POI / NPOI can lezen the icon family identity, per-stop thresholds, and reverse / show-icon-only flags directly from CF12 without consulting the legacy CFEX record. Layout matches NPOIIconMultiStateFormatting.Serialize():reserved(2) + reserved(1) + num(1) + iconSet.id(1) + options(1)+ per-stopIconMultiStateThreshold(cfvo + equals byte + 4 reserved). - HotXLS
TXLSIconSetTypevalues0..16map 1:1 onto NPOI'sIconSetid enum (3Arrows / 3TrafficLights1 / 4RedToBlack / 5Quarters etc), so existing user code using icon-set constants continues to rondreis unchanged.ShowOnlysets options bit 0 (iconOnly),Reversesets bit 2. - Default per-stop thresholds (HotXLS
cfvPercentwith even-split values: 3-icon=0/33/67, 4-icon=0/25/50/75, 5-icon=0/20/40/60/80) emit as NPOI RangeTypePERCENT(4)+ value Double + equals byte (alwaysEQUALS_INCLUDE=1for now). This completes the kind-tail leg of the Gap #6 CF12 rewrite; CFEX emit retirement follows in v2.48.4.
Versie 2.48.2
- BIFF8 CF12 ($087A) 2-color and 3-color Color Scale rules now emit the NPOI-compatible
color_gradientsub-record inline so Apache POI / NPOI can lezen the per-stop threshold + color + interpolation positions directly from CF12 without consulting the legacy CFEX record. Layout matches NPOIColorGradientFormatting.Serialize():reserved(2) + reserved(1) + numI(1) + numG(1) + options(1)+ per-stopColorGradientThreshold(cfvo + position Double) + per-stopstep + ExtendedColor. - Stops use NPOI's
step = 1 / (N-1)formule so a 3-stop Color Scale gets positions 0.0 / 0.5 / 1.0 and a 2-stop Color Scale gets 0.0 / 1.0. Per-stop colors (RGB or theme viaSetThemeColor) flow through the same ExtendedColor block used by Data Bars in v2.48.1. - Default kinds for 3-stop ColorScale (cfvMinOfRange / cfvPercentile=50 / cfvMaxOfRange) map to NPOI RangeType
MIN(2) / PERCENTILE(5) / MAX(3); the middle stop's value (50.0 as Double) and per-stop position are byte-verified againstpoi_ConditionalFormattingSamples.xlsrecord 215 in the test suite.
Versie 2.48.1
- BIFF8 CF12 ($087A) Data Bar rules now emit the NPOI-compatible
data_barsub-record inline (28 bytes appended aftertemplate_params) so Apache POI / NPOI can decode the bar color, min/max thresholds, and percent length bounds without consulting the legacy CFEX record (which POI ignores entirely). Layout matches NPOIDataBarFormatting.Serialize():reserved1(2)+reserved2(1)+options(1)+percentMin(1)+percentMax(1)+ ExtendedColor(16) + ThresholdMin/Max. - HotXLS bar color (BGR
LongWord) is written into the ExtendedColor block withtype=RGB; theme-color Data Bars (set viaSetThemeColor) emittype=THEMED+ themeIndex + tint.MinLength/MaxLengthdefault 10% / 90% (configurable via the spec object), matching Excel's standard Data Bar appearance. - Color Scale and Icon Set kind tails (v2.48.2 — v2.48.3) and CFEX retirement (v2.48.4) are still pending; this release only completes the Data Bar leg of the Gap #6 CF12 rewrite. See the v2.48.0 entry for the header rewrite that this PATCH builds on.
Versie 2.48.0
- BIFF8 CF12 ($087A) record header layout corrected against NPOI
CFRule12Record.serialize()and Excel-saved reference files. The previous layout placedipriority/iTemplate/grbit/parmsimmediately aftercce2and treatedcbdxfas a 2-byte length field; Excel actually schrijftext_formatting_length(4)+ an optionalSerializeFormattingBlockheader before the formule tokens, followed byformula_scale,ext_opts,priority,template_type, and a length-prefixedtemplate_paramsblock. - HotXLS-emitted CF12 records now match the byte layout of
poi_ConditionalFormattingSamples.xlsrecords 152..215 in the header section (data_bar / color_gradient / multistate kind tails arrive in v2.48.1 — v2.48.3; the paired CFEX still emits in this release and retires in v2.48.4). See the v2.47.1 entry for the CONDFMT12 sibling fix that motivated this rewrite. - The bogus 2-byte
nIDfield HotXLS appended at the end of every CF12 payload (no such field exists in the spec) is removed — rule identity is carried by the parent CONDFMT12 record. Existing v2.34.0 — v2.47.1 .xls files should be re-saved through v2.48.0 to rewrite their CF12 records.
Versie 2.47.1
- BIFF8 CONDFMT12 ($0879) record wire format corrected to match Excel-saved files. The previous implementation followed an early draft layout that placed the 8-byte associated bereik as "reserved" inside the FtrHeader and inserted a non-existent 4-byte Reserved field before
numCF; Excel-saved .xls files actually fill the 8 bytes inside FtrHeader with the rule's associated cel bereik and have no Reserved field, so HotXLS-emitted files were shifted by 4 bytes plus had a zeroed bereik slot. Reference dump frompoi_ConditionalFormattingSamples.xls(Apache POI test fixture) record 152 now matches HotXLS output byte-for-byte. - Concrete fix:
StoreCondFmt12Headernow schrijft FtrHeader asrt(2) + grbitFrt(2) + associatedRange(8), then the body asnumCF(2) + needRecalcAndId(2, bits packed) + enclosingRange(8) + cref(2) + sqref array. Total fixed bytes drop from 30 to 26 (Reserved 4 removed).ParseCondFmt12updated symmetrically to lezen at the corrected offsets. - Existing HotXLS-generated .xls files written by v2.34.0 — v2.47.0 should be re-saved through v2.47.1 to repair their CONDFMT12 records. Files round-tripped via Excel between version bumps were never affected because Excel rewrote the records to its own correct layout on opslaan.
Versie 2.47.0
- BIFF8 chart-sheet creation now binds real data bereiken to series. The
CategoriesandValuesA1-bereik strings supplied to the 6-argumentAddChartSheetoverload (e.g.'Data!$A$2:$A$5') are compiled intotArea3DPTG tokens written into the seriesBRAI id=0(categories) andBRAI id=1(values) records. Excel-opened .xls files now render actual data points in the plot area instead of the empty placeholder chart that v2.42.0 produced. - Sheet name resolution + EXTERNSHEET registration is automatic: the parser looks the named sheet up in the werkmap, registers an XTI entry if one is not already present, and schrijft the matching 0-based
ixtiinto the PtgArea3d body. Re-saved files keep theixticonsistent with the werkmap's final EXTERNSHEET ordering because the chart record stream is re-serialized through the formule compiler at opslaan time. - Accepted bereik shapes:
Sheet1!$A$2:$A$5(absolute),Sheet1!A2:A5(relative markers tolerated — chart series always store as absolute),'My Sheet'!$A$1:$B$5(single-quoted sheet names with spaces), and single-cel refs likeSheet1!$A$1(degenerates to a 1×1 PtgArea3d). Series data-point counts (cValx/cValy) are now derived automatically from the area dimensions instead of staying at zero. - Unsupported reference shapes silently fall back to the v2.41.0-stijl
cce=0placeholder BRAI so the chart still opens in Excel: cross-werkmap refs ([Book2.xls]Sheet1!...), named bereiken (Sheet1!ProfitColumn), refs missing the!sheet prefix, and refs that point at the chart sheet itself. These deferred cases are tracked for follow-up phases. - This completes Roadmap #10 Phase 2 (column chart end-to-end). Series labels (Phase 2 first half, v2.42.0) plus series bereik binding (this release) means a column chart created via
AddChartSheetkan nu display proper legend entries plus real plotted data without any post-processing in Excel.
Versie 2.46.0
- The Differential XF (DXF) decoder on the BIFF8 side now resolves xclrType=1 (indexed palette) colors from the standard Excel 2003 64-color palette. Previously indexed colors fell through to the RGB path and the icv byte was misinterpreted as part of an RGB value, producing nonsense colors (typically dark grey) on lezen; Excel-saved .xls files that used indexed colors (rather than RGB or theme) for their CF12 DXF blocks now rondreis with sensible visual colors.
- The lookup uses the built-in Excel 2003 default palette baked into HotXLS — icv 0..7 are the eight system colors (black / white / red / green / blue / yellow / magenta / cyan), icv 8..15 mirror the system colors, and icv 16..63 are the standard customizable defaults (dark variants, light tints, browns, oranges, plums, etc.). Out-of-bereik icv values fall back to black ($000000).
- BIFF8 PALETTE record (rt=$0092) werkmap customization is not consulted — a werkmap that customizes its user-changeable palette slots (8..63) will have its CF12 DXF indexed colors resolved against the default values rather than the customized ones. For most Excel files that use the default palette this is correct; for files with aangepaste palettes the visual color may shift slightly until full PALETTE plumbing lands in a future release.
- xclrType=0 (auto) and xclrType=2 (RGB) paths are unchanged — auto still becomes RGB 0 (black), RGB still decodes the xclrValue 4-byte BGR LongWord directly. Only the previously-broken xclrType=1 path is fixed.
Versie 2.45.0
- Conditional formatting rules now rondreis the priority attribute on both the XLSX
<cfRule priority="N"/>and the BIFF8 CF12ipriorityfield. Previously every rule was assigned a sequential priority based on its index in the collection on opslaan, and the priority on Excel-saved files was ignored on lezen; now user-set priorities survive a load-edit-opslaan cycle on both backends. - New
Priorityeigenschap onTCondFormatRule(BIFF8 side) andTXLSXConditionalFormat(XLSX side). Default is zero, which behoudt the existing auto-by-index behavior on opslaan; set to a positive value to pin the priority and override the automatic assignment. - Priority lets multi-rule layering be controlled — when several rules cover the same bereik (e.g. a Data Bar + a CellIs highlight + an Icon Set), Excel applies them in priority order (lower number first). Round-tripping the priority means HotXLS-edited werkmappen keep the user's intended rendering order instead of having it recomputed from collection iteration order.
- Default behavior unchanged for callers that don't touch
Priority: the XLSX writer continues to emitpriority="1","2","3"… in collection order, and the BIFF8 CF12 writer continues to emitipriority=1. lezen paths populatePriorityfrom the wire value when present; explicit checks against zero remain backward-compatible with code that ignored the eigenschap.
Versie 2.44.0
- Icon Set conditional-format rules now ondersteuning per-stop icon overrides on the XLSX side. Each of the 3 / 4 / 5 stops in an icon set can opt out of the family default and display any icon from any of the 17 built-in Excel 2007 icon families, identified by icon set name + icon id. The OOXML element involved is
<cfIcon iconSet="OtherSet" iconId="N"/>emitted per overridden stop inside the<iconSet>body. - New methoden on
TXLSIconSetSpecopt a stop into override mode:SetIconOverride(stopIndex, OverrideSet, IconId)andClearIconOverride(stopIndex). lezen-only eigenschappenHasIconOverride[i],IconOverrideSet[i],IconOverrideId[i]expose the per-stop override state for inspection and rondreis preservation. - The XLSX writer emits
<cfIcon>children only for stops that calledSetIconOverride; stops without an override stay on the family default (no<cfIcon>emitted). The reader parses incoming<cfIcon>elements positionally inside an iconSet body and applies them to the matching stop on the newTXLSXConditionalFormat.IconSetspec. - Known limitations: BIFF8 (.xls) CFEX wire format has no slot for per-stop icon overrides, so writing an icon-set rule with overrides to .xls renders the family default for all stops (BIFF8 readers will not see the override info). werkmap-level icon-family validation is not enforced — passing an icon id beyond the override family's icon count is preserved verbatim but Excel may fall back to a default icon at render time.
Versie 2.43.0
- XLSX (.xlsx) conditional-format rules now rondreis theme color references in the
<color>element of Data Bar and Color Scale rules. Previously the writer only emitted<color rgb="FFRRGGBB"/>and the reader ignoredtheme/tintattributes; now both sides behouden the theme palette index plus the optional tint, so stijlen like "accent-2 lightened 50%" survive an Excel openen / HotXLS edit / Excel re-openen cycle without being flattened to a frozen RGB. - New methoden on
TXLSDataBarSpecandTXLSCfValue(used by ColorScale stops) opt the slot into theme mode:SetThemeColor(themeId, tint)andClearThemeColor. lezen-only eigenschappenIsThemeColor,ThemeColorId,ThemeColorTintexpose the active mode. Tint is a single in the [-1.0, +1.0] bereik — negative values darken the theme color, positive values lighten it. - The XLSX writer emits
<color theme="N"/>whenTintis exactly 0.0, or<color theme="N" tint="0.5"/>when non-zero, matching Excel's own "shortest form" output. The reader parses both attribute combinations and falls back to the existingrgb=path when neitherthemenortintis present. - Default behavior is unchanged: rules created with the existing RGB-only
AddCondFormatDataBar/AddCondFormatColorScale*entry points keep emitting<color rgb="..."/>exactly as before. Theme mode is purely opt-in via the newSetThemeColorsetter on the returned spec object. - Known limitations: BIFF8 (.xls) CFEX still only carries the RGB color (single 4-byte BGR LongWord per stop / per data bar) — theme color in CFEX would need a parallel wire-format extension. werkmap theme palette resolution (theme1.xml parsing) is still out of scope; HotXLS behoudt the theme index verbatim but does not resolve it to a concrete RGB for rendering / preview purposes.
iconSetrules carry no<color>elements so the theme-mode addition does not affect them.
Versie 2.42.0
- BIFF8 chart-sheet creation API gains a fifth
AddChartSheetoverload that accepts an array ofTXLSChartSeriesInforecords (Name,Categories,Values). Each non-emptyNameis written into the chart substream as a literal series label via atStrPTG token on the series-nameBRAI(id=2). Excel uses this label in the legend and in the series selector, so a multi-series chart now ships with proper series captions instead of the default "Series1 / Series2" placeholders. TXLSChartSeriesInfois re-exported fromlxHandlealongsideTXLSChartType, so callers can build the array without importinglxChartBuilderdirectly.- This is the first half of Roadmap #10 Phase 2 (column chart end to end). The series-name path is wired up; category and value data binding (turning the
CategoriesandValuesA1-bereik strings into realtArea3Dcel-bereik references inside the BRAI) is still a placeholder — those two fields are accepted on the API but not yet emitted into the chart substream. A follow-up release will route them through the formule compiler and the EXTERNSHEET reference tabel to land the second half of Phase 2.
Versie 2.41.0
- HotXLS gains programmatic BIFF8 chart-sheet creation. A new
AddChartSheetoverload set onSheetsschrijft a complete chart substream into the saved .xls file, where previously chart sheets could only be preserved opaquely on a load-opslaan rondreis. Four overloads cover the common entry points: name only / name + chart type / + title / + category-axis title + value-axis title. The returnedIXLSWorksheetappears in theSheetscollection, gets a chart-sheet boundsheet entry written on opslaan, and Excel opens it as a chart tab. - A new
TXLSChartTypeenum selects the chart kind:xlsChartTypeColumn,xlsChartTypeBar,xlsChartTypeLine,xlsChartTypePie. The enum is re-exported fromlxHandleso user code does not need to import the chart-builder unit directly. - The emitted chart substream covers the BIFF8 framing the spec calls for — BOF (dt=$0020), Chart / PlotGrowth / Frame / Series / SheetProperties / AxesUsed / AxisParent (POS + category axis + value axis + PlotArea + Frame + ChartFormat + chart-kind record + ChartFormatLink + Legend), EOF — so Excel recognises the result as a real chart tab of the requested kind. Existing chart-sheet rondreis via
TXLSCustomChartis unchanged. - This is the first cut of Roadmap #10 (CHART substream — the largest item in the BIFF8 audit). Phase 1 ships the framing and the API surface so that subsequent phases can layer in series data binding, axis titles, and richer per-chart-type formatting.
- Limitations: the new chart sheet renders an empty default chart of the requested kind. Series data binding (linking the chart to actual cel bereiken), populated title text, and per-chart-type formatting (gap width / bar overlap / pie hole size / marker stijl) are deferred to subsequent phases. opslaan-and-reopen with Excel behoudt the chart sheet's presence and its kind, but not yet user-supplied data.
Versie 2.40.0
- New XlsCondFormat12 Delphi demo under
Demo/Delphi/XlsCondFormat12/demonstrates the v2.34.0+ conditional-format extension API end to end. Three buttons let you generateCondFormat12.xls(BIFF8 backend),CondFormat12.xlsx(XLSX backend), or both side by side. Each output sheet carries the same four rule kinds — Data Bar, 3-color scale, Icon Set (3 arrows), and 2-color scale — covering ten data rows so you can openen the files in Excel and visually verify how each backend renders the extension rules. - The BIFF8 path additionally exercises the v2.35.0 DXF stijl override: the Data Bar rule attaches white bold font color so the cel text stays legible over the dark bar fill.
- New DUnitX test fixture at
Tests/Delphi/HotXLS.CondFormat12Tests.pascovers ten rondreis and API-surface scenarios for the CF12 family: BIFF8 rondreis for all four rule kinds, DXF stijl rondreis for RGB colors, theme colors, and font flags (bold / italic / underline), and XLSX rondreis for Data Bar / 3-color scale / Icon Set with ShowOnly. The fixture is wired intoHotXLSDelphiTests.dprand the matching.dprojso existing CI runs pick it up automatically. - To ondersteuning the fixture,
TCondFormatexposes two new public accessors:RuleCountandRule(I), so callers can iterate rules after lezen instead of relying on the previously private rule list.
Versie 2.39.0
- The Differential XF (DXF) stijl override on conditional formatting rules ondersteunt nu theme color encoding in addition to the existing RGB mode. Each color slot — font color, fill background, fill foreground — can be set against a werkmap theme index plus a tint value, so stijlen like "accent-2 lightened 50%" rondreis without being flattened to a frozen RGB.
- Three new methoden on
TXLSDxfStyleopt a slot into theme mode:SetFontColorTheme(themeId, tint),SetFillBgColorTheme(themeId, tint),SetFillFgColorTheme(themeId, tint). Tint is a single in the [-1.0, +1.0] bereik — negative values darken the theme color, positive values lighten it, 0.0 leaves the base color. The corresponding existingSetXxxColor(rgb)methoden stay RGB mode; the two modes are mutually exclusive per slot and whichever was called last wins. - Query the active mode via new
XxxColorIsTheme/XxxColorThemeId/XxxColorThemeTintlezen-only eigenschappen paired with each of the three color slots.HasXxxColorreturns True in either mode; existing callers checking onlyHasXxxColor+ readingXxxColorcontinue to work, treating theme-mode slots as having color 0 (a downgrade rather than a crash). - The BIFF8 wire format follows the standard XFProp Colour layout:
xclrType=2+ 4-byte BGR LongWord for RGB (existing v2.35.0 behavior),xclrType=3+ 2-byte signed tint × 32767 + 4-byte theme index for theme mode (new). The DXF blob decoder mirrors this dispatch — incoming Excel-saved files using theme color in their CF12 DXF blocks now expose the theme id and tint through the new eigenschappen. - Known limitations: theme-mode rondreis on BIFF8 (.xls) is the only path supported by this release — the XLSX (.xlsx) side still emits and leest
<color rgb="..."/>only and ignorestheme/tintattributes (planned for a follow-up release together with the werkmap theme palette plumbing).
Versie 2.38.0
- XLSX (.xlsx) reading now recognizes the Excel 2007+ conditional formatting extension rules in incoming files — data bar, color scale (2 and 3 stops, auto-detected from the cfvo count), and icon set — and populates the matching
TXLSXConditionalFormatobject so user code can inspect and rondreis these rules without losing them. Previously, Excel-saved .xlsx werkmappen with these rule kinds had them dropped silently on load. - The reader parses the OOXML
<cfRule type="dataBar|colorScale|iconSet">envelope plus the inner<dataBar>/<colorScale>/<iconSet>body, walking child<cfvo>entries to recover each threshold's type (num / min / max / percent / percentile / formule / autoMin / autoMax) and val, and child<color>entries to recover the data bar color or per-stop scale colors. - Icon set rules rondreis the
iconSetfamily name (the 17 baseline Excel 2007 sets — 3-arrows / 3-flags / 3-traffic / 3-signs / 3-symbols / 4-arrows / 4-rating / 4-traffic / 5-arrows / 5-rating / 5-quarters and gray variants), thereverseflag, and theshowValueflag (mapped toShowOnly). - Color values parsed from the OOXML
rgb="AARRGGBB"attribute are converted to the same BGRLongWordconvention (R in the low byte, matching VCLTColorand BIFF8LongRGB) used by the existing schrijven API, so a load-edit-opslaan rondreis behoudt the visual colors exactly. - Existing XLSX
<cfRule type="cellIs">handling is unchanged; the dispatch picks the new rule kinds only when thetypeattribute names them, and falls back to the cel-value path otherwise. - Known limitations: theme color references (OOXML
<color theme="N" tint="0.5"/>) are lezen as 0 instead of being resolved against the werkmap theme palette;iconIdper-stop overrides on icon sets are not yet captured;<cfRule>priorityattribute is ignored on lezen (rules keep their parse order).
Versie 2.37.0
- The BIFF8 CFEX record format now carries the full per-stop cfvo array (kind + value string + color, per [MS-XLS] cfvo semantics) instead of just the bar/stop color. Data Bar rules now persist the min/max threshold kinds and values, color scales persist each stop's kind + value + color combination, and icon sets persist each threshold's kind + value alongside the reverse / showOnly flags.
- CFEX writing voegt toe a version flag byte (ver=1) so older HotXLS readers that expect the v2.34.0 minimal CFEX layout silently fall back to the legacy interpretation. The v2.37.0 reader also recognizes ver=0 records produced by older HotXLS builds, so rondreis with mixed-version installations works in both directions for the kind/color fields that the older format carried.
- The reader now detects mixed CONDFMT + CONDFMT12 entries on the same bereik — a common pattern in Excel-saved files where the old cel-value backup and the new Data Bar / Color Scale / Icon Set rule cover identical sqref. The older CONDFMT entry is flagged via a new
IsShadowedeigenschap onTCondFormatso user-facing code that iterates the conditional-format collection can skip the duplicate. The writer continues to emit both record families on opslaan for cross-version Excel 2003 ↔ Excel 2007+ compatibiliteit. - New
TotalRangeeigenschap onTCondFormatexposes the merged-extent bereik that was previously private; useful for users implementing aangepaste dedup, bereik queries, or the shadow check pattern. - Known limitations: shadow detection is bounded by an exact bounding-box match (row1/col1/row2/col2 equality). Mixed entries where CONDFMT covers a slightly different sqref subset are not deduped; ColorScale full-cfvo rondreis behoudt the 8 standard kind values (num/min/max/percent/percentile/formule/autoMin/autoMax) but does not rondreis Excel's theme-color tint metadata for the stop colors.
Versie 2.36.0
- XLSX (.xlsx) output ondersteunt nu the three Excel 2007+ conditional formatting rule kinds — data bar, color scale (2-stop and 3-stop), and icon set — bringing the XLSX backend to parity with the v2.34.0 BIFF8 (.xls) backend. Four new public methoden on
TXLSXWorksheetmirror the XLS API surface:AddCondFormatDataBar,AddCondFormatColorScale2,AddCondFormatColorScale3,AddCondFormatIconSet. - The saved .xlsx file now emits the OOXML
<conditionalFormatting>element with the appropriate child structure for each rule kind:<cfRule type="dataBar"><dataBar><cfvo/><cfvo/><color/>for bars,<cfRule type="colorScale"><colorScale>with 2 or 3 cfvo + color stops, and<cfRule type="iconSet"><iconSet iconSet="...">with the appropriate cfvo set. - Built-in icon-set name mapping covers the same seventeen Excel 2007 baseline sets supported by the XLS backend (3Arrows / 3Flags / 3TrafficLights1 / 3Signs / 3Symbols / 3Symbols2 / 4Arrows / 4ArrowsGray / 4RedToBlack / 4Rating / 4TrafficLights / 5Arrows / 5ArrowsGray / 5Rating / 5Quarters), produced as the standard OOXML
iconSetattribute string. - Threshold types and color values use the same enumeration and color convention as the XLS API — same
TXLSCfValueKindfor num / min / max / percent / percentile / formule, same Delphi BGRLongWordcolor format. Existing XLSX cel-valueAddConditionalFormatcalls continue to behave identically (no regression). - Known limitations: theme color encoding is not yet emitted (OOXML
<color>uses thergbARGB string attribute only); theshowValue="0"attribute is set whenShowOnlyis true on an icon set, buticonIdper-stop overrides are not yet supported. XLSX lezen-side recognition of incoming data bar / color scale / icon set rules from Excel-saved files remains deferred — only schrijven is wired up in this release.
Versie 2.35.1
- The BIFF8 reader now decodes the Differential XF (DXF) bytes attached to a CF12 rule back into the rule's
TXLSDxfStyleeigenschap bag, in addition to keeping the raw bytes inDxfBlob. Loading an Excel-saved werkmap with styled data bar / color scale / icon set rules now exposes the font color, fill colors, bold / italic / underline, and number format id directly through theHasXxx+ value pair on eachRule.Style. - rondreis behavior: a load-edit-opslaan cycle now reflects any post-load mutation of
Rule.Style. If a user leest a werkmap, changesRule.Style.SetFontColor, and saves, the new color wins; if the user doesn't touch the stijl, the saved file carries the same overrides as the original. - Unknown
xfPropTypevalues in the DXF blob are skipped rather than rejected, so newer Excel files using eigenschap types not yet recognized by this release still load (the raw bytes remain inDxfBlobfor inspection or future rondreis ondersteuning).
Versie 2.35.0
- Conditional formatting rules now carry a Differential XF (DXF) stijl override so that a CF12 rule firing in Excel can change the cel's font color, fill, font weight, italic, underline, or number format without altering the cel's base XF. The override is exposed as a new
TXLSDxfStyleeigenschap on eachTCondFormatRule, accessible after creating a rule via the existingAddCondFormatDataBar/AddCondFormatColorScale*/AddCondFormatIconSetAPIs. - Supported stijl overrides in this release: font color, fill background color, fill foreground color, fill pattern, font bold, font italic, font underline stijl, and built-in number format id. Each eigenschap has a paired
HasXxxflag — only eigenschappen explicitly set viaSetXxxemit into the BIFF8 file. - The BIFF8 writer now appends a non-empty DXF block to the CF12 record whenever the rule's stijl has at least one override set. The DXF block uses the public XFProp array layout (cxfp + per-eigenschap type / size / data tuples) so Excel can pick up the stijl changes when the rule applies.
- The BIFF8 reader behoudt the raw DXF bytes from an Excel-saved file into the rule's
DxfBlobeigenschap, so a load-edit-opslaan rondreis no longer silently loses the cel styling carried by CF12 rules. Decoding the raw bytes back into theTXLSDxfStyleeigenschap bag is planned for a follow-up release. - Default behavior is unchanged for rules that don't opt into a stijl —
cbdxf = 0is emitted, identical to v2.34.0, so existing data bar / color scale / icon set rules render exactly as before. - Known limitations: theme-color encoding for DXF is not supported (RGB only); border overrides and gradient stops are not in this release's eigenschap set; the wire-format byte ordering for the XFProp value blobs follows public [MS-XLS] notes and may require small tweaks for full Excel rondreis fidelity once validated against BiffView. XLSX-side parity for the three new rule kinds remains deferred.
Versie 2.34.0
- New public conditional-formatting API on the werkblad for the Excel 2007+ extension rules:
AddCondFormatDataBar,AddCondFormatColorScale2,AddCondFormatColorScale3, andAddCondFormatIconSet. Each methode accepts a sqref bereik like"A1:A10"plus the kind-specific parameters (bar color, gradient stop colors, or icon-set family) and returns the created rule object. - The BIFF8 (.xls) writer now emits the corresponding CONDFMT12 / CF12 / CFEX record family alongside the existing cel-value CONDFMT / CF records, so werkmappen created via the new API persist their data bar, 2-color or 3-color scale, and icon-set rules to disk.
- The BIFF8 reader recognizes incoming CONDFMT12 / CF12 / CFEX records and exposes them through the same in-memory rule model, so Excel-authored .xls files with extension rules are no longer silently dropped on load.
- Built-in icon-set catalog covers the seventeen Excel 2007 baseline sets — 3-arrow / 3-flag / 3-traffic-light / 3-sign / 3-symbol families, 4-arrow / 4-rating / 4-traffic-light, and 5-arrow / 5-rating / 5-quarter — selectable through the
TXLSIconSetTypeenumeration. - Threshold types for data bar bounds and color-scale / icon-set stops can be any of number, min/max of bereik, percent, percentile, or formule, matching the cfvo kinds used by Excel.
- Existing cel-value conditional formatting behavior is unchanged; only new APIs and new BIFF8 record handling were toegevoegd.
- Known limitations in this release: XLSX output for the three new rule kinds is not yet wired up (existing XLSX cel-value rules unaffected); the differential-XF stijl block on CF12 is emitted empty so Excel may render bars and scales with default colors instead of the API-supplied colors; per-stop cfvo arrays carry only the color in CFEX, not the kind/value combination. These gaps are planned for the v2.34.x / v2.35.x follow-up releases together with the demo werkmap and Excel-rendering validation.
Versie 2.33.3
- New XlsTables Delphi demo under
Demo/Delphi/XlsTables/demonstrates the BIFF8 tabellen (ListObjects) schrijven side end-to-end. It generatesSalesTable.xlswith a four-column sales region (Region / Product / Quarter / Revenue) bound as a tabel at A1:D10 usingSheet.AddTable('SalesTable', 'A1:D10', headers). openen the produced .xls in Excel to verify the column dropdowns, banded-row stripes, and the SalesTable structured-reference name in the Name Box. - The demo is the shortest end-to-end recipe for adopting the v2.33.0
AddTableAPI: it setsStyleName = 'TableStyleMedium2'andShowRowStripes = True, fills nine data rows + one header row, and schrijft the werkmap with a singleSaveAscall. Output goes next to the executable; an "openen Output Folder" button is provided for convenience. - Compilation infrastructure is unchanged: the existing
build-Win32-Demo.cmdpicks upXlsTables.dprautomatically via itsfor /r Demo *.dprsweep — no changes to build scripts or .cbproj/.dproj configs required.
Versie 2.33.2
- BIFF8 (.xls)
SaveAsnow suppresses the standalone sheet-levelAUTOFILTERINFO/AUTOFILTERrecords ($009D / $009E) when a tabel on the same sheet fully covers the autofilter bereik. Excel embeds an autofilter dropdown inside the tabel object itself, so emitting an additional sheet-level autofilter for the identical bereik triggers Office File Validation to reject the file. This matches the XLSX-side fix shipped in v2.29.4. - The coverage check is conservative: a tabel is considered to "cover" the autofilter only when its first/last row and first/last column bracket the autofilter's bounds. Partial overlap (e.g. autofilter spanning extra rows below a tabel) keeps emitting the sheet-level autofilter so legacy workflows that put a filter above or beside a tabel region continue to work.
- BIFF5 saves and sheets without any tabel are unaffected — the suppression check only runs when the file format is BIFF8 and the werkblad has at least one tabel. No public API change.
Versie 2.33.1
- BIFF8 (.xls) lezen side now recognizes the shared-feature tabellen records that v2.33.0 toegevoegd on the schrijven side. Opening an .xls saved by Excel (or by HotXLS itself) with one or more ListObjects/tabellen now populates the werkblad's
Tablescollection with aTXLSTableper parsed FEAT11 ($0872), reconstructing the tabel's bereik from the primary Ref8U, recovering the tabel id, name, and display name when present, and filling in the tabel stijl name from the paired LIST12 ($0877) record. Previously these records were silently ignored, dropping all tabel state on rondreis. - The shared FEATHEADR ($0867) opcode is now dispatched by its
Isffield instead of always going to the protection parser. Isf=2 (Enhanced Protection) keeps the existing behavior; Isf=4 (SharedList) is acknowledged as the marker for tabellen on the sheet; Isf=3 (SmartTags) and other values are safely ignored. FEATHEADR11 ($0871) is also acknowledged silently as a tabellen marker. - The reader is best-effort and tolerant: malformed or Excel-variant FEAT11 payloads degrade gracefully to a tabel that has at least the correct cel bereik, even if the higher-offset fields (per-column ids, structured-reference data) cannot be parsed. Sheet protection rondreis is unchanged — the existing options bit at Isf=2 payload offset 19 is still lezen identically.
Versie 2.33.0
- BIFF8 (.xls) werkbladen now ondersteuning tabellen (Excel ListObjects). Call
Worksheet.AddTable(Name, Range, Columns)on anIXLSWorksheetto attach a named tabel region to a cel bereik — for exampleSheet.AddTable('SalesTable', 'A1:F9', HeaderList). The .xls opslaan path emits the BIFF8 shared-feature record family that marks the sheet as containing tabellen: FEATHEADR ($0867 with Isf=4), FEATHEADR11 ($0871), and a paired FEAT11 ($0872) + LIST12 ($0877) per tabel. Previously, callingAddTableon the XLS facade was unavailable; tabellen defined on a werkblad were silently dropped onSaveAs(xlExcel97). - New public API on
IXLSWorksheet:Tables: TXLSTableseigenschap (lezen-only collection) andAddTablemethode. The shape mirrorsTXLSXTable/TXLSXTableson the XLSX side, so code that voegt toe tabellen to a werkmap can be format-agnostic.TXLSTableexposesId,Name,DisplayName,Range,Columns,StyleName(default'TableStyleMedium2'),ShowFirstColumn,ShowLastColumn,ShowRowStripes(default true),ShowColumnStripes, andTotalsRowShown. - The new sheet-stream records are emitted just before the werkblad EOF, after sheet protection, only when the file format is BIFF8 (
xlExcel97). werkmappen without tabellen opslaan exactly as before — no FEATHEADR is emitted, no record stream changes, no overhead. BIFF5 saves are unaffected since tabellen are a BIFF8+ concept. - tabel ids are assigned sequentially per sheet (1..N) at opslaan time if not pre-set, so callers can leave
Idat its default afterAddTable. The default stijl name'TableStyleMedium2'matches what Excel and the XLSX side already use, keeping tabel appearance consistent across both file formats. - Known limitations of this initial release (v2.33.0): totals-row formules and structured-reference auxiliary bereiken are not yet emitted; conflict suppression between sheet-level
AUTOFILTERINFOand a tabel bereik will be toegevoegd in a follow-up; the lezen side (parsing an Excel-saved .xls with tabellen back into theTablescollection) is also a follow-up. tabellen created via this v1 schrijven path are well-formed for rondreis preservation in Excel itself.
Versie 2.32.1
- Fixed a compilation error introduced by the v2.32.0 FILEPASS schrijven-side feature that prevented the library from building on RAD Studio 12+ with strict type-checking. The
EncryptAllBlobshulp declared its scatter buffer asPBytein a context wherePByteresolved tolxHandle's local alias, while the call targetEncryptBlobDatainlxEncrypterexpectedlxBLOB.PByte. Although the two types both alias^Byte, Delphi treats them as distinct under E2010 strict type-checking. The buffer variable is now fully qualified aslxBLOB.PByte, so the v2.32.0 password-encryption path compiles cleanly across all supported RAD Studio versions (12.0–37.0).
Versie 2.32.0
- toegevoegd
EncryptionPasswordeigenschap onIXLSWorkbook. Setting a non-empty password beforeSaveAsnow produces an Excel-compatible password-protected .xls file: Excel, LibreOffice Calc, and other BIFF8 readers prompt for the password on openen and refuse access when it is wrong. Previously the password setter was silently ignored on the schrijven side and werkmappen were always emitted in plaintext. - The schrijven path emits the BIFF8 FILEPASS record ($002F) immediately after the werkmap BOF and RC4-encrypts every subsequent record body using the existing lezen-side algorithm (vMajor=1, vMinor=1 -- Excel "Office 97/2000 Compatible" encryption). 16-byte Salt and Verifier are generated via Windows
CryptGenRandomrather than PascalRandom. Block-key re-derivation at every 1024-byte boundary is preserved so large werkmappen, SST CONTINUE chains, and multi-sheet streams encrypt correctly. - Encryption applies to BIFF8 (
xlExcel97) only -- the BIFF5 opslaan path remains plaintext. EmptyEncryptionPasswordkeeps the legacy plaintext output and is the default, so existing applications that never call the setter are unaffected. - lezen side: fixed a latent bug in
ParseFilePassthat caused the first record body after FILEPASS (typically CODEPAGE) to be treated as plaintext. HotXLS-written encrypted files now rondreis through HotXLS itself, and Excel-written encrypted files no longer hand back a garbage CODEPAGE value. - Security note: BIFF8 RC4 with vMajor=1/vMinor=1 uses a 40-bit key, considered broken by 2025 standards. Use this feature for compatibiliteit with Excel's classic password-protection UI, not for confidentiality of sensitive data. For real security, prefer XLSX with AES.
Versie 2.31.0
- toegevoegd
UseSharedFormulaseigenschap onIXLSWorkbook. When set toTrue, BIFF8 SaveAs groups cellen that share a template formule into native SHRFMLA records ($04BC), matching Microsoft Excel's compact wire format. Columns of formules like=A1*B1,=A2*B2, …,=A99*B99are grouped automatically, reducing file size by 30–60 % on template-heavy sheets. - Grouping is column-down, contiguous, and template-based: only cellen in the same column with consecutive rows and PTG-equivalent formules are grouped. cellen with array formules or merged-cel flags are excluded.
- Default is
False, keeping the existing per-cel formule record emission unchanged. Opt in by settingWorkbook.UseSharedFormulas := Truebefore callingSaveAs. - Reading side is unaffected: HotXLS has always lezen SHRFMLA records correctly, so round-tripped files continue to work. This is a MINOR version bump (2.30.x → 2.31.0) because a new public eigenschap is toegevoegd and BIFF8 output format changes when the feature is enabled.
Versie 2.30.6
- Fixed a fourth class of compilation error in the C++Builder demos under RAD Studio 37.0's clang-based bcc32 compiler: indexing a border stijl through a smart-pointer interface using
->Borders[idx]->Proptriggered error E5843 ("member reference type is not a pointer"). All occurrences have been changed to->Borders->Item[idx]->Prop, which accesses the indexed eigenschap directly on the interface. This fix appears in the ApiTour, ExportWithColoring, PurchaseOrder, and QuickStart demos and completes full clang compatibiliteit for all nine C++Builder demo projects.
Versie 2.30.5
- All nine C++Builder demo projects now build cleanly under RAD Studio 37.0's clang-based bcc32 compiler. Fixed three classes of compilation error: the
lxFormulaeigenschapEOFwas renamedIsEofto eliminate a conflict with the Cstdio.hmacro of the same name; XLS API enum constants (xlHAlignCenter,xlAround,xlMedium, etc.) are now explicitly qualified with theLxhandle::namespace in C++Builder demo code; and XLSX cel-value assignments changed fromOleVariant(...)toVariant(...)becauseTXLSXCell.ValueisSystem::Variantand the clang compiler rejects the implicit protected-base-class conversion fromOleVariant.
Versie 2.30.4
- The OrderCalc demo (Delphi Purchase Order sample) bevat nu an XLSX export option alongside the existing XLS, HTML, and RTF formats. Selecting "Excel 2007+ file (*.xlsx)" in the opslaan dialog schrijft the purchase order using the native TXLSXWorkbook API, producing a standards-compliant XLSX file with fonts, fills, borders, alignment, number formats, and Excel formules preserved.
Versie 2.30.3
- SaveXLSWorkbookAsXLSX (the bridge used by TDataToXLS.SaveAs and TGridToXLS.SaveAs when the target filename ends in .xlsx) now copies cel background fill colors, font colors, and font stijl attributes (name, size, bold, italic) from the underlying XLS werkmap to the XLSX output. Column widths — including explicitly narrowed columns set before export — are also copied. Previously only cel values and number formats were transferred, so the XLSX output was uniformly unstyled, all column widths were at the default, and any deliberately-narrow decorative column appeared as an oversized blank column.
Versie 2.30.2
- Fixed a rondreis bug in the XLS reader where the Outline.SummaryRow direction was inverted after openen. The WSBOOL record's fRwSumsBelow flag (BIFF8 spec p278 byte 0 bit 6, mask $0040) means "summary rows appear *below* detail", but the parser previously set SummaryRow = xlAbove when the bit was set (and xlBelow when clear) -- exactly the opposite of the spec. The writer side was already correct (emits $0040 for xlBelow), so opening an Excel file with "summary rows below detail" and re-saving it via HotXLS would silently flip the outline direction to "above". Now the parse direction matches the spec and the writer, so outline configurations rondreis correctly. fColSumsRight ($0080) was already handled correctly and is unchanged.
Versie 2.30.1
- XLS (BIFF8) writer now emits INTERFACEHDR / INTERFACEEND / WRITEACCESS records in the werkmap globals section, matching Microsoft Excel's native record layout. Native Excel always schrijft this trio between CODEPAGE/DSF and WINDOW1, and stricter BIFF readers / Office File Validation paths may expect them. INTERFACEHDR carries the code page (1200, UTF-16), INTERFACEEND is an empty marker, and WRITEACCESS carries the "saved by" user name (currently hard-coded to "HotXLS"; a future release may promote this to a werkmap eigenschap). Output XLS files now match Excel's native byte layout more closely.
Versie 2.30.0
- toegevoegd a classic-to-XLSX export bridge. TDataToXLS.SaveAs and TGridToXLS.SaveAs now schrijven .xlsx file names through the XLSX engine while keeping the existing .xls, .html, and .rtf paths unchanged.
- toegevoegd werkblad view APIs for XLS and XLSX. IXLSWorksheet.View and TXLSXWorksheet.View ondersteuning normal view, page-break preview, and page-layout view, and the setting is preserved by the relevant file writer/reader path.
- toegevoegd classic werkmap compatibiliteit APIs: IXLSWorkbook.SetCodePage and IXLSWorkbook.VBAProject. VBA projects kan nu be inspected through TXLSVBAProject/TXLSVBAModule module names and source text when a werkmap contains a VBA storage.
- Extended TXLSXWorkbook with ParsedVBAProject, a lezen-only parsed view over a valid vbaProject.bin payload, while preserving the existing raw VbaProject byte rondreis behavior.
- toegevoegd the optional cxGridAddExcel unit for DevExpress cxGrid export workflows. It is intentionally not included in the default packages so installations without DevExpress continue to build cleanly.
- Fixed XLSX chart sheet rendering where the chart appeared blank when the werkmap was opened in Excel (a freshly opened chart sheet briefly showed the 3 chart-context icons in the top-right and then dropped them, leaving the sheet empty). Chart sheet drawings now use <xdr:absoluteAnchor> with explicit extent (~10in × 7.2in = 9525000 × 6858000 EMU) instead of <xdr:twoCellAnchor> with cx=0/cy=0; chart sheets have no cel grid to resolve twoCellAnchor against, so Excel was falling back to the inner xfrm of zero size and rendering the chart at zero pixels. Per ECMA-376-1 14.2.3.2, chart sheet drawings must use absoluteAnchor. werkblad chart anchors are unchanged.
Versie 2.29.4
- Fixed an XLSX packaging bug that caused Excel's repair prompt "We found a problem with some content in <file>.xlsx" on werkmappen where a sheet-level autoFilter and a tabel cover the same bereik (e.g. the MemoryDataExport demo's XlsxFeatureGallery.xlsx Details sheet, which called AddTable('SalesTable', 'A1:F9', ...) followed by SetAutoFilter('A1:F9')). OOXML forbids two filter mechanisms over the same bereik; the writer now suppresses the duplicate sheet-level <autoFilter> emission when its bereik coincides with any tabel's bereik. The tabellen' own autoFilter (rendered as the tabel header dropdowns) still works.
- Fixed a related schema violation in <dataValidation> output: an operator attribute was emitted for every validation, but ECMA-376-1 18.3.1.32 only allows it for types whole / decimal / date / time / textLength. AddListValidation produces type="list", which used to leak operator="between"; OFV is stricter than Excel about this and could reject the werkmap. The operator attribute is now omitted for list / aangepaste / none.
- Fixed the <legacyDrawing r:id="..."/> element on werkbladen that mix internal and external hyperlinks with comments (XlsxFeatureGallery.xlsx Dashboard sheet has 1 internal + 1 external + 1 comment). The rId calculation counted all hyperlinks instead of only the externals (internals use the inline location= attribute and do not consume an rId), so legacyDrawing pointed at the comments rels target instead of the vmlDrawing target. ECMA-376-1 18.3.1.51 requires legacyDrawing to reference a vmlDrawing-typed rels. The rId is now computed from the external hyperlink count only.
- Also stopped emitting a redundant xl/werkbladen/_rels/sheetN.xml.rels file for chart sheets toegevoegd via AddChartSheet. The duplicate relationship file pointed at a nonexistent werkblad part and showed up as an orphan inside the .xlsx zip; chart sheets now schrijven only the correct xl/chartsheets/_rels/sheetN.xml.rels.
- Updated the MemoryDataExport demo (XlsxFeatureGallery) to drop the redundant SetAutoFilter('A1:F9') call on the Details sheet -- AddTable already attaches an autoFilter to the tabel bereik, so the extra call previously triggered the OFV rejection above. The writer's defensive suppression covers customer code that does not get the demo update.
Versie 2.29.3
- Fixed an XLSX rondreis regression where borders drawn on otherwise-empty rows were dropped after openen + modify + SaveAs. ApiTour's row 8 horizontal divider (produced by a bereik.SetBorders call on a row with no data) rendered correctly in the freshly generated ApiTour.xlsx but disappeared in ApiTour-XLSX-Modified.xlsx after the demo's Modify pass re-saved the file, leaving Excel showing a broken vertical grid line at C8 / D8 in the modified file only (the original ApiTour.xlsx was unaffected). The XLSX parser now also applies cel stijlen when a `<c>` element is self-closing or has no value/formule children, so styled valueless cellen survive the round trip.
Versie 2.29.2
- Fixed an XLSX rondreis regression in openen + modify + SaveAs flows. When ParseWorksheetXml lezen a cel whose
referenced a stijlen.xml cellXf, it stored N directly on cel.FormatIndex. On SaveAs the cellXfs are rebuilt from the werkmap stijl pools (with optional composite entries) and the new layout's slot at the same numeric index almost never carries the same semantics; the resaved cel ended up pointing at the wrong cellXf -- or past the end of the new cellXfs tabel -- and Excel reported "Office has detected a problem with this file. We can try to recover". ApplyStyle now reverse-maps cellStyle to FontIndex / FillIndex / BorderIndex / NumberFormatIndex / AlignmentIndex / ProtectionIndex via the CellXfXxxMap tabellen that ParseStylesXml already populates, so the round trip re-emits the cel against the freshly-built cellXfs.
Versie 2.29.1
- Fixed two XLSX rendering regressions exposed by ApiTour demo: (1) cellen inside a row could be emitted out of column order when a bereik.SetBorders call toegevoegd cellen in non-monotonic order (e.g. outline pass creates A8/C8, inside pass creates B8 -- output was A8 / C8 / B8 / instead of A8 / B8 / C8 / so Excel reported "Office has detected a problem with this file" and forced Protected View). The XLSX writer now sorts each row's cellen by column before emission, matching the OOXML CT_Row schema. (2) cellen that set 2 or more stijl indices simultaneously (Font + Fill + Border, etc.) used to be collapsed to a single-dim cellXf via priority chain (FontIndex won, Border / Fill were dropped), so e.g. a header row with FontIndex + FillIndex + BorderIndex set on a bereik[..].SetBorders rendered without the borders. The writer now collects a composite cellXf pool during SaveAs and routes multi-dim cellen to a synthesized cellXf that behoudt every dimension.
Versie 2.29.0
- Renamed the internal hulp unit `lxList2` to `lxKeyList` and renamed `lxList`'s WideString-key classes from `TXLSKeyList` / `TXLSKeyEntry` / `TXLSKeyArray` to `TXLSStringKeyList` / `TXLSStringKeyEntry` / `TXLSStringKeyArray` so the unit name matches its main class `TXLSObjectKeyList` and the two key-list generations are self-describing (`TXLSStringKey*` for the legacy WideString-key pool, `TXLSObjectKey*` for the THashtableKey-based dedup pool). If your code references the old unit name or class names, update your uses clauses and type names accordingly.
Versie 2.28.3
- Fixed an XLSX cel-emit regression that caused borders set on otherwise-empty rows to disappear. `bereik[''A3:C10''].SetBorders(xlsxEdgeOutline,...)` on a sheet whose row 8 carried no data used to render the C/D vertical grid line broken across that row because the writer skipped any cel whose Value was unassigned -- even when the cel had a BorderIndex / FontIndex / FillIndex / NumberFormatIndex / AlignmentIndex / ProtectionIndex assigned. The writer now emits `
` for valueless cellen that carry any stijl index.
Versie 2.28.2
- Fixed an XLSX werkblad schema violation that caused Excel to refuse loading sheets which combined merged cellen with AutoFilter. The XLSX writer now emits the <autoFilter> element before <mergeCells>, matching the OOXML CT_werkblad sequence (autoFilter is #11, mergeCells is #15). Previously such werkmappen triggered Excel's repair dialog with `Load error. Line 1, column 0` on sheet1.xml and recovery would also drop tableParts / autoFilter from sibling Details sheets.
Versie 2.28.1
- toegevoegd convenience APIs to the classic XLS facade. IXLSRange now exposes lezen-only Width and WidthInPixels hulpen plus SaveAsCSV(FileName); IXLSWorksheet and IXLSWorkbook now expose SaveAsCSV(FileName / Stream) overloads for the used bereik or active sheet; IXLSPageSetup now exposes Order, Draft, BlackAndWhite, PrintNotes, and lezen-only IsFitToPages. SETUP record opslaan/openen behoudt nu those print flags.
Versie 2.28.0
- toegevoegd RTF export on TXLSXWorkbook. New SaveAsRTF overloads (FileName / Stream x default-active-sheet / explicit SheetIndex) schrijven the chosen sheet as an RTF 1.6 document containing a plain tabel. Column widths are derived from the sheet's ColWidth data (1 Excel character unit is approximated as 96 RTF twips); columns without explicit widths fall back to StandardWidth if set, otherwise to 809 twips (~8.43 chars). Per-cel bold (\\b), italic (\\i), and font size (\\fsN in half-points) are applied from the cel's FontIndex. Non-ASCII characters are encoded as signed-16-bit RTF \\uN? unicode escapes per RTF 1.6 §2.4.2, covering the full BMP bereik. Merged cellen are not spanned — origin cellen carry the content and non-origin cellen within the bereik are emitted as empty cellen. Default SheetIndex schrijft the active sheet; out-of-bereik returns -1. Empty sheets produce a minimal valid RTF document.
Versie 2.27.0
- toegevoegd HTML export on TXLSXWorkbook. New SaveAsHTML overloads (FileName / Stream x default-active-sheet / explicit SheetIndex) schrijven the chosen sheet as a UTF-8 HTML document with a UTF-8 BOM. Output is a single <tabel> inside a minimal HTML page. Merged cellen are expressed as colspan / rowspan attributes. cel styling is emitted as inline CSS: font family, size (pt), bold (font-weight:bold), italic (font-stijl:italic), strikethrough (text-decoration:line-through), and explicit font color; solid-pattern fill foreground color as background-color; horizontal alignment (left / center / right / justify) and WrapText (white-space:pre-wrap). Date variant values render as 'yyyy-mm-dd hh:nn:ss'; rich-text cellen flatten to their concatenated run text. Theme colors are silently skipped (no theme1.xml resolution in the simple HTML export). Default SheetIndex schrijft the active sheet; out-of-bereik returns -1.
Versie 2.26.0
- toegevoegd theme color + indexed color + tint/shade ondersteuning on TXLSXFont, TXLSXFill, and TXLSXBorderEdge. Each color slot now carries three new fields beside the existing RGB Color: ColorTheme (Integer; -1 = unset; 0..11 = OOXML theme slot), ColorIndex (Integer; -1 = unset; 0..63 = OOXML legacy palette slot — pairs with werkmap.IndexedColor[N] and XlsxDefaultIndexedPalette), and TintAndShade (Double in [-1.0, 1.0]; only emitted with theme). TXLSXFill exposes Foreground / Background variants of all three. Writer priority: theme > indexed > rgb; the older "ColorIsAuto = True" path keeps suppressing the element entirely. SaveAs and openen rondreis the full <color theme="N" tint="..."/> and <color indexed="N"/> attribute sets on font / fill / border colors. Bookkeeping: TXLSXBorders.LookupOrAdd now compares all three new fields so theme-colored borders don't collide with rgb-colored entries in the pool.
Versie 2.25.0
- toegevoegd external werkmap link rondreis on TXLSXWorkbook. New types: TXLSXExternalLink (Target URL + SheetNames list) + TXLSXExternalLinks collection. TXLSXWorkbook.ExternalLinks eigenschap exposes the collection; Add(Target) appends and returns a new link the caller fills out. SaveAs emits a werkmap-level <externalReferences> block in xl/werkmap.xml, an externalLink rel in xl/_rels/werkmap.xml.rels (tail of the rid bereik so existing rids stay stable), the xl/externalLinks/externalLink{N}.xml part per entry (<externalBook><sheetNames>) and its sibling .rels file pointing at the remote werkmap URL with TargetMode="External", plus matching ContentType Overrides. openen scans externalLink{N}.xml + .rels pairs starting at index 1 and stops at the first gap. The current release round-trips Target URL + SheetNames only; cached cel values inside <sheetDataSet> are not preserved.
Versie 2.24.0
- toegevoegd composing border hulp TXLSXRange.SetBorders. New TXLSXBorderEdgeKind enum (xlsxEdgeAll / Outline / Inside / InsideHorizontal / InsideVertical / Top / Bottom / Left / Right / DiagonalUp / DiagonalDown) selects which edges to schrijven. SetBorders(Kind, stijl, Color) / SetBorders(Kind, stijl) (defaults to opaque black) iterates every cel in the bereik, computes the edge mask per cel position (corner cellen get two outline edges, edge cellen get one, interior cellen get inside grid lines, etc.), composes stijl + Color onto a clone of the cel's current border (so successive Outline + Inside calls stack instead of overwriting), then does a werkmap-level lookup-or-add on werkmap.Borders and schrijft the resulting 1-based BorderIndex back on the cel. New TXLSXBorders.LookupOrAdd hulp returns 0 for empty borders so the pool never bloats with no-op entries.
Versie 2.23.0
- toegevoegd CSV export overloads on TXLSXWorkbook. New entry points: SaveAsCSV(FileName) / SaveAsCSV(FileName, SheetIndex, Delimiter) / SaveAsCSV(Stream) / SaveAsCSV(Stream, SheetIndex, Delimiter) schrijven the chosen sheet's populated extent as UTF-8 with leading BOM and CRLF line terminators. Default variants pick the active sheet and comma delimiter; the SheetIndex/Delimiter overload accepts any WideChar (commonly tab #9 for TSV). Field quoting follows RFC 4180 — values containing the delimiter, double quote, CR or LF are wrapped in quotes with embedded quotes doubled. Date values render as 'yyyy-mm-dd hh:nn:ss'; rich-text cellen flatten to the concatenated run text; empty cellen in the interior of the bounding rectangle render as bare delimiters and the row stops at the last populated column.
Versie 2.22.0
- toegevoegd werkmap-level indexed color palette overrides on TXLSXWorkbook. New entry points: IndexedColor[Index: Integer]: LongWord (lezen/schrijven, valid slots 0..63, ARGB LongWord), HasCustomIndexedColor(Index): Boolean (reports whether the caller has overridden a slot), CustomIndexedColorCount: Integer (number of overridden slots; 0 = palette emits as default), ResetIndexedColors: procedure (discard every override). The new XlsxDefaultIndexedPalette constant exposes the OOXML legacy ECMA-376 palette for slots 0..63. SaveAs emits <colors><indexedColors> with all 64 <rgbColor> children only when at least one slot has been overridden; untouched slots fall back to the default palette so files re-saved without changes stay clean. openen parses the block and silently drops slots whose value matches the default so round-trips stay minimal. Out-of-bereik slot assignments (< 0 or > 63) are dropped instead of raising.
Versie 2.21.0
- toegevoegd six sheet-view display eigenschappen on TXLSXWorksheet. Zoom: Integer is the zoom percent shown in Excel's status bar (10..400, default 100; out-of-bereik assignments clamp on schrijven). DisplayGridLines / DisplayZeros: Boolean (default True) hide cel grid lines or render zero-valued cellen as empty when set False. DisplayRightToLeft: Boolean (default False) flips the sheet to RTL layout for Arabic / Hebrew / etc. StandardWidth / StandardHeight: Double set the default column width (Excel character units) / default row height (points); 0 = unset, in which case Excel applies its built-in 8.43 / 15 defaults. SaveAs emits <sheetView showGridLines / showZeros / rightToLeft / zoomScale> and <sheetFormatPr defaultColWidth / defaultRowHeight> only when the values differ from the Excel defaults; openen parses them back. Existing freeze-pane + tab-geselecteerde handling on <sheetView> is unchanged and now shares a single emitter.
Versie 2.20.7
- toegevoegd TStream overloads on TXLSXWorkbook for in-memory serialization. New entry points: SaveAs(Stream: TStream) / SaveAs(Stream: TStream; FileFormat: TXLSXFileFormat) schrijven the entire .xlsx package into the given stream starting at the current position; openen(Stream: TStream) leest it back. The caller owns the stream and must Free it. Useful for HTTP responses, blob storage, in-memory pipelines, and unit tests that bypass the local file system. The existing file-based SaveAs / openen overloads are unchanged and now delegate to the same internal schrijven / lezen hulpen.
Versie 2.20.6
- toegevoegd Hidden / Visible / Comment eigenschappen to TXLSXDefinedName. Hidden maps to the OOXML <definedName hidden="1"/> attribute (defaults False / Visible=True; True hides the name from Excel's Name Manager UI). Visible is a Boolean alias (inverse of Hidden) for clearer call-site code. Comment maps to <definedName comment="..."/>. SaveAs emits both attributes when they differ from defaults; openen parses them back. SheetIndex (the existing Local scope binding via localSheetId) is unchanged.
Versie 2.20.5
- toegevoegd five more font traits to TXLSXFont. New TXLSXFontVertAlign enum (xlsxVertAlignBaseline / Superscript / Subscript) drives the existing Excel "Superscript" / "Subscript" font checkboxes via a single VertAlign eigenschap (mutually exclusive in the UI). New Boolean OutlineFont and Shadow eigenschappen for the matching Excel font effects. New Integer Family (OOXML font-family number: 1=Roman / 2=Swiss / 3=Modern / 4=Script / 5=Decorative; 0=unset) and CharSet (GDI charset number: 0=ANSI / 1=Default / 134=GB2312 / 136=ChineseBig5 / etc.; -1=unset). SaveAs emits the matching <vertAlign> / <outline/> / <shadow/> / <family> / <charset> children inside <font>; openen parses them back. ColorIndex / ThemeColor / TintAndShade are deferred to the upcoming theme milestone.
Versie 2.20.4
- toegevoegd border diagonal direction toggles. TXLSXBorder now exposes DiagonalUp: Boolean and DiagonalDown: Boolean. The two flags share the existing Diagonal edge's stijl and Color and pick which diagonal direction(s) Excel renders — up-only (bottom-left to top-right), down-only (top-left to bottom-right), or both. SaveAs emits diagonalUp / diagonalDown attributes on the <border> element when set; openen parses them back. Previously the engine wrote one Diagonal edge with no direction control, so Excel never drew either diagonal line.
Versie 2.20.3
- toegevoegd werkmap Date1904 toggle. TXLSXWorkbook now exposes a Date1904: Boolean eigenschap that selects between the Windows 1900 epoch (default; matches Excel for Windows) and the Mac 1904 epoch (Excel for Mac legacy). SaveAs emits <workbookPr date1904="1"/> in xl/werkmap.xml when set; openen leest it back. The flag is metadata only — the engine does not transform stored serials; callers must set Date1904 before assigning TDateTime cel values so the rondreis lands on the right calendar.
Versie 2.20.2
- toegevoegd auto-filter per-column criteria ondersteuning. New types: TXLSXAutoFilterOp enum (Equal / NotEqual / GreaterThan / LessThan / GreaterOrEqual / LessOrEqual), TXLSXAutoFilterColumn class (ColId + 1 or 2 criteria + AND/OR connector), TXLSXAutoFilterColumns collection. TXLSXWorksheet exposes AutoFilterColumns eigenschap and AddAutoFilterColumn(ColId, Op, Criteria) / AddAutoFilterColumn(ColId, Op1, Criteria1, Op2, Criteria2, AndConnector) / ClearAutoFilterColumns convenience methoden. SaveAs expands the existing <autoFilter ref="..."/> into a body of <filterColumn colId=N><customFilters and=0|1><customFilter operator="..." val="..."/>...</customFilters></filterColumn> per column when criteria are set; openen parses the same structure back. Previously the engine only stored the autofilter bereik (sqref) and Excel showed empty filter dropdowns.
Versie 2.20.1
- toegevoegd manual page break ondersteuning on TXLSXWorksheet. New entries: AddRowBreak(BeforeRow) / AddColBreak(BeforeCol) to insert a horizontal or vertical page break before a given row / column (Excel UI "Before" semantics — row N starts a new page). HasRowBreak / HasColBreak check; RemoveRowBreak / RemoveColBreak drop a single entry; ClearRowBreaks / ClearColBreaks / ClearAllPageBreaks bulk-clear. RowBreakCount / ColBreakCount + indexed RowBreaks(Index) / ColBreaks(Index) expose the stored 1-based "Before" indices for iteration. SaveAs emits <rowBreaks> / <colBreaks> with <brk id="N-1" max="..." man="1"/> children between <headerFooter> and <drawing>; openen parses them back.
Versie 2.20.0
- toegevoegd sheet visibility (Hidden / VeryHidden), per-sheet selection and active-sheet tracking on TXLSXWorkbook / TXLSXSheets / TXLSXWorksheet. New types: TXLSXSheetVisibility enum (xlsxSheetVisible / xlsxSheetHidden / xlsxSheetVeryHidden). New TXLSXWorksheet eigenschappen: Visibility, Visible (Boolean alias), IsSelected (lezen-only). New TXLSXSheets members: ActiveIndex, Activate(Index), Move(FromIndex, ToIndex). New TXLSXWorkbook.ActiveSheet proxy. SaveAs emits <sheet state="..."/> on the werkmap's sheet entries, <bookViews><workbookView activeTab=N/></bookViews> when the active sheet is not the default 0, and tabSelected="1" on the active sheet's <sheetView>; openen parses all three back into the new eigenschappen. The first toegevoegd sheet becomes both visible and active by default so existing call sites continue to work.
Versie 2.19.2
- toegevoegd four more PageSetup attribute toggles on TXLSXWorksheet to round out the OOXML <pageSetup> coverage: BlackAndWhite (B/W rendering), Draft (suppress graphics for faster preview), PrintNotes (print cel comments as displayed instead of hiding them), and PrintOverThenDown (left-to-right rows first instead of the default top-to-bottom columns first traversal). SaveAs emits the matching blackAndWhite / draft / cellComments / pageOrder attributes; openen parses them back. Defaults stay off so unchanged werkbladen do not gain extra attributes.
Versie 2.19.1
- toegevoegd three-part header and footer convenience eigenschappen to TXLSXWorksheet. New entries: LeftHeader / CenterHeader / RightHeader and LeftFooter / CenterFooter / RightFooter. Each leest or schrijft the matching &L / &C / &R segment of the existing HeaderText / FooterText raw string; writing any one segment rebuilds the full raw form so the rondreis writer and reader keep working without changes.
- toegevoegd print-option toggles for sheet-level page output. New TXLSXWorksheet eigenschappen: CenterHorizontally, CenterVertically, PrintGridlines, PrintHeadings. SaveAs emits a <printOptions horizontalCentered / verticalCentered / gridLines / headings/> element when any of the four is enabled; openen parses the same attributes back. Defaults stay off so unchanged werkbladen do not gain an extra <printOptions/> element.
- toegevoegd per-sheet PrintArea, PrintTitleRows and PrintTitleCols rondreis. These map to the OOXML built-in werkmap-level _xlnm.Print_Area and _xlnm.Print_Titles defined names scoped via localSheetId. PrintArea takes a bare A1 reference (e.g. "$A$1:$D$10"); PrintTitleRows and PrintTitleCols take row-only or column-only references (e.g. "$1:$3" or "$A:$B") and combine into a single Print_Titles entry. The writer prepends the sheet name with proper quoting (single quotes around names that contain spaces or special chars); the reader strips the prefix and routes the entries back into the matching sheet so they do not leak into the user-facing TXLSXWorkbook.DefinedNames collection.
Versie 2.19.0
- toegevoegd row / column insert and delete operations with full sheet-wide shift on TXLSXWorksheet. New entries: InsertRows(BeforeRow, Count), DeleteRows(StartRow, Count), InsertCols(BeforeCol, Count), DeleteCols(StartCol, Count). InsertRows / InsertCols push existing rows / columns away from the cut by Count; DeleteRows / DeleteCols drop the [Start, Start+Count-1] band and pull everything past the cut back by Count.
- The shift applies across every piece of sheet geometry that depends on row / column position: cel anchors (cellen), merged-bereik corners (MergedCells — straddling bereiken are clipped to the surviving edges and inside-only bereiken are removed), the row / column metadata lists (FRowHeights / FColWidths / outline levels / hidden / collapsed), Hyperlink and Comment anchors (entries inside a deleted band are removed), FreezePane (FFreezeRow / FFreezeCol), AutoFilterRange, and the per-entry bereik string on every ConditionalFormat, DataValidation, and Excel tabel (an entry whose bereik falls entirely inside the cut is removed).
- New Delete(Index) members on the supporting collections so the shift logic can remove a single entry without a Clear: TXLSXHyperlinks, TXLSXComments, TXLSXConditionalFormats, TXLSXDataValidations, TXLSXTables.
- Out of scope in this release: Images and Charts are not shifted (their EMU pixel anchors decouple them from the cel grid and a faithful shift would require recomputing the EMU offsets); werkmap-level DefinedNames formules are not rewritten. Both are tracked for a follow-up release.
Versie 2.18.2
- toegevoegd AutoFit hulpen for column widths and row heights. TXLSXWorksheet exposes AutoFitColumn(ACol) / AutoFitColumns(ColMin, ColMax) and AutoFitRow(ARow) / AutoFitRows(RowMin, RowMax); TXLSXRange exposes AutoFitColumns and AutoFitRows that forward to the werkblad over the bereik's bounds. Width is estimated in Excel character units (Calibri 11pt baseline; ASCII counts 1, CJK characters count 2) with a 1.20 px-per-char correction and 1.0 padding, clamped to [8.43, 255.0]. Row height defaults to 15 pt and grows by 12.75 pt per embedded newline in the cel text. Wide bereiken (EntireRow / EntireColumn) are clamped to the last cel-bearing row / column on the werkblad so AutoFit does not iterate to the Excel grid limits.
Versie 2.18.1
- toegevoegd per-cel protection rondreis to the XLSX engine. TXLSXCell exposes new Locked: Boolean (default True) and FormulaHidden: Boolean (default False) convenience eigenschappen that mirror Excel's cel-protection model. They surface the pool index TXLSXCell.ProtectionIndex (1-based into the new werkmap-level TXLSXProtections pool); writing the convenience eigenschap looks up or appends the (Locked, FormulaHidden) pair in the pool. Defaults (Locked=True, FormulaHidden=False) collapse to ProtectionIndex=0 so the pool stays empty for stock cellen.
- toegevoegd TXLSXRange.SetLocked(ALocked) and TXLSXRange.SetFormulaHidden(AHidden) batch hulpen so unlocking or hiding a whole bereik only does one pool lookup-or-add and applies the result to every cel in the rectangle.
- toegevoegd the matching writer / reader plumbing. SaveAs emits one cellXf with an inline <protection locked="N" hidden="M"/> child per werkmap Protections entry (after the alignment block); openen parses <protection> back into werkmap.Protections and threads the new CellXfProtMap through ParseStylesXml and ParseWorksheetXml so per-cel ProtectionIndex round-trips alongside the existing font / fill / border / number-format / alignment indices.
Versie 2.18.0
- toegevoegd TXLSXRange object for multi-cel access and batch operations on TXLSXWorksheet. New entry points: werkblad.bereik['A1:C5'], werkblad.RCRange[r1,c1,r2,c2], werkblad.UsedRange, werkblad.EntireRow(r), werkblad.EntireColumn(c). The returned bereik exposes SetValue / SetFormula / Clear / ClearAll / Merge / Unmerge / Offset / Resize plus per-cel stijl index setters (SetFontIndex / SetFillIndex / SetBorderIndex / SetNumberFormatIndex / SetAlignmentIndex) and a SetNumberFormat(Fmt) convenience that looks up or appends the format string in the werkmap pool. TXLSXRange objects are owned by the werkblad and released on werkblad destruction; callers do not free them.
- toegevoegd TXLSXCell.NumberFormat: WideString convenience that pairs with the existing NumberFormatIndex. Reading returns the format string from the werkmap pool; writing looks up or voegt toe the string and updates NumberFormatIndex transparently. Requires the cel to be attached to a werkmap (the standard flow through TXLSXWorkbook.Sheets.Add(...).cellen[r, c]).
- toegevoegd cel -> sheet -> werkmap back-references so each TXLSXCell can resolve its owning werkmap without external bookkeeping. TXLSXSheets, TXLSXWorksheet, and TXLSXCells gained internal Owner references wired through their constructors; TXLSXCell exposes a lezen-only werkmap eigenschap and an internal SetWorkbook used by TXLSXCells.GetItem when auto-creating a cel on access.
Versie 2.17.42
- Fixed XLSX cel rondreis on reopen. cellen written by SaveAs were being dropped on openen, with HasCell(row, col) returning False and all cel-level state (value, formule, font index, fill index, border index, number format index) lost. The root cause was a spurious MoveToAttribute('r') call in the werkblad parser that flipped the reader's node type to attribute, which then made the subsequent IsEmptyElement check return True and shut off cel parsing for every <c> element with an r="" attribute (i.e. every cel). Removing the unnecessary cursor move restores text, numeric, formule, and date cel rondreis together.
- Fixed XLSX stijl index restore on reopen. aangepaste font, fill, border, and number-format indices on cellen were reading back as zero even after the matching pools (werkmap.Fonts/Fills/Borders/NumberFormats) round-tripped correctly. The cellXf parser tracked its position with a counter that only advanced on the </xf> end tag, but Excel commonly emits self-closing <xf .../> entries (no inner <alignment>), so the counter never moved past zero and every cellXf mapping clobbered the previous one. The parser now advances the counter on a self-closing <xf/> too, so per-cel FontIndex / FillIndex / BorderIndex / NumberFormatIndex rondreis.
- Fixed XLSX date cel rondreis. Writing a TDateTime to TXLSXCell.Value used to route through the shared-string pool with t="s" because Delphi's VarIsNumeric() returns False for varDate; SaveAs now schrijft the date serial number into <v> directly and applies the date cellXf, so date cellen reopen as a varDate Variant instead of a localized string that the caller could not coerce back to TDateTime.
Versie 2.17.41
- Fixed "zlib stream does not ondersteuning seeking" error raised when reopening .xlsx files that contain embedded images or a VBA project (.xlsm). The image-reload path and the VBA-payload reload path both routed the inflated entry stream through TMemoryStream.CopyFrom(Source, 0), which internally rewinds Source to derive the byte count; the rewind is not legal on a forward-only Deflate stream. Both call sites now use a chunked lezen-until-EOF hulp, so .xlsx files with images or macros rondreis through SaveAs/openen without raising.
Versie 2.17.40
- toegevoegd chart-sheet (full-page chart werkblad) ondersteuning to the XLSX engine. TXLSXWorksheet exposes a new IsChartSheet flag plus a werkmap-level werkmap.AddChartSheet(Name, ChartType, Title) hulp that creates the sheet, flips the flag, and seeds Charts[0] with a sensible default anchor. SaveAs schrijft IsChartSheet sheets to xl/chartsheets/sheetN.xml with a dedicated rels file pointing at the shared drawing part, registers them as chartsheet content-types, and emits the chartsheet relationship in xl/_rels/werkmap.xml.rels. Regular werkbladen keep their existing xl/werkbladen/sheetN.xml path. openen recognizes chartsheets via the relationship type but currently loads them as plain werkbladen (their chart data still arrives via the shared chart parts).
Versie 2.17.39
- toegevoegd collapsed row / collapsed column rondreis for outline groups in the XLSX engine. TXLSXWorksheet exposes RowCollapsed[Row] and ColCollapsed[Col] Boolean eigenschappen along with SetRowCollapsed / SetColCollapsed / ClearRowCollapsed / ClearColCollapsed hulpen. SaveAs emits collapsed="1" on the matching <row> and <col> entries; openen parses the attribute back. Together with the existing outlineLevel and hidden attributes, this lets the XLSX engine rondreis a fully collapsed grouping hierarchy.
Versie 2.17.38
- toegevoegd hidden row / hidden column rondreis to the XLSX engine. TXLSXWorksheet exposes RowHidden[Row] and ColHidden[Col] Boolean eigenschappen along with SetRowHidden / SetColHidden / ClearRowHidden / ClearColHidden hulpen. SaveAs emits hidden="1" on the matching <row> and <col> entries; openen parses the attribute back into the werkblad so hidden rows / columns survive the rondreis without forcing a aangepaste width or outline level.
Versie 2.17.37
- toegevoegd werkblad tab color rondreis to the XLSX engine. TXLSXWorksheet exposes TabColor (ARGB) and TabColorIsAuto eigenschappen. SaveAs emits a <sheetPr><tabColor rgb="..."/></sheetPr> block as the first child of <werkblad> when the tab color is set; openen parses <tabColor> back into the werkblad so colored sheet tabs survive the rondreis. Default werkmappen stay free of the extra block (TabColorIsAuto = True).
Versie 2.17.36
- toegevoegd cel alignment rondreis to the XLSX engine. New TXLSXHorizontalAlignment and TXLSXVerticalAlignment token enums, TXLSXAlignment class (Horizontal, Vertical, WrapText, ShrinkToFit, Indent, TextRotation), and a werkmap-level TXLSXAlignments collection (werkmap.Alignments). TXLSXCell now carries an AlignmentIndex (1-based into werkmap.Alignments). SaveAs appends one cellXf with an inline <alignment/> child per werkmap alignment entry; openen leest <alignment> attributes back into werkmap.Alignments and maps the cellXf back to TXLSXCell.AlignmentIndex. ParseWorksheetXml and ParseStylesXml grew a CellXfAlignMap parameter to carry the mapping across the two phases.
Versie 2.17.35
- toegevoegd the AES encryption (ECMA-376 Standard Encryption) API surface to the XLSX engine. TXLSXWorkbook exposes SaveAsEncrypted(FileName, Password) / OpenEncrypted(FileName, Password) / CanReadEncrypted(FileName) plus a typed EXlsxEncryptionNotImplemented exception. CanReadEncrypted recognizes the Microsoft Compound File Binary magic bytes ($D0 $CF $11 $E0 $A1 $B1 $1A $E1) so callers can detect encrypted archives before deciding how to openen them; OpenEncrypted transparently falls back to plain openen for unencrypted .xlsx files. The AES-128/256 + SHA + OLE Compound File pipeline itself is not yet wired up — both schrijven and lezen of actually-encrypted archives raise the typed exception until the follow-up release lands the algorithm. The exception type is deliberately distinct so existing callers can catch it and fall back to werkblad.Protect / werkmap.ProtectWorkbook for the visual lock.
Versie 2.17.34
- Performance: replaced the O(N^2) WideString concatenation that built each werkblad's cel rows with a TXLSWideStringBuilder. Large sheets (10k+ cellen) now stay linear in memory and CPU on SaveAs. toegevoegd a new WriteWorksheetXmlStreaming hulp and a TXLSXWorkbook.StreamingWrite opt-in flag — when enabled, SaveAs no longer holds every werkblad's XML in a sheetXmls cache at the same time; each werkblad is built, written, and dropped before moving to the next. sharedStrings.xml is emitted last so the streaming path still produces a fully-populated SST. Default behavior unchanged.
Versie 2.17.33
- toegevoegd cel-bereik operations to the XLSX engine. TXLSXWorksheet exposes ClearRange(R1, C1, R2, C2), CopyRange(SrcR1, SrcC1, SrcR2, SrcC2, DstR, DstC) for in-sheet copy, CopyRangeTo(... TargetSheet, DstR, DstC) for cross-sheet copy, and MoveRange(SrcR1, SrcC1, SrcR2, SrcC2, DstR, DstC) for cut-and-paste. Each operation duplicates the cel value, formule, four stijl indices, and any rich-text payload; MoveRange skips overlap with the destination so partial overlaps still behouden their copied values. TXLSXCells also gains a Remove(Row, Col) hulp.
Versie 2.17.32
- toegevoegd internal hyperlink anchors to the XLSX engine. TXLSXHyperlink now carries a Location eigenschap (e.g. "Sheet2!A1") and an IsInternal hulp; TXLSXHyperlinks exposes AddInternal, and TXLSXWorksheet voegt toe three AddHyperlinkToCell overloads. SaveAs emits internal hyperlinks with the inline location="" attribute and skips the werkblad rels entry; openen recognizes location="" hyperlinks and routes them back through AddInternal. External URL hyperlinks continue to flow through the rels file unchanged.
Versie 2.17.31
- toegevoegd rich-text rondreis to the XLSX engine. New TXLSXRichTextRun class (per-run Name / Size / Bold / Italic / Strikethrough / Underline / Color) and TXLSXRichText container that exposes AddRun / AddRunText / Clear / PlainText. TXLSXCell now carries an owned RichText eigenschap; SaveAs schrijft the cel as a shared-string with multiple <r>/<rPr>/<t> runs and openen rebuilds the TXLSXRichText from the parsed SST entry, with the cel's Variant Value still surfacing the concatenated plain text for callers that ignore formatting.
Versie 2.17.30
- toegevoegd chart rondreis to the XLSX engine. New TXLSXChartType enum (column / bar / line / pie), TXLSXChartSeries (Name, CategoriesRange, ValuesRange), and TXLSXChart (ChartType, Title, axis titles, From/To anchor cellen, Series) classes plus a per-werkblad TXLSXCharts collection (werkblad.Charts). TXLSXWorksheet exposes AddChart(Type, Title, FromRow, FromCol, ToRow, ToCol). SaveAs emits xl/charts/chartN.xml (werkmap-global numbering) and binds it to a twoCellAnchor / graphicFrame inside the shared xl/drawings/drawingN.xml; openen parses both the anchor and the chart definition back into the collection. Chart titles, axis titles, series names and source bereiken rondreis.
Versie 2.17.29
- Fixed an EListError "Operation not allowed on sorted list" raised by SetColWidth, SetRowHeight, SetRowOutlineLevel, and SetColOutlineLevel. Each of those four TStringList fields was created with Sorted=True but written through the Values[Name] := X setter, which RAD Studio's RTL refuses on a sorted list. The lists are now created unsorted; lookups continue to go through IndexOfName, which is fine at typical per-sheet column / row counts.
Versie 2.17.28
- Fixed TZipArchive.Exists, which was a stub that always returned false. The XLSX openen path uses zip.Exists(...) to gate every part lezen, so every previously-claimed rondreis (cellen, stijlen, comments, drawings, doc props, defined names, protection, VBA, etc.) silently dropped its content on lezen. Exists now delegates to the existing Fcd.Entries.Exists lookup, matching the OpenFile / CreateFile pattern.
Versie 2.17.27
- toegevoegd VBA project preservation to the XLSX engine. TXLSXWorkbook exposes a VbaProject byte payload plus LoadVbaProjectFromFile(FileName), ClearVbaProject, and HasVbaProject hulpen. SaveAs schrijft the bytes to xl/vbaProject.bin, registers the .bin content-type, switches the werkmap content-type to the macro-enabled variant, and voegt toe a vbaProject relationship to the werkmap rels file; openen leest xl/vbaProject.bin back into the eigenschap. The bytes are not parsed or modified, so existing .xlsm projects rondreis exactly. Note: macro-enabled werkmappen must be saved with a .xlsm extension for Excel to enable macros.
Versie 2.17.26
- toegevoegd werkmap and sheet protection to the XLSX engine. TXLSXWorksheet exposes Protect / Protect(Password) / UnProtect plus IsProtected and SheetProtectHash; TXLSXWorkbook voegt toe ProtectWorkbook (with optional password, LockStructure, LockWindows flags) and UnProtectWorkbook plus IsWorkbookProtected / WorkbookProtectHash / LockStructure / LockWindows. SaveAs emits <sheetProtection> on each protected werkblad and <workbookProtection> on protected werkmappen; openen parses both blocks back into the API. Passwords are stored as the standard 4-hex legacy hash for rondreis fidelity (the original plaintext is not recoverable).
Versie 2.17.25
- toegevoegd document-eigenschap rondreis to the XLSX engine. TXLSXWorkbook now exposes Title, Author, Subject, Keywords, Description, Category, LastModifiedBy, Created, Modified, Company, Application, and AppVersion eigenschappen. SaveAs emits docProps/core.xml and docProps/app.xml (and registers them in [Content_Types].xml + _rels/.rels) when any eigenschap is touched; openen parses both files back so authors, modification stamps, and application metadata survive a opslaan-and-reopen.
Versie 2.17.24
- toegevoegd Excel-stijl tabel rondreis to the XLSX engine. New TXLSXTable class (Id, Name, DisplayName, bereik, Columns, StyleName, ShowFirstColumn / ShowLastColumn / ShowRowStripes / ShowColumnStripes) and a per-werkblad TXLSXTables collection. TXLSXWorksheet exposes tabellen plus AddTable(Name, bereik, ColumnNames). SaveAs emits xl/tabellen/tableN.xml (werkmap-global numbering), updates werkblad rels with tabel relationships, voegt toe <tableParts> to the werkblad, and registers the tabel content-type. openen parses tabel relationships and tableN.xml back into the werkblad so styled tabel bands survive a opslaan-and-reopen.
Versie 2.17.23
- toegevoegd auto-filter rondreis to the XLSX engine. TXLSXWorksheet exposes an AutoFilterRange eigenschap plus SetAutoFilter(Row1, Col1, Row2, Col2) / SetAutoFilter(bereik) / ClearAutoFilter hulpen. SaveAs emits <autoFilter ref="..."/> after the merge-cellen block when the bereik is non-empty; openen parses the ref back into the eigenschap so the filter band on a werkblad survives a opslaan-and-reopen.
Versie 2.17.22
- toegevoegd page-setup rondreis to the XLSX engine. TXLSXWorksheet exposes Margin{Left,Right,Top,Bottom,Header,Footer}, PageLandscape, PaperSize, PageScale, FitToWidth, FitToHeight, HeaderText, and FooterText eigenschappen plus SetPageMargins(L, R, T, B[, H, F]) convenience overloads. SaveAs emits the corresponding <pageMargins>, <pageSetup>, and <headerFooter> blocks between hyperlinks and drawings; openen parses them back. Default-only werkbladen stay untouched (PageSetupTouched flag gates output).
Versie 2.17.21
- toegevoegd freeze-pane rondreis to the XLSX engine. TXLSXWorksheet exposes FreezePane(Col, Row) / UnfreezePane methoden plus lezen-only FreezeCol and FreezeRow eigenschappen. SaveAs schrijft a <sheetViews>/<pane state="frozen"> block before <sheetData> with the matching activePane and selection; openen parses <pane state="frozen"> back into the freeze position so frozen-top/left/corner layouts survive a opslaan-and-reopen.
Versie 2.17.20
- toegevoegd row and column outline (grouping) levels to the XLSX engine. TXLSXWorksheet exposes RowOutlineLevel[Row] and ColOutlineLevel[Col] indexed eigenschappen plus SetRowOutlineLevel / HasRowOutlineLevel / ClearRowOutlineLevels and the matching column hulpen. SaveAs emits outlineLevel attributes on <row> entries and merged <col> entries (combined with aangepaste widths when present); openen parses both attributes back into the werkblad so grouped row/column hierarchies survive the rondreis.
Versie 2.17.19
- toegevoegd conditional formatting and data validation rondreis to the XLSX engine. New TXLSXCfOperator enum and TXLSXConditionalFormat class (bereik, Op, formule1, formule2) plus a TXLSXConditionalFormats collection on each werkblad (werkblad.ConditionalFormats). New TXLSXDataValidationType, TXLSXDvOperator, TXLSXDataValidation (bereik, ValidationType, Op, formule1, formule2, AllowBlank, ShowInputMessage, ShowErrorMessage), and a TXLSXDataValidations collection (werkblad.DataValidations) with an AddList(bereik, Items) shortcut for the common dropdown case. TXLSXWorksheet exposes AddConditionalFormat and AddDataValidation / AddListValidation hulpen. SaveAs schrijft <conditionalFormatting> blocks (with cfRule type="cellIs") and a <dataValidations> block after sheetData; openen parses both blocks back into the collections.
Versie 2.17.18
- toegevoegd defined-name rondreis to the XLSX engine. New TXLSXDefinedName class (Name, formule, SheetIndex) and a werkmap-level TXLSXDefinedNames collection (werkmap.DefinedNames) with Add(Name, formule[, SheetIndex]) overloads and IndexOfName lookup. SaveAs emits a <definedNames> block in xl/werkmap.xml; entries with SheetIndex >= 0 carry a localSheetId attribute (sheet-scoped) and entries with SheetIndex = -1 are werkmap-scoped. openen parses <definedName> elements back into the collection so saved-and-reopened werkmappen keep their named bereiken intact.
Versie 2.17.17
- toegevoegd image rondreis to the XLSX engine. New TXLSXImageFormat enum (png, jpeg, gif, bmp), TXLSXImage class (Row/Col anchor, WidthEMU/HeightEMU, Format, Data), and a per-werkblad TXLSXImages collection. TXLSXWorksheet exposes Images plus AddImage(Row, Col, Data, Format) and AddImageFromFile(Row, Col, FileName) hulpen. SaveAs schrijft the image bytes into xl/media/imageN.<ext>, generates xl/drawings/drawingN.xml with a oneCellAnchor per image (and a matching _rels file), registers content types and werkblad/drawing relationships, and emits a <drawing r:id="..."/> reference inside the werkblad. openen parses drawingN.xml + drawing rels + media to rondreis images back into werkblad.Images.
Versie 2.17.16
- toegevoegd aangepaste number-format rondreis to the XLSX engine. New TXLSXNumberFormat class and a werkmap-level TXLSXNumberFormats collection (werkmap.NumberFormats) deduplicate format codes via Add(FormatCode). TXLSXCell exposes a new NumberFormatIndex eigenschap; SaveAs emits a <numFmts> block in xl/stijlen.xml (aangepaste ids starting at the OOXML-reserved base 164) and pairs each format with a dedicated cellXf, openen parses aangepaste numFmts back and reverses the cellXf->numFmtId map into NumberFormatIndex on lezen. Precedence on conflict: FormatIndex > FontIndex > FillIndex > BorderIndex > NumberFormatIndex.
Versie 2.17.15
- toegevoegd cel-border rondreis to the XLSX engine. New TXLSXBorderStyle enum, TXLSXBorderEdge class (stijl + Color + ColorIsAuto for each side), TXLSXBorder class with Left/Right/Top/Bottom/Diagonal edges plus SetAll(stijl[, Color]) hulpen, and a werkmap-level TXLSXBorders collection (werkmap.Borders) with a Borders.AddBox(stijl[, Color]) shortcut. TXLSXCell exposes a new BorderIndex eigenschap; SaveAs emits each border into xl/stijlen.xml and pairs it with a dedicated cellXf, openen parses borders back and translates the cellXf->borderId map into BorderIndex on lezen. Precedence remains FormatIndex > FontIndex > FillIndex > BorderIndex when several are set on the same cel.
Versie 2.17.14
- toegevoegd cel-fill rondreis to the XLSX engine. New TXLSXFillPattern enum and TXLSXFill class describe patternType, fgColor, and bgColor; the werkmap-level TXLSXFills collection is reachable via werkmap.Fills, with a Fills.AddSolid(color) convenience for the common solid-color case. TXLSXCell exposes a new FillIndex eigenschap; SaveAs emits each fill into xl/stijlen.xml and pairs it with a dedicated cellXf, openen parses them back and reverses cel s attributes into FillIndex on lezen. FontIndex still takes precedence when both are set.
Versie 2.17.13
- Completed the XLSX font rondreis. openen now parses xl/stijlen.xml back into werkmap.Fonts and a cellXf->fontId tabel; each cel's s attribute is mapped back into TXLSXCell.FontIndex so saved-and-reopened werkmappen behouden aangepaste fonts (Name, Size, Bold, Italic, Strikethrough, Underline, Color).
Versie 2.17.12
- toegevoegd a TXLSXFont class plus a werkmap.Fonts collection so XLSX cellen can pick a aangepaste font. TXLSXCell carries a new FontIndex eigenschap; SaveAs emits the fonts list in xl/stijlen.xml and one cellXf per font, then references the matching cellXf from each cel's s attribute. openen rondreis of FontIndex is planned for the next release.
Versie 2.17.11
- toegevoegd row-height rondreis to the XLSX engine. TXLSXWorksheet exposes a RowHeight[Row] eigenschap plus SetRowHeight, HasRowHeight, and ClearRowHeights hulpen. SaveAs schrijft the ht and customHeight="1" attributes on each <row> with a customized height (including rows that only carry a height, with no cel data); openen leest the ht attribute back into the row-height map.
Versie 2.17.10
- toegevoegd column-width rondreis to the XLSX engine. TXLSXWorksheet exposes a ColWidth[Col] eigenschap along with SetColWidth, HasColWidth, and ClearColWidths hulpen. SaveAs emits a <cols> block with one <col> entry per customized column; openen replays <col min/max/width> entries back into the werkblad so unmodified widths fall back to the Excel default.
Versie 2.17.9
- toegevoegd cel-comment rondreis to the XLSX engine. TXLSXWorksheet exposes a Comments collection and AddComment(Row, Col, Text[, Author]) overloads. SaveAs emits xl/commentsN.xml (with deduplicated author list) and a companion xl/drawings/vmlDrawingN.vml so Excel can render the comment balloons; openen leest commentsN.xml back into the collection. werkblad rels, content types, and <legacyDrawing> wiring are handled automatically.
Versie 2.17.8
- toegevoegd hyperlink rondreis to the XLSX engine. TXLSXWorksheet exposes a Hyperlinks collection and AddHyperlink(Row, Col, Url[, Display[, Tooltip]]) overloads. SaveAs schrijft a <hyperlinks> block in each werkblad and emits a matching xl/werkbladen/_rels/sheetN.xml.rels file with the external URL targets; openen leest the werkblad rels first to resolve <hyperlink r:id="..."/> entries into URLs in the collection.
Versie 2.17.7
- toegevoegd merged-cel rondreis to the XLSX engine. TXLSXWorksheet exposes a MergedCells collection and a MergeCells(R1, C1, R2, C2) convenience methode that mirror the BIFF facade stijl. SaveAs emits a <mergeCells> block after sheetData, and openen parses <mergeCell ref="A1:B2"/> entries back into the collection.
Versie 2.17.6
- The XLSX engine now round-trips date values and formules. TDateTime cel values are serialized as Excel serial numbers and tagged with a built-in date cellXf so Excel renders them as dates; on openen, cellen whose stijl references the date cellXf are decoded back to TDateTime variants. TXLSXCell exposes a new formule eigenschap; SaveAs schrijft the formule as a <f> child element and openen parses <f> text back into the cel.
Versie 2.17.5
- toegevoegd a stijlen.xml scaffold to the XLSX engine. SaveAs now emits a minimum-valid xl/stijlen.xml with default fonts, fills, borders, cellStyleXfs, and cellXfs entries, plus the corresponding content-type and werkmap-relationship registrations. cellen carry a FormatIndex eigenschap and emit the s="N" cel attribute when non-zero, and openen leest s="N" back into FormatIndex. Concrete stijl descriptors (fonts, fills, borders, cellXfs as werkmap-level collections) will be toegevoegd in follow-up commits.
Versie 2.17.4
- toegevoegd shared strings (SST) ondersteuning to the XLSX engine. SaveAs builds a deduplicated string tabel and emits xl/sharedStrings.xml, replacing inline string emission. openen leest xl/sharedStrings.xml first and resolves t="s" cel references through the SST. Inline string cellen from third-party XLSX files are still accepted on openen.
Versie 2.17.3
- Replaced the cel record array on TXLSXWorksheet with TXLSXCell objects and a TXLSXCells collection. The cel-access call site now leest werkblad.cellen.Item[Row, Col].Value, matching the IXLSCells / IXLSRange shape on the BIFF facade. werkblad.cellen.HasCell / cellen.Count / cellen.CellByIndex / cellen.Clear are also available.
Versie 2.17.2
- Introduced the TXLSXSheets collection class on TXLSXWorkbook, mirroring the IXLSWorkSheets collection on the BIFF facade. Code now leest werkmap.Sheets.Add / werkmap.Sheets.Count / werkmap.Sheets[i] / werkmap.Sheets.IndexByName instead of the previous werkmap.AddSheet / werkmap.SheetCount / werkmap.Sheet[i] methoden.
Versie 2.17.1
- Renamed TXLSXWorkbook.SaveToFile to SaveAs and TXLSXWorkbook.LoadFromFile to openen, matching the existing IXLSWorkBook naming stijl. toegevoegd file-format and password overloads so the XLSX facade leest the same way as the BIFF facade. AddSheet now offers a no-argument overload that generates a default sheet name.
Versie 2.17.0
- TXLSXWorkbook.SaveAs produces a minimum OOXML .xlsx archive with cel values (numbers, booleans, and inline strings). The archive contains content types, root relationships, werkmap + relationships, and a werkblad per sheet.
- TXLSXWorkbook.openen leest back the minimum OOXML .xlsx archive — sheet names from xl/werkmap.xml and cel values from xl/werkbladen/sheetN.xml. Shared strings, stijlen, dates, and formules are not yet supported.
- toegevoegd OOXML namespace, content-type, and relationship constants plus reference / parsing / escape hulpen (XlsxColumnLabel, XlsxCellRef, XlsxColumnIndex, XlsxParseCellRef, XlsxParseRangeRef, XlsxEscapeText, XlsxEscapeAttr) for use by future XLSX features.
Versie 2.16.4
- The XLSX facade unit (lxHandleX) now defines its own werkmap and werkblad types (TXLSXWorkbook, TXLSXWorksheet), independent of the BIFF facade. opslaan and load entry points are reserved; the OOXML wiring will be filled in a follow-up release.
- toegevoegd a developer reference topic for the new XLSX facade, describing how lxHandle and lxHandleX coexist and which hulp units they share.
Versie 2.16.3
- Introduced
lxHandleX, a dedicated XLSX facade unit that lives alongside the existinglxHandleBIFF facade. The two units share the same underlying infrastructure (stijl pools, XML utilities, ZIP archive) but expose independent class hierarchies:lxHandleownsTXLSWorkBookand the classic XLS/HTML/RTF/CSV paths;lxHandleXwill ownTXLSXWorkbookand all XLSX-specific APIs. Three methode stubs accidentally toegevoegd tolxHandle(SetCodePage,GetColumnXFIndex,GetRowXFIndex) were removed to keep the BIFF facade’s public API identical to v2.15.0. Existing code thatuses lxHandlerequires no changes.
Versie 2.16.2
- toegevoegd three internal data-structure units completing the XLSX engine foundation:
lxAvlTreeprovides an O(log N) AVL tree (TAVLTree/TAVLNode) for sorted lookups;lxColsandlxRowsare column and row info containers with fine-grained deduplication and index rewriting, used by the XLSX engine’s per-sheet column-width and row-height maps. All three are dormant in this release and are activated in v2.17.0 when the XLSX lezen/schrijven engine is first enabled.
Versie 2.16.1
- toegevoegd six internal XML and ZIP utility units that complete the XLSX engine’s infrastructure layer:
lxWStream(wide-character file stream with file-existence check and AnsiString schrijven hulp);lxCacheStream(buffered stream wrapper that reduces underlying I/O calls);lxZlibStream(forward-only deflate/inflate stream, independent of the existingloZlibBIFF encryption binding);lxXmlReader(SAX-stijl pull reader for high-speed XML parsing);lxXmlWriter(streaming XML writer with element-name reuse);lxZipArchive(central-directory ZIP reader/writer with per-entry deflate streams). Together with the seven units from v2.16.0 these form the complete internal foundation for the XLSX engine.
Versie 2.16.0
- toegevoegd seven internal stijl-infrastructure units as the foundation for the upcoming XLSX engine:
lxHashTable(generic hash tabellen with integer, WideString, and object-key variants);lxKeyList(object-key list with fast lookup and index rewriting);lxStyleColor(Office theme color and palette slot manager);lxStyleFont,lxStyleFill, andlxStyleBorder(deduplicated pools for font, fill, and border stijlen covering all 12 BIFF line types and XLSX stijl mappings);lxStyleXf(aggregates all five stijl pools with a number-format list into a single XF record). All seven units are dormant in this release and do not affect existing XLS paths.
Versie 2.15.1
- toegevoegd
lxRgbcolor utility hulpen:RGBtoHLS,HLStoRGB,RGBTint, andGetRGBTintconvert between the RGB and HLS color spaces (0–240 HLS bereik). These underpin theme-color tint calculations, color-scale conditional formatting, and palette interpolation in XLSX output. - toegevoegd
lxStrBuilderhigh-performance string builders:TXLSStringBuilder(AnsiChar) andTXLSWideStringBuilder(WideChar) use pre-allocated, doubling-growth buffers to eliminate the per-concatenation memory reallocation of standard Pascal strings. The AnsiChar variant drives the XLSX XML serialization path; the WideChar variant handles wide-string assembly in the XLSX parser.
Versie 2.15.0
- Reworked the HtmlHelp reference into a web-ready structure with dedicated topic, asset, script, stijl, and source folders.
- toegevoegd a browser-friendly help home page and contents navigation page, with unified headers, topic shortcuts, and footers.