HotXLS versionsinformation
Versionshistorik för användarsynliga HotXLS-funktioner, korrigeringar, XLS/XLSX-förbättringar, exportuppdateringar, kompatibilitetsändringar och dokumentationsuppdateringar.
[Unreleased]
Version 2.88.111
- Classic XLS-kalkylblad stöder nu fristående ritlager-TextBoxar. Använd
TXLSShapes.AddTextBoxför att skapa enTXLSTextBoxmed eget rad-/kolumnankare, text, text runs, linje-/fyllningsformat och normal shape-borttagning utan att skapa en cellkommentar.
Version 2.88.110
- ApiTour-demona täcker nu fler mönster för workbook-automatisering. ApiTour-exemplen för Delphi och C++Builder visar callback-baserad områdesskrivning med
WriteCells, skanning av inlästa celler medForEachCell, malluppdateringar medFindTextochReplaceText, HTML-export av markerat område tillApiTour-Range.htmloch Delphi-callbacks för egna formler viaOnUserFunction.
Version 2.88.109
- QuickStart-demona visar nu en mer komplett första arbetsbok. Delphi- och C++Builder-exemplen skapar en formaterad multiplikationstabell med formler för rad- och kolumnsummor, låsta fönsterrutor och matchande XLS/XLSX-åtgärder; demoträdet innehåller nu även välformade HTML-readme-sidor för varje exempel.
Version 2.88.108
- XLSX områden har nu direkta hjälpare för HTML-export.
TXLSXRange.SaveAsHTML(FileName)andTXLSXRange.SaveAsHTML(Stream)export only the valt XLSX område as a UTF-8 HTML tabell, sharing the arbetsbok HTML renderer's escaping, basic stil output, and merged-cell span handling.
Version 2.88.107
- XLSX kalkylblad now include hjälpare för textsökning och ersättning.
TXLSXWorksheet.FindTextandTXLSXWorksheet.ReplaceTextscan inläst text celler in row-major order, skip formler and non-text values, and stöd optional case-sensitive matching for template workflows.
Version 2.88.106
- BIFF8 Window2 visningsflaggor bevarar nu anpassad rutnätslinje and fryst rutestatus. HotXLS now clears
fDefaultHdrwhenWindow2.icvHdrstores a anpassad rutnätslinje color, bevarar Excel-authoredfFrozenNoSplitduring öppna/spara, and skriverfFrozenNoSplitforFreezePanesoutput.
Version 2.88.105
- CF12 formeltrösklar now rundtur through BIFF8 Data Bar, Color Scale, and Icon Set rules. formel-based threshold values compile to CF12 formel token bytes on spara and are restored to
TXLSCfValue.Valuewhen a arbetsbok is reopened.
Version 2.88.104
- Classic XLS formler and icon-set thresholds now emit tighter BIFF8 records. Integer constants in formler use the compact
tInttoken when they fit the BIFF unsigned-integer område, andTXLSIconSetSpec.ThresholdEqualsInclude[Index]now controls the CF12 icon-set threshold equals byte so callers can choose include or exclude comparison semantics.
Version 2.88.103
- Classic XLS kalkylblad now include a text find hjälpare.
IXLSWorksheet.FindText(SearchText, Row, Col[, MatchCase])locates the first matching inläst text cell, skips formler and non-text celler, and clears the returned coordinates when no match is found.
Version 2.88.102
- Classic XLS kalkylblad now include a text replacement hjälpare.
IXLSWorksheet.ReplaceText(SearchText, ReplacementText[, MatchCase])replaces matches in inläst text celler, skips formler and non-text celler, and reports the changed cell count for template-filling workflows.
Version 2.88.101
- områden har nu direkta hjälpare för HTML-export.
IXLSRange.SaveAsHTML(FileName)andIXLSRange.SaveAsHTML(Stream)export the valt område through the existing HTML renderer, so callers no longer need to create aTXLSHTMLExportinstance or passxlHTMLexplicitly for common område fragments.
Version 2.88.100
TXLSWorkbook.GetSheetNames(Stream, AList)now läser 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 kalkylblad names without first saving to a file.
Version 2.88.99
- kalkylblad lookup, hyperlink creation, and multi-area selection APIs are now easier to use. Classic XLS and XLSX sheet collections add
TryGetSheetByName, classic XLS kalkylblad addAddHyperlinkconvenience overloads, andIXLSWorksheet.SelectAreascan skriva active multi-område selections.
Version 2.88.98
- Classic XLS arbetsböcker now expose a
UserNamealias for the saved-by field.IXLSWorkbook.UserNamemaps to the same WRITEACCESS value asLastSavedBy, so code that uses theUserNamenaming convention can läsa and update the arbetsbok audit name directly.
Version 2.88.97
- XLSX kalkylblad now share the callback cell scan and område skriva hjälpare.
TXLSXWorksheet.ForEachCellenumerates inläst celler in row order with value and formel text, whileTXLSXWorksheet.WriteCellsfills numeric or A1-stil områden from a callback with per-cell skip and cancellation.
Version 2.88.96
- Classic XLS kalkylblad now stöd callback-driven område writing.
IXLSWorksheet.WriteCellsfills a 1-based numeric område or A1-stil område in row order, lets the callback provide each cell value, stöder per-cell skip, and can cancel long skriva loops early.
Version 2.88.95
- Classic XLS kalkylblad kan nu enumerate inläst celler through a callback.
IXLSWorksheet.ForEachCellwalks existing kalkylblad celler in row order, passes 1-based sheet, row, and column coordinates with value and formel text, and lets the callback cancel long scans early.
Version 2.88.94
- formel calculation kan nu call application-defined functions.
TXLSWorkbook.OnUserFunctionandTXLSXWorkbook.OnUserFunctionletCalculatedelegate anpassad or unsupported kalkylblad functions to application code, passing evaluated arguments and using the returnedVariantresult when handled.
Version 2.88.93
- Classic XLS kalkylblad protection now exposes per-action permission flags.
IXLSWorksheetlägger tillAllowDeleteRows,AllowInsertRows,AllowFormatCells,AllowSort,AllowAutoFilter, and the remaining SheetProtect permission egenskaper, with BIFF8 options written and läsa back through the existing protection records.
Version 2.88.92
- Classic XLS VBA payloads har nu explicit load/spara/clear hjälpare.
IXLSWorkbook.LoadVBAProjectFromFile,SaveVBAProjectToFile,HasVBAProject, andClearVBAProjectexpose the preserved OLE VBA storage payload whileVBAProjectremains the parsed läsa-only module view.
Version 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.
Version 2.88.90
- Classic XLS kalkylblad har nu one-call AutoFilter criteria setup.
IXLSWorksheet.ApplyAutoFiltersets a kalkylblad AutoFilter område and skriver a field criterion in the same call, with A1-stil and 1-based numeric område overloads plus optional two-criterion operators.
Version 2.88.89
- Classic XLS shapes kan nu be removed by cell område.
TXLSShapes.DeleteInRangedeletes anchored pictures or shapes whose OfficeArt client anchors intersect a 1-based kalkylblad område, returning the number of shapes removed.
Version 2.88.88
- Classic HTML export tabell 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.
Version 2.88.87
- Classic HTML export stöder nu minimal tabell output.
TXLSHTMLExport.SimpleExportskriver a plain HTML tabell without generated CSS classes, hyperlink anchors, or comment title attributes while preserving escaped display text and merged-cell spans.
Version 2.88.86
- Classic HTML export kan nu skriva a document title.
TXLSHTMLExport.Titleskriver an escaped HTML<title>element before the generated stil block, while the default empty value keeps existing output unchanged.
Version 2.88.85
- Classic HTML export now carries cell comments as tooltips.
TXLSHTMLExport.Optionsinnehåller nuxhCommentsby default, writing cell comment text as escapedtitleattributes while still allowing callers to remove the option for plain cell output.
Version 2.88.84
- Classic HTML export hyperlink output is now configurable.
TXLSHTMLExport.Optionsdefaults to[xhHyperlinks]for existing behavior, and callers can removexhHyperlinksto export linked celler as plain escaped text.
Version 2.88.83
- Classic HTML export bevarar nu cell hyperlinks.
SaveAsHTMLwraps linked celler in HTML anchor tags, emits hyperlink addresses as escapedhrefvalues, carries ScreenTip text as escapedtitleattributes, and keeps the displayed cell text escaped inside the link.
Version 2.88.82
- Classic XLS arbetsböcker kan nu control the saved-by user name.
IXLSWorkbook.LastSavedByexposes the WRITEACCESS saved-by field so generated or edited arbetsböcker can store an explicit audit name while unedited source arbetsböcker continue preserving their original metadata.
Version 2.88.81
- Classic XLS kalkylblad kan nu control the displayed gridline color index.
IXLSWorksheet.GridlineColorIndexexposes the Window2icvHdrfield so saved kalkylblad can reopen with a chosen gridline color while leaving gridline visibility and print gridline settings unchanged.
Version 2.88.80
- Classic XLS arbetsböcker kan nu set the active sheet by index.
IXLSWorkbook.ActiveSheetIndexexposes a 1-based active-tab egenskap backed by the WINDOW1 active sheet field, allowing saved arbetsböcker to reopen on a chosen kalkylblad without changing the first visible tab.
Version 2.88.79
- Classic XLS kalkylblad outlines kan nu control automatic outline stilar.
TXLSOutline.ApplyStylesexposes the WSBool outline stil flag, allowing saved kalkylblad to bevara or explicitly enable Excel outline stil application without changing outline levels or summary placement.
Version 2.88.78
- Classic XLS page setup kan nu control automatic page breaks.
IXLSPageSetup.AutoPageBreaksexposes the kalkylblad WSBool automatic page-break flag, allowing saved kalkylblad to keep automatic page breaks enabled or disable them explicitly while preserving manual page breaks.
Version 2.88.77
- Classic XLS arbetsböcker kan nu control AutoFilter date grouping.
IXLSWorkbook.AutoFilterDateGroupingexposes the Window1 date-grouping flag with a positive Boolean API, allowing saved arbetsböcker to keep Excel's date filter grouping enabled or disable it explicitly.
Version 2.88.76
- Classic XLS arbetsböcker kan nu set arbetsbok window position and size directly.
IXLSWorkbook.XWindow,YWindow,WindowWidth, andWindowHeightexpose the Window1 geometry fields so saved arbetsböcker can reopen with a chosen window rectangle.
Version 2.88.75
- Classic XLS arbetsböcker kan nu spara the arbetsbok window hidden state directly.
IXLSWorkbook.WindowHiddenmaps to the Window1 hidden flag, allowing saved arbetsböcker to reopen with the arbetsbok window hidden without changing kalkylblad visibility.
Version 2.88.74
- Classic XLS arbetsböcker kan nu spara the arbetsbok window minimized state directly.
IXLSWorkbook.Minimizedmaps to the Window1 minimized flag, allowing saved arbetsböcker to reopen with the arbetsbok window minimized.
Version 2.88.73
- Classic XLS arbetsböcker kan nu hide or show the vertical scrollbar directly.
IXLSWorkbook.ShowVerticalScrollmaps to the Window1fDspVScrollflag, allowing saved arbetsböcker to öppna with the vertical scrollbar hidden or visible.
Version 2.88.72
- Classic XLS arbetsböcker kan nu hide or show the horizontal scrollbar directly.
IXLSWorkbook.ShowHorizontalScrollmaps to the Window1fDspHScrollflag, allowing saved arbetsböcker to öppna with the horizontal scrollbar hidden or visible.
Version 2.88.71
- Classic XLS arbetsböcker kan nu hide or show the sheet tab bar directly.
IXLSWorkbook.ShowSheetTabsmaps to the Window1fDspTabsflag, letting saved arbetsböcker öppna with sheet tabs hidden or visible without changing kalkylblad visibility.
Version 2.88.70
- Classic XLS arbetsböcker kan nu set the arbetsbok tab bar ratio directly.
IXLSWorkbook.TabRatioexposes the Window1wTabRatiovalue so callers can adjust the space reserved for sheet tabs versus the horizontal scrollbar.
Version 2.88.69
- Classic XLS arbetsböcker kan nu set the first visible sheet tab directly.
IXLSWorkbook.FirstSheetexposes the Window1itabFirstvalue as a 1-based egenskap, so callers can choose which sheet tab appears at the left edge when Excel opens the arbetsbok.
Version 2.88.68
- Classic XLS kalkylblad can bevarar 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.
Version 2.88.67
- Classic XLS kalkylblad can bevarar 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.
Version 2.88.66
- Classic XLS kalkylblad can bevarar nu and set the show-formler view.
IXLSWorksheet.DisplayFormulasmaps to the BIFF WINDOW2fDspFmlaflag so Excel can öppna a sheet showing formel text instead of calculated results.
Version 2.88.65
- Classic XLS kalkylblad kan nu set Normal view zoom independently.
IXLSWorksheet.NormalViewZoomexposes the cached WINDOW2 Normal zoom so callers can spara distinct zoom levels while a sheet is in Page Break Preview.
Version 2.88.64
- Classic XLS kalkylblad kan nu set Page Break Preview zoom directly.
IXLSWorksheet.PageBreakPreviewZoomexposes the cached WINDOW2 preview zoom so callers can spara different Normal and Page Break Preview zoom levels.
Version 2.88.63
- Classic XLS kalkylblad now expose split-pane hjälpare.
IXLSWorksheet.SplitPanes(Width, Height)creates a movable pane split using the existing BIFF pane writer, andUnsplitPanesclears the pane record before saving.
Version 2.88.62
- Classic XLS kalkylblad har nu simpler frozen-pane hjälpare.
IXLSWorksheet.FreezePanes(Cols, Rows)freezes the requested left columns and top rows, whileUnfreezePanesremoves the pane record before saving.
Version 2.88.61
- Classic XLS sheet-name discovery now accepts streams.
TXLSWorkbook.GetSheetNames(Stream, List)läser BIFF sheet names from a caller-provided XLS stream without loading kalkylblad contents, matching the file-name hjälpare for in-memory arbetsbok data.
Version 2.88.60
- kalkylblad collections now expose direct by-name lookup hjälpare.
IXLSWorkSheets.SheetByName(Name)andTXLSXSheets.SheetByName(Name)return the matching kalkylblad object ornil, so callers no longer need to resolve an index before accessing a sheet.
Version 2.88.59
- The XLSX facade now läser sheet names directly from streams.
TXLSXWorkbook.GetSheetNames(Stream, List)läser ordered names fromxl/workbook.xmlwithout loading kalkylblad XML, matching the file-name overload for in-memory and BLOB-backed arbetsböcker.
Version 2.88.58
- The XLSX facade now exposes quick sheet-name discovery.
TXLSXWorkbook.GetSheetNames(FileName, List)läser ordered names fromxl/workbook.xmlwithout loading kalkylblad XML.
Version 2.88.57
TXLSWorkbook.GetSheetNamesstöder nu XLSX packages. The metod läserxl/workbook.xmlfrom.xlsx,.xlsm,.xltx, and.xltmfiles and returns ordered sheet names without loading kalkylblad XML.
Version 2.88.56
- Classic XLS arbetsböcker kan nu läsa sheet names without loading kalkylblad.
TXLSWorkbook.GetSheetNames(FileName, List)scans the arbetsbok globals stream and returns ordered sheet names from Excel 97-2003.xlsfiles.
Version 2.88.55
- Classic XLS område AutoFilter criteria now skriva BIFF8 filter records.
TXLSRange.Autofilter(Field, Criteria)creates the filter område when needed and emitsAUTOFILTERconditions for simple string, numeric, Boolean, blank, nonblank, and comparison-prefixed criteria.
Version 2.88.54
- Classic XLS kalkylblad har nu kalkylblad-level AutoFilter hjälpare.
IXLSWorksheet.SetAutoFilter,ClearAutoFilter, andAutoFilterRangemanage BIFF8 filter dropdown områden directly while reusing the existingAUTOFILTERINFOand filter database name writer.
Version 2.88.53
- Classic XLS kalkylblad now expose list data-validation creation.
IXLSWorksheet.AddListValidation(Range, Items)skriver BIFF8DVALandDVrecords, keeps the dropdown visible by default, stöder comma-separated inline lists, and bevarar the rules throughOpen/SaveAsround-trips.
Version 2.88.52
- formel calculation now works consistently across XLS and XLSX entry points.
TXLSWorkbook.Calculatenow accepts Excel-stil leading-equals formler such as=SUM(A1:B1)+C1, and the XLSX facade lägger tillTXLSXWorkbook.CalculateplusTXLSXWorksheet.Calculate. The XLSX path shares the HotXLS formel token parser and evaluator for cell and område references, referenced formel celler, cross-sheet references, and arbetsbok or sheet scoped defined-name områden.
Version 2.88.51
- XLSX områden now stöd Excel-stil merge across.
TXLSXRange.Merge(True)skriver one<mergeCell>entry per row, matching the classic XLSRange.Merge(True)behavior, while no-argumentMergeandMerge(False)continue to create one full-område merged rectangle.
Version 2.88.50
- BIFF8 HeaderFooter and HFPicture placement now match the current MS-XLS rules. HotXLS bevarar Excel-authored
HeaderFooter($089C) records for even / first page header and footer text, and replaysHFPicture($0866) records after kalkylblad dimensions and drawing objects per the kalkylblad ABNF, so page-layout details survive .xls öppna/spara round-trips.
Version 2.88.49
- Comment rich-text runs har nu a typed API.
TXLSComment.TextRunsexposes BIFF8TXOFormatRunentries so callers can inspect or set per-character font boundaries in .xls comments while HotXLS still bevarar the underlying run bytes for safe round-trips.
Version 2.88.48
- Pivot-tabell supplemental SX records are now exposed through the typed API. HotXLS now attaches inläst BIFF8 pivot records such as
SXIVD,SXLI,SXFormat,SXEx,SXVDEx,SXRule,SXFilt, andSXAddltoTXLSPivotTable.SupplementalRecordsfor inspection while still preserving the original raw bytes for spara round-trips.
Version 2.88.47
- External arbetsbok cached values now survive .xls öppna/spara round-trips. HotXLS bevarar nu BIFF8
XCTandCRNrecords attached to inlästSUPBOOKentries, so cached cell values for external arbetsbok links are no longer dropped during spara.
Version 2.88.46
- Built-in stil outline levels now survive .xls öppna/spara round-trips. HotXLS now läser and bevarar the BIFF8
STYLEiLevelbyte for built-in stilar, so Excel RowLevel_1..7 and ColLevel_1..7 stil metadata is no longer reset to the default during spara.
Version 2.88.45
- Defined name metadata now survives .xls öppna/spara round-trips. HotXLS bevarar nu inläst 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 spara.
Version 2.88.44
- ObProj arbetsbok markers now survive .xls öppna/spara round-trips. HotXLS bevarar nu inläst BIFF8
ObProjrecords even when no VBA storage is exposed through the object model, so arbetsbok-level VBA project markers and third-party metadata are no longer dropped during spara.
Version 2.88.43
- kalkylblad option flags now survive .xls öppna/spara round-trips. HotXLS bevarar nu unmodeled BIFF8
WSBOOLbits such as dialog-sheet, automatic page-break, stil-application, and outline-gutter display flags while still updating the existing fit-to-page and outline summary settings through the public API.
Version 2.88.42
- Additional arbetsbok metadata records now survive .xls öppna/spara round-trips. HotXLS bevarar nu inläst BIFF8
COUNTRY,BOOKBOOL,BACKUP,FNGROUPCOUNT,USESELFS, andRECALCIDrecord bodies instead of rewriting them with defaults, keeping arbetsbok-level kompatibilitet and calculation metadata stable.
Version 2.88.41
- Multi-area selections and active pane focus now survive .xls öppna/spara round-trips. HotXLS bevarar nu inläst 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-område selections are no longer collapsed during spara.
Version 2.88.40
- External arbetsbok names now survive .xls öppna/spara round-trips. HotXLS bevarar nu inläst BIFF8
EXTERNALNAMErecords attached to externalSUPBOOKentries, including DDE/OLE/link metadata and formel tails, so external names and link definitions are no longer dropped when saving.
Version 2.88.39
- Password-protected BIFF8 .xls files now use and läsa RC4 CryptoAPI FILEPASS records. HotXLS now skriver Excel 2007/2010-stil
FILEPASSvMajor=2 metadata for encrypted .xls arbetsböcker and läser both legacy RC4 vMajor=1 and RC4 CryptoAPI vMajor=2/3/4 files, so password-protected arbetsböcker no longer fail or downgrade to the older encryption header.
Version 2.88.38
- Excel-authored .xls hyperlink metadata now survives öppna/spara round-trips. HotXLS bevarar nu the BIFF8
HLinkrecord body for inläst hyperlinks unless the hyperlink is edited, keeping sourcestreamVersion,hlstmfoption bits such asfIcon, moniker data, and related target metadata stable across saves.
Version 2.88.37
- arbetsbok window state now survives .xls öppna/spara round-trips. HotXLS now läser and bevarar the BIFF8
WINDOW1record's window position, size, visibility/iconic flags, first displayed sheet tab, valt-tab count, and tab-scrollbar ratio instead of rewriting them with defaults on every spara.
Version 2.88.36
- BIFF8 WriteAccess saved-by users now survive .xls öppna/spara round-trips. HotXLS now läser and bevarar the
$005C WRITEACCESSrecord body instead of replacing Excel's saved-by user withHotXLS, so arbetsbok audit metadata remains stable after saving.
Version 2.88.35
- Excel comment authors now survive .xls öppna/spara 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 arbetsbok again.
Version 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.
Version 2.88.33
- Additional OfficeArt solver-container rule records now rundtur. Beyond typed
msofbtConnectorRule($F012), HotXLS bevarar 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 spara.
Version 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 spara while malformed container-stil assumptions remain out of the XLS path.
Version 2.88.31
- OfficeArt connector rules now rundtur. 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 spara/reload. The earlier audit note listed $F121, but MS-ODRAW definesOfficeArtFConnectorRuleas $F012.
Version 2.88.30
- Unrecognised OfficeArt SpContainer leaf records now rundtur. 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.
Version 2.88.29
- ComboBox and ListBox OBJ unknown subrecords now rundtur. 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 lägger till the same else-branch as v2.88.28 Picture, capturing the unknown subrecord's 4-byte header + body into
FObjTailRaw. Both AddObj metoder 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.
Version 2.88.28
- Picture-shape OBJ unknown subrecords now rundtur. 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 lägger till 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 bevara the API surface (callers can still adjust
ftCfValueetc.), while the raw tail bevarar only the unknown bytes. Newly authored pictures via the Drawing API have emptyFObjTailRaw, so output is byte-identical to v2.88.27.
Version 2.88.27
- OBJ trailing-subrecord rundtur 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 spara 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.
Version 2.88.26
- OBJ trailing-subrecord rundtur 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 spara/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.
Version 2.88.25
- OBJ record trailing subrecords now preserved across the spara 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 arbetsböcker. HotXLS previously discarded every byte after CMO on läsa and emitted only an empty FtEnd on skriva, 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 område 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.
Version 2.88.24
- Multi-font and multi-color cell comments now rundtur. 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 läsa and emitted a single empty default run + LastRun on skriva — 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 arbetsböcker. Typed Excel-API access to individual format runs is still deferred — the existing single-WideString comment API is unchanged.
Version 2.88.23
- Print resolution and copy count now rundtur — 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 läsa 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 egenskaper.
PrintResolution: LongWord,PrintVResolution: LongWord, andCopies: LongWord— all default to the values the writer previously hardcoded (600 / 600 / 1) so arbetsböcker 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 rundtur work complete. With this fix every synlig för användare 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 / cell errors / resolution / copies. Only the two spec-hint grbit bits (
fNoPls,fNoOrient) remain unexposed, both of which HotXLS skriver as zero matching Excel's default behaviour.
Version 2.88.22
- anpassad Page Setup "First page number" now round-trips. The BIFF8 Setup record carries the arbetsbok'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 anpassad value, per MS-XLS §2.4.257. HotXLS previously dropped both on läsa 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 egenskaper.
UseFirstPageNumber: Booleanmirrors the bit (False = "Auto", default);FirstPageNumber: Integercarries the iPageStart value (default 1, clamped to the spec's signed-Word område -32768..32767 by the setter). HotXLS round-tripsiPageStartverbatim even whenUseFirstPageNumberis False, so toggling between Auto and anpassad in Excel bevarar the last user-typed value.
Version 2.88.21
- "Print comments at end of sheet" choice now survives the spara 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 läsa and emitted as zero on skriva — so a user-chosen "At end of sheet" silently reverted to "As displayed on sheet" on every HotXLS resave. - New TXLSPageSetup.PrintNotesAtEnd Boolean egenskap. Defaults to
Falsematching Excel's UI default. The reader and writer rundtur the bit verbatim (even whenPrintNotes = False), so a arbetsbok with comments temporarily disabled retains the "at end of sheet" preference for when the user re-enables them — mirroring Excel's own behaviour.
Version 2.88.20
- arbetsbok "Set precision as displayed" choice now round-trips. The BIFF8 CalcPrecision record ($000E) carries the arbetsbok-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 cell values to their formatted decimal places. - New TXLSWorkbook.UseFullPrecision Boolean egenskap. 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 cell value on the rundtur, 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.
Version 2.88.19
- "Recalculate arbetsbok before saving" checkbox now round-trips. The BIFF8 CalcSaveRecalc record ($005F) carries the arbetsbok's File → Options → spara → "Recalculate arbetsbok 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 spara" silently re-enabled itself on every HotXLS resave, which actually mattered for manual-calc arbetsböcker where the user had deliberately frozen the on-disk cell values. - New TXLSWorkbook.RecalcOnSave Boolean egenskap. Defaults to
True(matches both Excel's UI default and the legacy hardcoded value), so arbetsböcker that never touch the egenskap keep byte-identical output to v2.88.18. Setter accepts any Boolean; the reader normalises arbitrary non-zero source bytes toTrue.
Version 2.88.18
- Iterative calculation settings (enable + max iterations + max change) now rundtur. The BIFF8 CalcIter ($0011), CalcCount ($000C), and CalcDelta ($0010) records together carry Excel's "Enable iterative calculation" trio of options (File → Options → formler), 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 formler and convergence-sensitive financial models.
- Three new TXLSWorkbook egenskaper.
EnableIteration: Booleanmirrors the checkbox;MaxIterations: LongWordis the iteration cap (clamped to the spec-legal 1..32767 område 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 arbetsböcker that never touch the new egenskaper produce byte-identical output to v2.88.17.
Version 2.88.17
- arbetsbok calculation mode (Manual / Automatic / Auto except tabeller) now round-trips. The BIFF8 CalcMode record ($000D) carries the arbetsbok-level "formler → 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-valt Manual mode silently reverted to Automatic on every HotXLS resave — bad for large arbetsböcker where Manual is set deliberately for performance. The new ParseCalcMode handler stores the source value on the arbetsbok and StoreCalculationSettings now emits the stored value instead of the constant. - New TXLSWorkbook.CalculationMode egenskap. läsa-skriva
LongWordegenskap 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 arbetsbok in an undefined state. Existing code that never touches the egenskap keeps the legacy "Automatic" default, so previous output is byte-identical for default arbetsböcker.
Version 2.88.16
- Page Setup "cell errors as" choice now survives the spara cycle. The BIFF8 Setup record ($00A1) packs the Page Setup → Sheet tab "cell 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 läsa and emitted them as zero on skriva, so a arbetsbok the user had configured to print#DIV/0!as#N/Asilently reverted to "displayed" after every HotXLS resave. The reader now decodesiErrorsinto a newTXLSPageSetup.PrintCellErrorsegenskap and the writer rebuilds the field from it. - New TXLSPageSetup.PrintCellErrors egenskap. läsa-skriva
LongWordegenskap acceptingxlPrintErrorsDisplayed(0, default),xlPrintErrorsBlank(1),xlPrintErrorsDash(2), orxlPrintErrorsNA(3) — four new constants exported fromlxTNC.inc. Existing PageSetup callers that never touch the egenskap keep the default ("displayed"), so the legacy print output is unchanged.
Version 2.88.15
- cell comment alignment and orientation now rundtur. 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 spara 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 spara/reload trip. - Six new TMSOShapeTextBox egenskaper for explicit comment styling.
HAlignment,VAlignment,Rotation,LockText,JustLastLine, andSecretEditare exposed as läsa-skriva egenskaper 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 skriver (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 korrigerar harder to misalign.
Version 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.
Version 2.88.13
- Long cell comments now läsa 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.
Version 2.88.12
- Cached strings longer than ~4100 characters from string-returning formler now rundtur across Continue records. v2.88.11 wired up the läsa 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 läser 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.
Version 2.88.11
- String-returning formler now rundtur 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 formel record. ParseFormula now remembers the cell coordinates when it sees a string-variant formel, 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.
Version 2.88.10
- BIFF8 formel records now rundtur the cached value Excel computed. ParseFormula used to skip the 8-byte FormulaValue payload at offset 6 entirely, so the cached result of every formel in a inläst .xls (numbers, booleans, errors, empty) was thrown away and HotXLS had to re-evaluate every cell through its own formel engine. When that engine could not match Excel (unsupported XLM functions, broken external links, formler the engine has not yet implemented) the cell 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 formler 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.
Version 2.88.9
- BIFF8 formel records with unresolvable values now flag fAlwaysCalc instead of the reserved1 bit. When the HotXLS evaluator could not calculate a formel at spara 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 formel on next recalc and the cell shows the correct result.
Version 2.88.8
- PageSetup.PrintTitleColumns / PrintTitleRows now raise on bad input. Setting either egenskap with a malformed område string (anything
ColDiapasonToValues/RowDiapasonToValuescould not parse) previously dropped the assignment silently — the arbetsbok kept whatever Print_Titles område was already set, or no område 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 stil onTXLSRangeinvalid-index paths.
Version 2.88.7
- Row miyRw field now stays within the MS-XLS spec område. Pre-BIFF8 versions of Excel encoded "use the arbetsbok 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 skriver 255 directly; the reader still strips bit 15 on the way in for backwards kompatibilitet 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 tillagt. 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 formler matches what the spec implies and disambiguates correctly via the following ShrFmla / Array record. Both items are now annotated as retracted.
Version 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 kalkylblad after a SaveAs. The reader now lägger till a placeholder sheet for every BoundSheet8 record and stores the rawdtbyte on a newSheet.SheetTypeRawegenskap; the writer emits the original byte back. Macro substream BOF records ($0040) are also treated as kalkylblad substreams during parsing so celler inside macro sheets are preserved rather than silently absorbed into the previous sheet.
Version 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 läsa 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 område to prevent an XF index ever colliding with the new flags. rundtur 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 spara.
Version 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 skriver (per spec the bit means "this sheet is currently displayed in the arbetsbok 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.
Version 2.88.3
- BIFF8 Window2 zoom and gridline color now rundtur. Previous releases dropped the WINDOW2 record fields past offset 6 on läsa and emitted hard-coded zeros on skriva, 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.
Version 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-cell reference and silently dropped the picture (sometimes refusing to öppna the arbetsbok when the embedded image bytes happened to violate CellWatch’s expected 16-byte structure). arbetsböcker that rundtur a header / footer image through HotXLS now keep the image intact.
Version 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 cell-stil extension and silently fell back to the built-in Office theme, losing any customised theme colors when round-tripping a arbetsbok through HotXLS.
Version 2.88.0
- [MS-XLSX] cross-audit round 4 — theme part + sheet-name setter. Two follow-up korrigerar 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 lägger till a new always-emitted part.
- Saved .xlsx packages now include an
xl/theme/theme1.xmlpart. stilar.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 arbetsbok 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 område, so existingXlsxFirstExternalLinkRidoffsets for sheets / sst / stilar / vba / externalLinks are unchanged. - Direct
Sheet.Name := '...'assignment now sanitises and dedupes too. Round 3 (v2.54.1) tillagt Excel naming-rule enforcement inTXLSXSheets.Add(AName), but theTXLSXWorksheet.Nameegenskap 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 rundtur — 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 egenskap setter now routes through a newSetNamemetod that replays the sameXlsxSanitizeSheetName+' (N)'-suffix dedup logic (case-insensitive, exclude-self) against the parent arbetsbok’s sheet collection. Detached kalkylblad (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 rundtur.
Version 2.87.4
- XLS shared formler now skriva a valid
ShrFmlabody. BIFF8 shared-formel output innehåller nu the requiredcUsebyte before the shared parsed formel, so arbetsböcker saved withUseSharedFormulasno longer shift the formel token stream by one byte. - XLS tabell stil and filter metadata now matches the latest MS-XLS layout.
AddTablenow skriverLIST12asList12TableStyleClientInfo, sets tabell 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.
Version 2.87.3
- XLS kalkylblad tabell metadata now follows the MS-XLS
Feature11tabell layout.AddTableoutput for .xls files now skriver aFeatHdr11tabell header plusFeature11TableFeatureType/Feat11FieldDataItempayloads, removes the legacy$0867 FeatHdrtabell marker, and stores tabell and column names asXLUnicodeStringvalues. - XLS tabell readback now understands the spec-correct field layout. HotXLS parses
TableFeatureTypetabell names, områden, totals-row state, and field captions, while keeping a fallback for older HotXLS-generated tabell records.
Version 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 kalkylblad tabeller now use spec-correct
ContinueFrt11chunks. WideAddTableoutputs with largeFeature11payloads now spara with$0875 ContinueFrt11continuation records and reopen with tabell metadata preserved, matching the [MS-XLS]Feature11/ContinueFrt11layout.
Version 2.87.1
- XLSX kalkylblad grid limit innehåller 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 områden touching the last row or last column were silently clipped to the previous row/column. - XLSX encryption docs and tests now match the implemented skriva path. Help pages and the regression suite now state that
SaveAsEncryptedskriver ECMA-376 Standard Encryption output for non-empty passwords, whileOpenEncryptedstill raises for encrypted packages and falls back for plain .xlsx files.
Version 2.87.0
- XLSX password-protected spara now works (wave J phase 2, backlog #29).
TXLSXWorkbook.SaveAsEncrypted(FileName, Password)now skriver 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 arbetsbok into an in-memory plaintext .xlsx zip → encrypts via AES-128 CBC with a fresh random 16-byte salt and verifier → skriver the CFB output viaStgCreateDocfile. öppna 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.
Version 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 skriva 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.
Version 2.86.0
- QueryTable and External Data Connection rundtur (wave I, backlog #28). Excel-created QueryTables and external data connections (Data → Get External Data from Web / SQL / OLEDB) now survive a HotXLS spara/öppna cycle. Earlier the BIFF8 reader silently skipped
QsiSXTag($0802),QsiSXTagExt($0810), andDConn($0876), so the metadata that describes the upstream query was dropped on spara and the tabell degraded to plain cell values. The reader now captures these records as opaque bytes and the writer emits them back into the kalkylblad substream (alongside the PIVOTVIEW block per [MS-XLS] §2.1.7.20.5) and the arbetsbok 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 arbetsböcker that already contain them no longer lose refresh metadata. BIFF8 (.xls) only; BIFF5 unaffected.
Version 2.85.1
- Restore Win32 / Win64 library build. Two pivot-line-item hjälpare 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.
Version 2.85.0
- Typed pivot subtotal API (wave H5.4). The typed
TXLSPivotFieldnow exposes aSubtotals: TXLSPivotSubtotalsset egenskap 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 rundtur source of truth — reserved bits 12-15 are preserved on läsa/skriva. Closes the wave H4.3 known limit “row field subtotal SXVD.grbitSub configuration unavailable from API” and finishes the wave H5 pivot follow-ups.
Version 2.84.1
- Multi data-field SXLI expansion (wave H5.3). When a pivot tabell 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 lägger till minimal byte overhead. Closes the wave H4.3 known limit “multi-data-field SXLI not correctly expanded”.
Version 2.84.0
- Pivot page-axis pre-selection API (wave H5.2). The typed
TXLSPivotFieldnow carries aPageItemIndexegenskap 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 läserField.PageItemIndexinstead of hardcoding $7FFD, and the typed reader now populatesPageItemIndexfrom SXPI on öppna so callers can inspect the saved page selection. Closes the wave H4.3 known limit “page filter caller-pre-selection unavailable from API”.
Version 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.
Version 2.83.1
- cell fill, font, and border colors set via RGB now rundtur through .xls spara/öppna. The BIFF8 XFExt ($087D) writer was emitting each record's ixfe field using the in-memory XF array position, but the matching cell records on disk skriva ixfe using the post-pruning SaveIndex order. Whenever any XF earlier in the tabell was pruned during spara (typical when one cell 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 cell shifted to a neighbouring cell on reload. The writer now resolves SaveIndex for each rich-slot XF and emits the matching on-disk ixfe, so RGB cell colors saved by HotXLS — interior fill, font color, border colors — survive a spara / reload rundtur cleanly. XFExt records for XFs that got pruned entirely are now skipped rather than emitted with a dangling ixfe.
Version 2.83.0
- Pivot line items + page item state (wave H4.3). Programmatically-built pivot tabeller 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 öppna 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 kalkylblad 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-tabell writer. Pivot tabeller built via
IXLSWorksheet.AddPivotTablenow ship self-contained caches with full layout metadata.
Version 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 område on öppna — 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. - rundtur path unchanged. Pivot caches läsa from disk (FromRawBlobs = True) continue to rundtur via the wave H1 raw-byte path — the new SXDBB writer only fires for typed caches built by
IXLSWorksheet.AddPivotTable. Mixed arbetsböcker (one round-tripped cache + one new cache) emit both paths cleanly.
Version 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 öppna instead of showing raw General-format values. New
IXLSWorksheet.PivotSetDataFieldFormat(DataField, FormatStr): Wordregisters the format in the arbetsbok's NumFormats tabell (auto-add or reuse) and skriver the resulting ifmt index toTXLSPivotDataField.NumberFormat. The typed writer already emits SXDI.ifmt, so this closes the loop. - Public NumFormats hjälpare on TXLSWorkbook.
Workbook.RegisterNumFormat(FormatStr): Wordexposes the same auto-add behavior at arbetsbok 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%');
Version 2.80.1
- Icon Set conditional formats rundtur cleanly through HotXLS spara/öppna. 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 cell-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 arbetsböcker from either generation re-öppna cleanly.
Version 2.80.0
- Programmatic pivot tabell creation API (wave H3). New
IXLSWorksheet.AddPivotTable(SourceRangeA1, DestRow, DestCol, Name): TXLSPivotTablemetod walks the supplied source område, infers each column's data type from the cell values, auto-builds aTXLSPivotCache(or reuses an existing one bound to the same område), and creates a typed pivot tabell on the destination sheet with one TXLSPivotField per cache field (axes initially unset). - Caller wires axes / data via convenience metoder.
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 tabeller), 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 kalkylblad 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 kalkylblad bodies. - rundtur safety preserved. Pivot tabeller and caches läsa from disk keep their wave H1
FromRawBlobs = Trueflag and continue to rundtur via the raw-byte path. Only the new programmatically created pivots flow through the typed writer. Mixed arbetsböcker (one round-tripped pivot + one new pivot via AddPivotTable) emit both paths cleanly. - Wave H3 limitations. Source område types other than rectangular A1 (named områden, external arbetsbok refs) are out of scope. SXLI / SXPI (line items / page items) are not emitted for typed pivots — Excel computes them on öppna. 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 område string each time.
Version 2.70.0
- Pivot tabell typed läsa 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 tabell structure without bytecode parsing. New types —
TXLSPivotTable,TXLSPivotField,TXLSPivotItem,TXLSPivotDataField,TXLSPivotCache,TXLSPivotCacheField,TXLSPivotCacheItem,TXLSPivotCaches,TXLSPivotTables— surface via the newIXLSWorksheet.PivotTablesandTXLSWorkbook.PivotCachesegenskaper. - What the model captures. Per pivot tabell: 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 läsa from disk leave per-record indices unpopulated and rely on the raw-byte path for fidelity. - rundtur safety. Pivot tabeller 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-exporterar the public types so existing imports keep working.
Version 2.69.0
- Pivot tabell rundtur preservation (wave H1). HotXLS now keeps every record that makes up a pivot tabell when an Excel-created .xls travels through öppna → spara. 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 tabeller on next öppna. The reader now captures all of these as opaque bytes and the writer replays them verbatim, so the pivot tabell on the cover sheet still renders correctly in Excel after a spara / reload cycle.
- kalkylblad 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 tabeller block and the trailing EOF), matching the [MS-XLS] §2.1.7.20.1 kalkylblad 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 arbetsbok each get their own bucket. On spara the writer rebuilds the full BOF / records / EOF substream for each captured cache and appends them to the arbetsbok 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 tabell structure, but the existing Excel-built pivot tabeller rundtur through HotXLS without loss.
Version 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=anpassad.NumValuecarries the magnitude (10.0 = 10% when Ebsrc=1, raw scalar for fixed value, multiplier for stddev). For anpassad (Ebsrc=5) theCnumfield carries the count of anpassad data points; spec says MUST=0 for the other sources, so the builder forces non-anpassad 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" stil. - anpassad 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 anpassad value array. anpassad 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.
Version 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-område 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
AddSerieshjälpare 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.
Version 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-stil 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.
Version 2.65.0
- formel array constants rundtur with their data.
PtgArraytokens ($20 / $40 / $60 — V / R / A class) in formel streams now carry theirPtgExtraArraypayload through both läsa and skriva paths.SUM({1,2,3}),=MMULT(...),{=COUNTIF(...)}and other array-literal formler bevara 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/ArrayValuesegenskaper (with the matchingTXLSArraySerValrecord describing num / str / bool / err / empty celler 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 läsa 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.
Version 2.64.0
- Chart backlog wave D phase 7: drawing theme color get / set rundtur within a process. Phase 5 introduced
XlsApplyThemeColorToDrawingas a set-only hjälpare 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 arbetsbok now also keeps an in-memory side-tabell that remembers the original theme idx + tint per(TMsoShapeContainer, OfficeArt property id)pair. A newXlsGetDrawingThemeColorreader consults that side-tabell 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 egenskap panes. After spara / öppna the side-tabell 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 + egenskap id). SubsequentXlsApplyThemeColorToDrawingcalls on the same slot overwrite the entry, so the tabell tracks the latest intent rather than accumulating history. - Stable identity through new internal egenskaper.
TXLSColorFormatgrew läsa-only_Containerand_Pidaccessors so the hjälpare can compose the side-tabell 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 rundtur" 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 rundtur cap is structural, not a HotXLS gap. The Phase 7 side-tabell bridges the in-process gap so app-internal code can pretend the format stöder theme colors as long as it lives within one arbetsbok session.
Version 2.63.0
- Chart backlog wave D phase 6: compound border selectors rundtur 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 cell-loop pass onSetRangeXFBordersPropertyregisters up to four XFExt slots in one go. - Compound selector mapping. The new
BorderEdgeSlotSet(BorderIndex): TXLSXfRichSlotSethjälpare 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](cell-to-cell 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 celler loop with BorderMask=15), andConsumePendingRichSlotregisters all four XFExt slots on each touched XF in the same pass. ~4x fewer cell-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 celler 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 cell genuinely has the matching border line, and the indexed wire is set by the per-cellBorderMaskExcel already understands.
Version 2.62.0
- Chart backlog wave D phase 5: anpassad theme XML rundtur + drawing theme hjälpare. Three pieces close the last theme-color gaps that phase 4 left öppna. anpassad 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 uppdateringar the arbetsbok'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 rundtur through HotXLS without falling back to defaults. A newXlsApplyThemeColorToDrawinghjälpare lets chart / shape callers address drawing colors with the same theme idx + tint vocabulary that celler 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 arbetsböcker emit no record and stay byte-compatible with pre-Phase-5 output. - Drawing theme color hjälpare. The new free function
XlsApplyThemeColorToDrawing(ColorFormat, Workbook, ThemeIdx, Tint)resolves a theme idx + tint through the arbetsbok palette and skriver 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: läsa-back returns the resolved RGB rather than the theme slot, and the rundtur theme reference is lost on disk. For full theme rundtur useIXLSInterior.SetThemeColor/IXLSFont.SetThemeColor/IXLSBorder.SetThemeColoron celler, which leverage XFExt $087D. - Wave D fully closed in five phases. Phase 1 (v2.58.1) tillagt the case-tabell acknowledgement, Phase 2 (v2.59.0) wrote XFExt for RGB cell colors, Phase 3 (v2.60.0) closed the RGB reader loop, Phase 4 (v2.61.0) shipped the theme color path on celler, and Phase 5 (this) completes the picture with anpassad theme XML rundtur plus the drawing-side hjälpare. celler 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 hjälpare but pay the OfficeArt format's RGB-only price on läsa-back.
Version 2.61.0
- Chart backlog wave D phase 4: BIFF8 theme color stöd (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 cell color getters resolve the same theme idx + tint back through the arbetsbok'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-kompatibilitet trick Microsoft uses when "spara 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-stil -1.0..+1.0 lighter/darker adjustment that gets encoded into FullColorExt.nTintShade as Q15 signed integer. - arbetsbok BIFF theme palette.
TXLSWorkbooknow carries anFBiffTheme: TXLSThemeColorsinitialised to the default Office theme scheme that the XLSX side has used for years throughTXLSColorManager.FTheme. cell color getters resolve theme idx + tint through this palette viaGetThemeRGBColor(idx, tint)(which already applies HSL-based tint adjustment inlxRgb.GetRGBTInt). Internal_BiffThemeegenskap exposes the palette for parser-side uppdateringar. - Theme record ($0892) acknowledged on läsa.
lxRead.ParseThemetakes$0892out of the default-skip path so the arbetsbok-globals case tabell 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 celler render correctly through them. arbetsböcker with a fully customised theme will surface theme celler through the default palette here (documented known limit; XML-based theme parsing is a follow-up wave). - Why no Theme record on skriva. 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 celler 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.
Version 2.60.0
- Chart backlog wave D phase 3: XFExt ($087D) läsa-side RGB / theme recovery closes the rundtur. The Phase 1 acknowledgement and Phase 2 emitter are now joined by a parser that actually consumes each
$087Drecord into the arbetsbok XF rich-color side-tabell. Files saved by Excel with RGB cell 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 celler. 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 arbetsbok side-tabell 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. - cell color getters consult the side-tabell 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 existingGetRGBTInthjälpare when the slot carries an RGB value. xclrType=3 (theme) falls through to the indexed path: the BIFF arbetsbok has no theme model on this call chain, so the palette approximation remains the best available answer for theme celler. celler whose XF was never touched by a Phase 2 setter or a parsed XFExt produce the same byte-identical läsa result as before. - Wave D is closed. spara bevarar caller-set RGB (Phase 2). Load bevarar Excel-set RGB (Phase 3). arbetsböcker 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-tabell slot rather than per-edge — both rare enough to leave for a future wave.
Version 2.59.0
- Chart backlog wave D phase 2: XFExt ($087D) emission for BIFF8 cell 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 arbetsbok 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 cell 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 rundtur stays safe. The BIFF8 cell 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). celler that never took the color-setter path still emit no XFExt — arbetsböcker with no rich colors produce the same byte stream as before. - Storage and bookkeeping. A new per-XF rich-color side-tabell in
TlxFormatListholds the original RGB / theme info the cell setter passed in, keyed by the arbetsbok's hash-resolved XF index.TXLSRange.SetXFProperty/SetRangeXFBordersPropertygrew an optionalOnNewIndexcallback so the cell setter can register the rich color against every XF index the cell ends up on (multi-cell områden that hash to multiple distinct XFs all get tagged). The side-tabell is consulted inStoreWorkbookright after stilar and before PALETTE, matching the*XFExtposition in [MS-XLS] §2.1.7.20.3 arbetsbok 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 arbetsbok's stil objects, because doing so in the hash-keyed stil 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 läsa back throughcell.Interior.Color. Closing that läsa-side gap is a separate follow-up (Phase 3) that requires reworking the stil hash to admit per-XF rich color before the first hash anchor.
Version 2.58.1
- Chart backlog wave D (läsa-side acknowledgement only): XFExt ($087D) no longer routed through the default-skip path. A new
ParseXFExtbranch in the BIFF8 arbetsbok-globals case tabell consumes$087Drecords that Excel skriver alongside RGB and theme-colored cell stilar. The reader still leaves the indexed-color XF record unchanged — full RGB / theme precision recovery onto the arbetsbok's hash-key stil model is deferred to a separate wave because it would require the BIFF writer-side stil 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 skriva + läsa implementation, but exploration found that the BIFF skriva pipeline (
TXLSWorkbook.FXFList: TlxFormatList) encodes XF stil 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 stil models or extendingTlxFormatListwith per-XF rich color side-tabeller, 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.
Version 2.58.0
- Chart backlog wave C: SST rich-text and phonetic rundtur (BIFF8 XLUnicodeRichExtendedString). Rich-text formatting set in Excel (a cell whose individual characters carry their own font / color, the "two colors in one cell" effect from the Format celler dialog) sits in the shared string tabell 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 spara, so opening then resaving a arbetsbok flattened every multi-format cell to a single font / color. The shared-string parser bevarar 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
CollectRawTailhjälpare 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 bevara correctly whenrtorszovershot the current record. The preserved tails are registered against the arbetsbok SST through the newTXLSStringTable.AddWithExtras, which deliberately does not bump the cell-reference counter so subsequentLabelSSTparsing still produces correctcstTotalon spara. - 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 arbetsbok 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.
Version 2.57.0
- Chart backlog wave G: Header / Footer pictures survive the rundtur (BIFF8 HFPicture). When Excel saves a kalkylblad with a header or footer background image (Insert → Header & Footer → Picture, then the company logo stil), 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 arbetsbok again therefore lost the header/footer image. The reader bevarar 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 kalkylblad. 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 kalkylblad ABNF. Each preserved body is wrapped in a fresh $086C header and routed throughAppendData— the existingAddContinuehjälpare 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 skriver it. - No new public API surface. Wave G is a rundtur preservation feature; HFPicture content is opaque to application code (no caller-facing setter to inject a new header image). arbetsböcker that never carried an HFPicture record produce byte-identical output as before. The internal hjälpare
TXLSWorksheet._AddHFPictureBlobis reserved for the reader; the underscore prefix flags it the same way as_Drawing/_Autofilter.
Version 2.56.0
- Chart backlog wave B: kalkylblad tab color rundtur (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 egenskap 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 arbetsbok 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 arbetsböcker. xlExcel5 output is untouched (no SheetExt record in BIFF5). - Reader restores the tab color on öppna. A new
ParseSheetExtbranch inParseWorkbookRecord's case tabell läseriTabIdand the FullColorExt block and skriver the resolved RGB value back toSheets[iTabId + 1].TabColor.xclrType=2(RGB) stores the raw value;xclrType=1(indexed icv) resolves through the arbetsbok 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. - rundtur example. Setting
Workbook.Sheets[1].TabColor := $00FF00(green: B=0, G=$FF, R=$00) before SaveAs to .xls produces a arbetsbok that opens in Excel with a green tab; saving that same arbetsbok back out and re-opening it returns the egenskap 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.
Version 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-formel multi-column writer no longer references a missing record field. The v2.50.0 SHRFMLA wire-format fix tillagt
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-formel groups (the only kind the collector currently produces) is unchanged; the spec-correctcolLastbyte is now real instead of an alias ofcolFirst. - XLSX cell writer references
XlsxFloatToStrthrough a forward declaration. The v2.51.0 locale-safety fix introduced an XlsxFloatToStr call in the cell-value branch (line 2718) but the hjälpare 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.
Version 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 område had its cache slots silently cut short. The builder now (a) computes the maximum point count across all series for theDIMENSIONSrow område, 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 celler 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.
Version 2.54.1
- [MS-XLSX] cross-audit follow-up. Two targeted korrigerar from the v2.52.0 audit’s "deferred" list. Both are user-observable; neither breaks existing call sites.
- Date celler keep their date format when combined with any single non-numFmt stil. A
TDateTimecell withFontIndex/FillIndex/BorderIndex/AlignmentIndex/ProtectionIndexset but no explicitNumberFormatIndexused to route through a single-dim cellXf whosenumFmtIdwas 0 (General), so Excel rendered the cell as a raw serial number (e.g.46038) instead of1/15/2026. The XLSX stil engine now treats the implicit date as a virtual dim: any other styled dim promotes the cell into a composite cellXf that carriesnumFmtId=14alongside the real dim. Pure-date celler 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 arbetsbok that failed to öppna with the “The name you entered is not valid” dialog.TXLSXSheets.Addnow normalises the name via the newXlsxSanitizeSheetNamehjälpare (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 rundtur unchanged.
Version 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 kalkylblad shell records, SST/Continue edges, formel PTG depth, encryption padding, chart records, drawing/comment writer, and Pivot/tabell stöd. Public API unchanged; existing code recompiles untouched.
- Comment Note record now spec-conformant. Two distinct korrigerar 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 rundtur even when Excel still opened the file. - Comment
Visibleegenskap 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 egenskap 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. - formel
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-tabell key, so functions emitted with the user-prompt flag (macro/UDF callers) hashed to$8000 | iftaband produced an empty function name, killing the entire formel. 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 arbetsbok 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 stöd 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 tabell / QueryTable / DConn unsupported) are documented as known gaps for future feature work rather than silent omissions.
Version 2.53.0
- OpenOffice excelfileformat.pdf cross-audit round 2. Three additional BIFF8 wire-format korrigerar uncovered by re-running the spec sweep after v2.50.0, this time targeting modules the first pass had touched only lightly: the formel token decoder, the XF alignment byte, and the ROW outline-collapse boundary check. Public API unchanged.
- Macro-command formler 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 läsa as 128 + N arguments, blowing the formel 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). celler withJustifyLastLine = Truespara with the bit cleared, so the distributed / justified last-line rendering reverts to the Excel default after a spara / 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.
Version 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.
- cell strings with leading / trailing whitespace rundtur. 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 cell 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 kalkylblad 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 läsa it (Apache POI / NPOI / OOXML SDK) pre-size their cell buffers from the hint instead of growing dynamically. The writer now computes the bounding rectangle of populated celler during the row-grouping pass and emits the element as the second child of<worksheet>(after<sheetPr>if present, before<sheetViews>). Empty kalkylblad collapse to<dimension ref="A1"/>. <sst count="...">reports total cell 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.
Version 2.51.0
- [MS-XLSX] cross-audit pass. Five wire-format and locale-safety korrigerar across the XLSX writer uncovered by validating against the Microsoft [MS-XLSX] — Excel (.xlsx) Extensions to the Office öppna XML SpreadsheetML File Format dokumentation (v20260108) and the underlying XML 1.0 / OOXML schema requirements. Public API is unchanged; existing applications recompile and re-spara without modification.
- Saved .xlsx files now öppna on every Windows region. Page margins, column widths, row heights, font sizes, color tints, theme tints, anpassad-font rich-text run sizes, and the
<v>-wrapped numeric value of every cell 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 cell 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 arbetsbok in those regions. - celler containing control characters no longer break the arbetsbok. 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. cell 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 öppna 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 rundtur 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 läser 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.
Version 2.50.0
- OpenOffice excelfileformat.pdf cross-audit pass. Eight follow-up wire-format and lifetime korrigerar uncovered by re-validating the BIFF8 writer / reader against the OpenOffice Microsoft Excel File Format dokumentation after the v2.49.0 [MS-XLS] pass. Public API is unchanged; existing applications recompile and re-spara without modification.
- Shared formler now span the full column område (§5.94 SHAREDFMLA). The
SHRFMLArecord body wrotecolFirstinto thecolLastbyte, collapsing every multi-column shared formel group to a single-column group in Excel. Fill-down formler across two or more columns now expand to the correct celler when the arbetsbok is reopened. The reader-sidecolLastwidth was also corrected (was reading a 16-bit value that pulled in the adjacent reserved byte). - Shared formel Boolean / Error results rundtur correctly (§5.50 formel). The same
FormulaValuebyte-layout bug fixed in v2.49.0 for standalone formler was still present in the shared-formel writer (celler that carry atExptoken pointing at aSHRFMLAmaster). CachedTRUE/FALSEand#REF!/#DIV/0!/etc. values now appear as written instead of always reading back asFALSE/#NULL!. - formel option flags identify shared-formel members (§5.50 formel). celler inside a shared-formel group now set the
fShrFmlabit (0x0008) in the formel 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 spara / load rundtur on strict CFRULE parsers; the "no format blocks" special case (all-zero option flags) is preserved. - CHOOSE() formler läsa 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 tabell + error jump), so the decoder walked into the jump-tabell contents and corrupted every following token. The decoder now läserncand 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 arbetsbok teardown. Long-running applications that build and discard many CF / DV containers no longer occasionally AV at shutdown.
Version 2.49.0
- Spec-audit pass against [MS-XLS] v20250520. Sixteen wire-format and behaviour korrigerar across the BIFF8 writer, formel decoder, encryption path, chart builder, conditional-format and data-validation runtime, SST/ExtSST index, VBA storage reader and OLE stream öppna path. Public API unchanged; existing code recompiles untouched. Highlights below.
- BIFF8
Formularecord Boolean and Error results now rundtur 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 formler läsa back as False and Error formler as #NULL! in every consuming application. - cell 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 metod-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 läsa FrtRefHeader anchor fields at offsets 2/4/6/8 instead of 4/6/8/10, so the anchor-område comparison never matched and per-cell tooltips were silently discarded; tooltips now associate with their hyperlinks. BIFF8 område-reference decoder also fixed aFFirstColRel/FLastColReltypo in the BIFF5/7 fallback sign-extension path that mis-decoded områden with negative last-column relative offsets. - Conditional formatting and data validation runtime korrigerar.
IsContainRowin bothTCondRangeandTDVRangereturned true only when the område degenerated to a single row (the comparison was inverted); per-row clearing of CF / DV rules now works on multi-row områden. 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 arbetsböcker containing icon-set rules öppna with the rules intact. - ExtSST quick-find index spec-conformant for large arbetsböcker. The
dsstfield is now computed asmax((cstUnique / 128) + 1, 8)per [MS-XLS] §2.4.107 instead of the static default of 8; arbetsböcker 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 arbetsbok stream öppna path matches the spec spelling. The first OLE
OpenStreamattempt uses 'arbetsbok' (capital W per [MS-XLS] §2.1.7.20) instead of all-lowercase, so compound-file containers on case-sensitive OLE implementations öppna 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.
Version 2.48.10
- HotXLS-saved .xls files now include the two OLE compound-file egenskap-set streams Excel expects on every arbetsbok:
\005SummaryInformationand\005DocumentSummaryInformation. Pre-v2.48.10 only TRIAL builds wrote them (as a banner-stamping mechanism); release builds produced .xls files whose arbetsbok 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 arbetsböcker 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 > egenskaper pane. The DocumentSummaryInformation stream is created empty (Win32 still emits the egenskap-set header + CODEPAGE egenskap — 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 arbetsböcker. kalkylblad-only outputs from earlier releases happened to escape the symptom because Excel is more lenient with metadata-less kalkylblad arbetsböcker than with chart-sheet arbetsböcker, but they were also technically missing the streams. New
Lib/lxXlsSummary.pasunit holds the two hjälpare procedures; lxHandle.pas calls them unconditionally insideTXLSWorkbook.SaveWorkbookafterStoreWorkbookpopulates the arbetsbok 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, arbetsbok 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 skriver for the same data.
Version 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 kalkylblad 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 område, 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 skriver 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 kalkylblad celler 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 actualValuesområde numbers; the wire format is in place. - End-to-end smoke test: öppna 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.
Version 2.48.8
- BIFF8 (.xls) writer no longer pads the arbetsbok 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 arbetsbok 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 arbetsbok 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 arbetsböcker happen to have enough records that the padding ended up small (≤ 4 zero bytes that Excel tolerated). Chart-sheet arbetsböcker 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 metod survives as private dead code inlxHandle.pasin case a future code path legitimately needs sector-rounded streams; the call site inStoreOleFileis removed. arbetsbok 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 läsa non-sector-aligned arbetsbok streams from Excel-saved files correctly.
Version 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 öppna in Excel without error but show the legend / X-axis symptoms above. Re-spara through v2.48.7+ to migrate; no API change — the same
AddChartSheetcall now produces a chart that renders identically to what Excel itself would skriva 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.
Version 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 tillagt
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 lägger till 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 arbetsbok: a "Data" kalkylblad 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 skriver 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 cell 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).
Version 2.48.5
- BIFF8 chart series records now render correctly in Excel. v2.47.0 tillagt
tArea3Dbinding for Categories / Values områden, 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 korrigerar 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 skriva4for text-axis categories (matching Apache POI'sCATEGORY_DATA_TYPE_TEXTconstant). WithsdtX=1Excel tried to coerce'North'/'South'celler 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 celler. 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 öppna in Excel without error but rendered the symptoms above. Re-spara through v2.48.5+ to get the corrected wire format; no API change is required, the same
AddChartSheetcall now produces the correct chart.
Version 2.48.4
- BIFF8 CFEX ($087B) emit is retired. HotXLS no longer skriver 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 läsa 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 rundtur correctly — re-spara 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 formel content), making them interoperable with Apache POI / NPOI and any other spec-compliant BIFF8 reader.
Version 2.48.3
- BIFF8 CF12 ($087A) Icon Set rules now emit the NPOI-compatible
multistatesub-record inline so Apache POI / NPOI can läsa 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 rundtur 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.
Version 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 läsa 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)formel 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.
Version 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.
Version 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 skriverext_formatting_length(4)+ an optionalSerializeFormattingBlockheader before the formel 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.
Version 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 område 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 cell område and have no Reserved field, so HotXLS-emitted files were shifted by 4 bytes plus had a zeroed område slot. Reference dump frompoi_ConditionalFormattingSamples.xls(Apache POI test fixture) record 152 now matches HotXLS output byte-for-byte. - Concrete fix:
StoreCondFmt12Headernow skriver 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 läsa 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 spara.
Version 2.47.0
- BIFF8 chart-sheet creation now binds real data områden to series. The
CategoriesandValuesA1-område 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 arbetsbok, registers an XTI entry if one is not already present, and skriver the matching 0-based
ixtiinto the PtgArea3d body. Re-saved files keep theixticonsistent with the arbetsbok's final EXTERNSHEET ordering because the chart record stream is re-serialized through the formel compiler at spara time. - Accepted område 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-cell 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-stil
cce=0placeholder BRAI so the chart still opens in Excel: cross-arbetsbok refs ([Book2.xls]Sheet1!...), named områden (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 område 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.
Version 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 läsa; Excel-saved .xls files that used indexed colors (rather than RGB or theme) for their CF12 DXF blocks now rundtur 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-område icv values fall back to black ($000000).
- BIFF8 PALETTE record (rt=$0092) arbetsbok customization is not consulted — a arbetsbok 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 anpassad 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.
Version 2.45.0
- Conditional formatting rules now rundtur 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 spara, and the priority on Excel-saved files was ignored on läsa; now user-set priorities survive a load-edit-spara cycle on both backends. - New
Priorityegenskap onTCondFormatRule(BIFF8 side) andTXLSXConditionalFormat(XLSX side). Default is zero, which bevarar the existing auto-by-index behavior on spara; 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 område (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 arbetsböcker 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. läsa paths populatePriorityfrom the wire value when present; explicit checks against zero remain backward-compatible with code that ignored the egenskap.
Version 2.44.0
- Icon Set conditional-format rules now stöd 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 metoder on
TXLSIconSetSpecopt a stop into override mode:SetIconOverride(stopIndex, OverrideSet, IconId)andClearIconOverride(stopIndex). läsa-only egenskaperHasIconOverride[i],IconOverrideSet[i],IconOverrideId[i]expose the per-stop override state for inspection and rundtur 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). arbetsbok-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.
Version 2.43.0
- XLSX (.xlsx) conditional-format rules now rundtur 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 bevara the theme palette index plus the optional tint, so stilar like "accent-2 lightened 50%" survive an Excel öppna / HotXLS edit / Excel re-öppna cycle without being flattened to a frozen RGB. - New metoder on
TXLSDataBarSpecandTXLSCfValue(used by ColorScale stops) opt the slot into theme mode:SetThemeColor(themeId, tint)andClearThemeColor. läsa-only egenskaperIsThemeColor,ThemeColorId,ThemeColorTintexpose the active mode. Tint is a single in the [-1.0, +1.0] område — 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. arbetsbok theme palette resolution (theme1.xml parsing) is still out of scope; HotXLS bevarar 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.
Version 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-område strings into realtArea3Dcell-område 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 formel compiler and the EXTERNSHEET reference tabell to land the second half of Phase 2.
Version 2.41.0
- HotXLS gains programmatic BIFF8 chart-sheet creation. A new
AddChartSheetoverload set onSheetsskriver a complete chart substream into the saved .xls file, where previously chart sheets could only be preserved opaquely on a load-spara rundtur. 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 spara, 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 rundtur 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 cell områden), populated title text, and per-chart-type formatting (gap width / bar overlap / pie hole size / marker stil) are deferred to subsequent phases. spara-and-reopen with Excel bevarar the chart sheet's presence and its kind, but not yet user-supplied data.
Version 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 öppna the files in Excel and visually verify how each backend renders the extension rules. - The BIFF8 path additionally exercises the v2.35.0 DXF stil override: the Data Bar rule attaches white bold font color so the cell text stays legible over the dark bar fill.
- New DUnitX test fixture at
Tests/Delphi/HotXLS.CondFormat12Tests.pascovers ten rundtur and API-surface scenarios for the CF12 family: BIFF8 rundtur for all four rule kinds, DXF stil rundtur for RGB colors, theme colors, and font flags (bold / italic / underline), and XLSX rundtur 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 stöd the fixture,
TCondFormatexposes two new public accessors:RuleCountandRule(I), so callers can iterate rules after läsa instead of relying on the previously private rule list.
Version 2.39.0
- The Differential XF (DXF) stil override on conditional formatting rules stöder 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 arbetsbok theme index plus a tint value, so stilar like "accent-2 lightened 50%" rundtur without being flattened to a frozen RGB.
- Three new metoder 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] område — negative values darken the theme color, positive values lighten it, 0.0 leaves the base color. The corresponding existingSetXxxColor(rgb)metoder 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/XxxColorThemeTintläsa-only egenskaper 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 egenskaper. - Known limitations: theme-mode rundtur on BIFF8 (.xls) is the only path supported by this release — the XLSX (.xlsx) side still emits and läser
<color rgb="..."/>only and ignorestheme/tintattributes (planned for a follow-up release together with the arbetsbok theme palette plumbing).
Version 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 rundtur these rules without losing them. Previously, Excel-saved .xlsx arbetsböcker 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 / formel / autoMin / autoMax) and val, and child<color>entries to recover the data bar color or per-stop scale colors. - Icon set rules rundtur 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 skriva API, so a load-edit-spara rundtur bevarar 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 cell-value path otherwise. - Known limitations: theme color references (OOXML
<color theme="N" tint="0.5"/>) are läsa as 0 instead of being resolved against the arbetsbok theme palette;iconIdper-stop overrides on icon sets are not yet captured;<cfRule>priorityattribute is ignored on läsa (rules keep their parse order).
Version 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 lägger till 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 rundtur 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 område — a common pattern in Excel-saved files where the old cell-value backup and the new Data Bar / Color Scale / Icon Set rule cover identical sqref. The older CONDFMT entry is flagged via a new
IsShadowedegenskap onTCondFormatso user-facing code that iterates the conditional-format collection can skip the duplicate. The writer continues to emit both record families on spara for cross-version Excel 2003 ↔ Excel 2007+ kompatibilitet. - New
TotalRangeegenskap onTCondFormatexposes the merged-extent område that was previously private; useful for users implementing anpassad dedup, område 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 rundtur bevarar the 8 standard kind values (num/min/max/percent/percentile/formel/autoMin/autoMax) but does not rundtur Excel's theme-color tint metadata for the stop colors.
Version 2.36.0
- XLSX (.xlsx) output stöder 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 metoder 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 / formel, same Delphi BGRLongWordcolor format. Existing XLSX cell-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 läsa-side recognition of incoming data bar / color scale / icon set rules from Excel-saved files remains deferred — only skriva is wired up in this release.
Version 2.35.1
- The BIFF8 reader now decodes the Differential XF (DXF) bytes attached to a CF12 rule back into the rule's
TXLSDxfStyleegenskap bag, in addition to keeping the raw bytes inDxfBlob. Loading an Excel-saved arbetsbok 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. - rundtur behavior: a load-edit-spara cycle now reflects any post-load mutation of
Rule.Style. If a user läser a arbetsbok, changesRule.Style.SetFontColor, and saves, the new color wins; if the user doesn't touch the stil, 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 egenskap types not yet recognized by this release still load (the raw bytes remain inDxfBlobfor inspection or future rundtur stöd).
Version 2.35.0
- Conditional formatting rules now carry a Differential XF (DXF) stil override so that a CF12 rule firing in Excel can change the cell's font color, fill, font weight, italic, underline, or number format without altering the cell's base XF. The override is exposed as a new
TXLSDxfStyleegenskap on eachTCondFormatRule, accessible after creating a rule via the existingAddCondFormatDataBar/AddCondFormatColorScale*/AddCondFormatIconSetAPIs. - Supported stil overrides in this release: font color, fill background color, fill foreground color, fill pattern, font bold, font italic, font underline stil, and built-in number format id. Each egenskap has a paired
HasXxxflag — only egenskaper 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 stil has at least one override set. The DXF block uses the public XFProp array layout (cxfp + per-egenskap type / size / data tuples) so Excel can pick up the stil changes when the rule applies.
- The BIFF8 reader bevarar the raw DXF bytes from an Excel-saved file into the rule's
DxfBlobegenskap, so a load-edit-spara rundtur no longer silently loses the cell styling carried by CF12 rules. Decoding the raw bytes back into theTXLSDxfStyleegenskap bag is planned for a follow-up release. - Default behavior is unchanged for rules that don't opt into a stil —
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 egenskap set; the wire-format byte ordering for the XFProp value blobs follows public [MS-XLS] notes and may require small tweaks for full Excel rundtur fidelity once validated against BiffView. XLSX-side parity for the three new rule kinds remains deferred.
Version 2.34.0
- New public conditional-formatting API on the kalkylblad for the Excel 2007+ extension rules:
AddCondFormatDataBar,AddCondFormatColorScale2,AddCondFormatColorScale3, andAddCondFormatIconSet. Each metod accepts a sqref område 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 cell-value CONDFMT / CF records, so arbetsböcker 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 område, percent, percentile, or formel, matching the cfvo kinds used by Excel.
- Existing cell-value conditional formatting behavior is unchanged; only new APIs and new BIFF8 record handling were tillagt.
- Known limitations in this release: XLSX output for the three new rule kinds is not yet wired up (existing XLSX cell-value rules unaffected); the differential-XF stil 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 arbetsbok and Excel-rendering validation.
Version 2.33.3
- New XlsTables Delphi demo under
Demo/Delphi/XlsTables/demonstrates the BIFF8 tabeller (ListObjects) skriva side end-to-end. It generatesSalesTable.xlswith a four-column sales region (Region / Product / Quarter / Revenue) bound as a tabell at A1:D10 usingSheet.AddTable('SalesTable', 'A1:D10', headers). öppna 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 skriver the arbetsbok with a singleSaveAscall. Output goes next to the executable; an "öppna 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.
Version 2.33.2
- BIFF8 (.xls)
SaveAsnow suppresses the standalone sheet-levelAUTOFILTERINFO/AUTOFILTERrecords ($009D / $009E) when a tabell on the same sheet fully covers the autofilter område. Excel embeds an autofilter dropdown inside the tabell object itself, so emitting an additional sheet-level autofilter for the identical område 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 tabell 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 tabell) keeps emitting the sheet-level autofilter so legacy workflows that put a filter above or beside a tabell region continue to work.
- BIFF5 saves and sheets without any tabell are unaffected — the suppression check only runs when the file format is BIFF8 and the kalkylblad has at least one tabell. No public API change.
Version 2.33.1
- BIFF8 (.xls) läsa side now recognizes the shared-feature tabeller records that v2.33.0 tillagt on the skriva side. Opening an .xls saved by Excel (or by HotXLS itself) with one or more ListObjects/tabeller now populates the kalkylblad's
Tablescollection with aTXLSTableper parsed FEAT11 ($0872), reconstructing the tabell's område from the primary Ref8U, recovering the tabell id, name, and display name when present, and filling in the tabell stil name from the paired LIST12 ($0877) record. Previously these records were silently ignored, dropping all tabell state on rundtur. - 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 tabeller on the sheet; Isf=3 (SmartTags) and other values are safely ignored. FEATHEADR11 ($0871) is also acknowledged silently as a tabeller marker. - The reader is best-effort and tolerant: malformed or Excel-variant FEAT11 payloads degrade gracefully to a tabell that has at least the correct cell område, even if the higher-offset fields (per-column ids, structured-reference data) cannot be parsed. Sheet protection rundtur is unchanged — the existing options bit at Isf=2 payload offset 19 is still läsa identically.
Version 2.33.0
- BIFF8 (.xls) kalkylblad now stöd tabeller (Excel ListObjects). Call
Worksheet.AddTable(Name, Range, Columns)on anIXLSWorksheetto attach a named tabell region to a cell område — for exampleSheet.AddTable('SalesTable', 'A1:F9', HeaderList). The .xls spara path emits the BIFF8 shared-feature record family that marks the sheet as containing tabeller: FEATHEADR ($0867 with Isf=4), FEATHEADR11 ($0871), and a paired FEAT11 ($0872) + LIST12 ($0877) per tabell. Previously, callingAddTableon the XLS facade was unavailable; tabeller defined on a kalkylblad were silently dropped onSaveAs(xlExcel97). - New public API on
IXLSWorksheet:Tables: TXLSTablesegenskap (läsa-only collection) andAddTablemetod. The shape mirrorsTXLSXTable/TXLSXTableson the XLSX side, so code that lägger till tabeller to a arbetsbok 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 kalkylblad EOF, after sheet protection, only when the file format is BIFF8 (
xlExcel97). arbetsböcker without tabeller spara exactly as before — no FEATHEADR is emitted, no record stream changes, no overhead. BIFF5 saves are unaffected since tabeller are a BIFF8+ concept. - tabell ids are assigned sequentially per sheet (1..N) at spara time if not pre-set, so callers can leave
Idat its default afterAddTable. The default stil name'TableStyleMedium2'matches what Excel and the XLSX side already use, keeping tabell appearance consistent across both file formats. - Known limitations of this initial release (v2.33.0): totals-row formler and structured-reference auxiliary områden are not yet emitted; conflict suppression between sheet-level
AUTOFILTERINFOand a tabell område will be tillagt in a follow-up; the läsa side (parsing an Excel-saved .xls with tabeller back into theTablescollection) is also a follow-up. tabeller created via this v1 skriva path are well-formed for rundtur preservation in Excel itself.
Version 2.32.1
- Fixed a compilation error introduced by the v2.32.0 FILEPASS skriva-side feature that prevented the library from building on RAD Studio 12+ with strict type-checking. The
EncryptAllBlobshjälpare 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).
Version 2.32.0
- tillagt
EncryptionPasswordegenskap 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 öppna and refuse access when it is wrong. Previously the password setter was silently ignored on the skriva side and arbetsböcker were always emitted in plaintext. - The skriva path emits the BIFF8 FILEPASS record ($002F) immediately after the arbetsbok BOF and RC4-encrypts every subsequent record body using the existing läsa-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 arbetsböcker, SST CONTINUE chains, and multi-sheet streams encrypt correctly. - Encryption applies to BIFF8 (
xlExcel97) only -- the BIFF5 spara path remains plaintext. EmptyEncryptionPasswordkeeps the legacy plaintext output and is the default, so existing applications that never call the setter are unaffected. - läsa 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 rundtur 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 kompatibilitet with Excel's classic password-protection UI, not for confidentiality of sensitive data. For real security, prefer XLSX with AES.
Version 2.31.0
- tillagt
UseSharedFormulasegenskap onIXLSWorkbook. When set toTrue, BIFF8 SaveAs groups celler that share a template formel into native SHRFMLA records ($04BC), matching Microsoft Excel's compact wire format. Columns of formler 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 celler in the same column with consecutive rows and PTG-equivalent formler are grouped. celler with array formler or merged-cell flags are excluded.
- Default is
False, keeping the existing per-cell formel record emission unchanged. Opt in by settingWorkbook.UseSharedFormulas := Truebefore callingSaveAs. - Reading side is unaffected: HotXLS has always läsa 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 egenskap is tillagt and BIFF8 output format changes when the feature is enabled.
Version 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 stil 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 egenskap directly on the interface. This fix appears in the ApiTour, ExportWithColoring, PurchaseOrder, and QuickStart demos and completes full clang kompatibilitet for all nine C++Builder demo projects.
Version 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
lxFormulaegenskapEOFwas 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 cell-value assignments changed fromOleVariant(...)toVariant(...)becauseTXLSXCell.ValueisSystem::Variantand the clang compiler rejects the implicit protected-base-class conversion fromOleVariant.
Version 2.30.4
- The OrderCalc demo (Delphi Purchase Order sample) innehåller nu an XLSX export option alongside the existing XLS, HTML, and RTF formats. Selecting "Excel 2007+ file (*.xlsx)" in the spara dialog skriver the purchase order using the native TXLSXWorkbook API, producing a standards-compliant XLSX file with fonts, fills, borders, alignment, number formats, and Excel formler preserved.
Version 2.30.3
- SaveXLSWorkbookAsXLSX (the bridge used by TDataToXLS.SaveAs and TGridToXLS.SaveAs when the target filename ends in .xlsx) now copies cell background fill colors, font colors, and font stil attributes (name, size, bold, italic) from the underlying XLS arbetsbok to the XLSX output. Column widths — including explicitly narrowed columns set before export — are also copied. Previously only cell 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.
Version 2.30.2
- Fixed a rundtur bug in the XLS reader where the Outline.SummaryRow direction was inverted after öppna. 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 rundtur correctly. fColSumsRight ($0080) was already handled correctly and is unchanged.
Version 2.30.1
- XLS (BIFF8) writer now emits INTERFACEHDR / INTERFACEEND / WRITEACCESS records in the arbetsbok globals section, matching Microsoft Excel's native record layout. Native Excel always skriver 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 arbetsbok egenskap). Output XLS files now match Excel's native byte layout more closely.
Version 2.30.0
- tillagt a classic-to-XLSX export bridge. TDataToXLS.SaveAs and TGridToXLS.SaveAs now skriva .xlsx file names through the XLSX engine while keeping the existing .xls, .html, and .rtf paths unchanged.
- tillagt kalkylblad view APIs for XLS and XLSX. IXLSWorksheet.View and TXLSXWorksheet.View stöd normal view, page-break preview, and page-layout view, and the setting is preserved by the relevant file writer/reader path.
- tillagt classic arbetsbok kompatibilitet APIs: IXLSWorkbook.SetCodePage and IXLSWorkbook.VBAProject. VBA projects kan nu be inspected through TXLSVBAProject/TXLSVBAModule module names and source text when a arbetsbok contains a VBA storage.
- Extended TXLSXWorkbook with ParsedVBAProject, a läsa-only parsed view over a valid vbaProject.bin payload, while preserving the existing raw VbaProject byte rundtur behavior.
- tillagt 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 arbetsbok 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 cell 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. kalkylblad chart anchors are unchanged.
Version 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 arbetsböcker where a sheet-level autoFilter and a tabell cover the same område (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 område; the writer now suppresses the duplicate sheet-level <autoFilter> emission when its område coincides with any tabell's område. The tabeller' own autoFilter (rendered as the tabell 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 arbetsbok. The operator attribute is now omitted for list / anpassad / none.
- Fixed the <legacyDrawing r:id="..."/> element on kalkylblad 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/kalkylblad/_rels/sheetN.xml.rels file for chart sheets tillagt via AddChartSheet. The duplicate relationship file pointed at a nonexistent kalkylblad part and showed up as an orphan inside the .xlsx zip; chart sheets now skriva 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 tabell område, 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.
Version 2.29.3
- Fixed an XLSX rundtur regression where borders drawn on otherwise-empty rows were dropped after öppna + modify + SaveAs. ApiTour's row 8 horizontal divider (produced by a område.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 cell stilar when a `<c>` element is self-closing or has no value/formel children, so styled valueless celler survive the round trip.
Version 2.29.2
- Fixed an XLSX rundtur regression in öppna + modify + SaveAs flows. When ParseWorksheetXml läsa a cell whose
referenced a stilar.xml cellXf, it stored N directly on cell.FormatIndex. On SaveAs the cellXfs are rebuilt from the arbetsbok stil pools (with optional composite entries) and the new layout's slot at the same numeric index almost never carries the same semantics; the resaved cell ended up pointing at the wrong cellXf -- or past the end of the new cellXfs tabell -- 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 tabeller that ParseStylesXml already populates, so the round trip re-emits the cell against the freshly-built cellXfs.
Version 2.29.1
- Fixed two XLSX rendering regressions exposed by ApiTour demo: (1) celler inside a row could be emitted out of column order when a område.SetBorders call tillagt celler 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 celler by column before emission, matching the OOXML CT_Row schema. (2) celler that set 2 or more stil 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 område[..].SetBorders rendered without the borders. The writer now collects a composite cellXf pool during SaveAs and routes multi-dim celler to a synthesized cellXf that bevarar every dimension.
Version 2.29.0
- Renamed the internal hjälpare 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.
Version 2.28.3
- Fixed an XLSX cell-emit regression that caused borders set on otherwise-empty rows to disappear. `område[''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 cell whose Value was unassigned -- even when the cell had a BorderIndex / FontIndex / FillIndex / NumberFormatIndex / AlignmentIndex / ProtectionIndex assigned. The writer now emits `
` for valueless celler that carry any stil index.
Version 2.28.2
- Fixed an XLSX kalkylblad schema violation that caused Excel to refuse loading sheets which combined merged celler with AutoFilter. The XLSX writer now emits the <autoFilter> element before <mergeCells>, matching the OOXML CT_kalkylblad sequence (autoFilter is #11, mergeCells is #15). Previously such arbetsböcker 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.
Version 2.28.1
- tillagt convenience APIs to the classic XLS facade. IXLSRange now exposes läsa-only Width and WidthInPixels hjälpare plus SaveAsCSV(FileName); IXLSWorksheet and IXLSWorkbook now expose SaveAsCSV(FileName / Stream) overloads for the used område or active sheet; IXLSPageSetup now exposes Order, Draft, BlackAndWhite, PrintNotes, and läsa-only IsFitToPages. SETUP record spara/öppna bevarar nu those print flags.
Version 2.28.0
- tillagt RTF export on TXLSXWorkbook. New SaveAsRTF overloads (FileName / Stream x default-active-sheet / explicit SheetIndex) skriva the chosen sheet as an RTF 1.6 document containing a plain tabell. 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-cell bold (\\b), italic (\\i), and font size (\\fsN in half-points) are applied from the cell'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 område. Merged celler are not spanned — origin celler carry the content and non-origin celler within the område are emitted as empty celler. Default SheetIndex skriver the active sheet; out-of-område returns -1. Empty sheets produce a minimal valid RTF document.
Version 2.27.0
- tillagt HTML export on TXLSXWorkbook. New SaveAsHTML overloads (FileName / Stream x default-active-sheet / explicit SheetIndex) skriva the chosen sheet as a UTF-8 HTML document with a UTF-8 BOM. Output is a single <tabell> inside a minimal HTML page. Merged celler are expressed as colspan / rowspan attributes. cell styling is emitted as inline CSS: font family, size (pt), bold (font-weight:bold), italic (font-stil: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 celler flatten to their concatenated run text. Theme colors are silently skipped (no theme1.xml resolution in the simple HTML export). Default SheetIndex skriver the active sheet; out-of-område returns -1.
Version 2.26.0
- tillagt theme color + indexed color + tint/shade stöd 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 arbetsbok.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 öppna rundtur 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.
Version 2.25.0
- tillagt external arbetsbok link rundtur on TXLSXWorkbook. New types: TXLSXExternalLink (Target URL + SheetNames list) + TXLSXExternalLinks collection. TXLSXWorkbook.ExternalLinks egenskap exposes the collection; Add(Target) appends and returns a new link the caller fills out. SaveAs emits a arbetsbok-level <externalReferences> block in xl/arbetsbok.xml, an externalLink rel in xl/_rels/arbetsbok.xml.rels (tail of the rid område 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 arbetsbok URL with TargetMode="External", plus matching ContentType Overrides. öppna 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 cell values inside <sheetDataSet> are not preserved.
Version 2.24.0
- tillagt composing border hjälpare TXLSXRange.SetBorders. New TXLSXBorderEdgeKind enum (xlsxEdgeAll / Outline / Inside / InsideHorizontal / InsideVertical / Top / Bottom / Left / Right / DiagonalUp / DiagonalDown) selects which edges to skriva. SetBorders(Kind, stil, Color) / SetBorders(Kind, stil) (defaults to opaque black) iterates every cell in the område, computes the edge mask per cell position (corner celler get two outline edges, edge celler get one, interior celler get inside grid lines, etc.), composes stil + Color onto a clone of the cell's current border (so successive Outline + Inside calls stack instead of overwriting), then does a arbetsbok-level lookup-or-add on arbetsbok.Borders and skriver the resulting 1-based BorderIndex back on the cell. New TXLSXBorders.LookupOrAdd hjälpare returns 0 for empty borders so the pool never bloats with no-op entries.
Version 2.23.0
- tillagt CSV export overloads on TXLSXWorkbook. New entry points: SaveAsCSV(FileName) / SaveAsCSV(FileName, SheetIndex, Delimiter) / SaveAsCSV(Stream) / SaveAsCSV(Stream, SheetIndex, Delimiter) skriva 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 celler flatten to the concatenated run text; empty celler in the interior of the bounding rectangle render as bare delimiters and the row stops at the last populated column.
Version 2.22.0
- tillagt arbetsbok-level indexed color palette overrides on TXLSXWorkbook. New entry points: IndexedColor[Index: Integer]: LongWord (läsa/skriva, 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. öppna parses the block and silently drops slots whose value matches the default so round-trips stay minimal. Out-of-område slot assignments (< 0 or > 63) are dropped instead of raising.
Version 2.21.0
- tillagt six sheet-view display egenskaper on TXLSXWorksheet. Zoom: Integer is the zoom percent shown in Excel's status bar (10..400, default 100; out-of-område assignments clamp on skriva). DisplayGridLines / DisplayZeros: Boolean (default True) hide cell grid lines or render zero-valued celler 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; öppna parses them back. Existing freeze-pane + tab-valt handling on <sheetView> is unchanged and now shares a single emitter.
Version 2.20.7
- tillagt TStream overloads on TXLSXWorkbook for in-memory serialization. New entry points: SaveAs(Stream: TStream) / SaveAs(Stream: TStream; FileFormat: TXLSXFileFormat) skriva the entire .xlsx package into the given stream starting at the current position; öppna(Stream: TStream) läser 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 / öppna overloads are unchanged and now delegate to the same internal skriva / läsa hjälpare.
Version 2.20.6
- tillagt Hidden / Visible / Comment egenskaper 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; öppna parses them back. SheetIndex (the existing Local scope binding via localSheetId) is unchanged.
Version 2.20.5
- tillagt five more font traits to TXLSXFont. New TXLSXFontVertAlign enum (xlsxVertAlignBaseline / Superscript / Subscript) drives the existing Excel "Superscript" / "Subscript" font checkboxes via a single VertAlign egenskap (mutually exclusive in the UI). New Boolean OutlineFont and Shadow egenskaper 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>; öppna parses them back. ColorIndex / ThemeColor / TintAndShade are deferred to the upcoming theme milestone.
Version 2.20.4
- tillagt border diagonal direction toggles. TXLSXBorder now exposes DiagonalUp: Boolean and DiagonalDown: Boolean. The two flags share the existing Diagonal edge's stil 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; öppna parses them back. Previously the engine wrote one Diagonal edge with no direction control, so Excel never drew either diagonal line.
Version 2.20.3
- tillagt arbetsbok Date1904 toggle. TXLSXWorkbook now exposes a Date1904: Boolean egenskap 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/arbetsbok.xml when set; öppna läser it back. The flag is metadata only — the engine does not transform stored serials; callers must set Date1904 before assigning TDateTime cell values so the rundtur lands on the right calendar.
Version 2.20.2
- tillagt auto-filter per-column criteria stöd. 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 egenskap and AddAutoFilterColumn(ColId, Op, Criteria) / AddAutoFilterColumn(ColId, Op1, Criteria1, Op2, Criteria2, AndConnector) / ClearAutoFilterColumns convenience metoder. 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; öppna parses the same structure back. Previously the engine only stored the autofilter område (sqref) and Excel showed empty filter dropdowns.
Version 2.20.1
- tillagt manual page break stöd 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>; öppna parses them back.
Version 2.20.0
- tillagt sheet visibility (Hidden / VeryHidden), per-sheet selection and active-sheet tracking on TXLSXWorkbook / TXLSXSheets / TXLSXWorksheet. New types: TXLSXSheetVisibility enum (xlsxSheetVisible / xlsxSheetHidden / xlsxSheetVeryHidden). New TXLSXWorksheet egenskaper: Visibility, Visible (Boolean alias), IsSelected (läsa-only). New TXLSXSheets members: ActiveIndex, Activate(Index), Move(FromIndex, ToIndex). New TXLSXWorkbook.ActiveSheet proxy. SaveAs emits <sheet state="..."/> on the arbetsbok'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>; öppna parses all three back into the new egenskaper. The first tillagt sheet becomes both visible and active by default so existing call sites continue to work.
Version 2.19.2
- tillagt 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 cell 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; öppna parses them back. Defaults stay off so unchanged kalkylblad do not gain extra attributes.
Version 2.19.1
- tillagt three-part header and footer convenience egenskaper to TXLSXWorksheet. New entries: LeftHeader / CenterHeader / RightHeader and LeftFooter / CenterFooter / RightFooter. Each läser or skriver the matching &L / &C / &R segment of the existing HeaderText / FooterText raw string; writing any one segment rebuilds the full raw form so the rundtur writer and reader keep working without changes.
- tillagt print-option toggles for sheet-level page output. New TXLSXWorksheet egenskaper: CenterHorizontally, CenterVertically, PrintGridlines, PrintHeadings. SaveAs emits a <printOptions horizontalCentered / verticalCentered / gridLines / headings/> element when any of the four is enabled; öppna parses the same attributes back. Defaults stay off so unchanged kalkylblad do not gain an extra <printOptions/> element.
- tillagt per-sheet PrintArea, PrintTitleRows and PrintTitleCols rundtur. These map to the OOXML built-in arbetsbok-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.
Version 2.19.0
- tillagt 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: cell anchors (celler), merged-område corners (MergedCells — straddling områden are clipped to the surviving edges and inside-only områden 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 område string on every ConditionalFormat, DataValidation, and Excel tabell (an entry whose område 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 cell grid and a faithful shift would require recomputing the EMU offsets); arbetsbok-level DefinedNames formler are not rewritten. Both are tracked for a follow-up release.
Version 2.18.2
- tillagt AutoFit hjälpare 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 kalkylblad over the område'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 cell text. Wide områden (EntireRow / EntireColumn) are clamped to the last cell-bearing row / column on the kalkylblad so AutoFit does not iterate to the Excel grid limits.
Version 2.18.1
- tillagt per-cell protection rundtur to the XLSX engine. TXLSXCell exposes new Locked: Boolean (default True) and FormulaHidden: Boolean (default False) convenience egenskaper that mirror Excel's cell-protection model. They surface the pool index TXLSXCell.ProtectionIndex (1-based into the new arbetsbok-level TXLSXProtections pool); writing the convenience egenskap 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 celler.
- tillagt TXLSXRange.SetLocked(ALocked) and TXLSXRange.SetFormulaHidden(AHidden) batch hjälpare so unlocking or hiding a whole område only does one pool lookup-or-add and applies the result to every cell in the rectangle.
- tillagt the matching writer / reader plumbing. SaveAs emits one cellXf with an inline <protection locked="N" hidden="M"/> child per arbetsbok Protections entry (after the alignment block); öppna parses <protection> back into arbetsbok.Protections and threads the new CellXfProtMap through ParseStylesXml and ParseWorksheetXml so per-cell ProtectionIndex round-trips alongside the existing font / fill / border / number-format / alignment indices.
Version 2.18.0
- tillagt TXLSXRange object for multi-cell access and batch operations on TXLSXWorksheet. New entry points: kalkylblad.område['A1:C5'], kalkylblad.RCRange[r1,c1,r2,c2], kalkylblad.UsedRange, kalkylblad.EntireRow(r), kalkylblad.EntireColumn(c). The returned område exposes SetValue / SetFormula / Clear / ClearAll / Merge / Unmerge / Offset / Resize plus per-cell stil index setters (SetFontIndex / SetFillIndex / SetBorderIndex / SetNumberFormatIndex / SetAlignmentIndex) and a SetNumberFormat(Fmt) convenience that looks up or appends the format string in the arbetsbok pool. TXLSXRange objects are owned by the kalkylblad and released on kalkylblad destruction; callers do not free them.
- tillagt TXLSXCell.NumberFormat: WideString convenience that pairs with the existing NumberFormatIndex. Reading returns the format string from the arbetsbok pool; writing looks up or lägger till the string and uppdateringar NumberFormatIndex transparently. Requires the cell to be attached to a arbetsbok (the standard flow through TXLSXWorkbook.Sheets.Add(...).celler[r, c]).
- tillagt cell -> sheet -> arbetsbok back-references so each TXLSXCell can resolve its owning arbetsbok without external bookkeeping. TXLSXSheets, TXLSXWorksheet, and TXLSXCells gained internal Owner references wired through their constructors; TXLSXCell exposes a läsa-only arbetsbok egenskap and an internal SetWorkbook used by TXLSXCells.GetItem when auto-creating a cell on access.
Version 2.17.42
- Fixed XLSX cell rundtur on reopen. celler written by SaveAs were being dropped on öppna, with HasCell(row, col) returning False and all cell-level state (value, formel, font index, fill index, border index, number format index) lost. The root cause was a spurious MoveToAttribute('r') call in the kalkylblad parser that flipped the reader's node type to attribute, which then made the subsequent IsEmptyElement check return True and shut off cell parsing for every <c> element with an r="" attribute (i.e. every cell). Removing the unnecessary cursor move restores text, numeric, formel, and date cell rundtur together.
- Fixed XLSX stil index restore on reopen. anpassad font, fill, border, and number-format indices on celler were reading back as zero even after the matching pools (arbetsbok.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-cell FontIndex / FillIndex / BorderIndex / NumberFormatIndex rundtur.
- Fixed XLSX date cell rundtur. 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 skriver the date serial number into <v> directly and applies the date cellXf, so date celler reopen as a varDate Variant instead of a localized string that the caller could not coerce back to TDateTime.
Version 2.17.41
- Fixed "zlib stream does not stöd 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 läsa-until-EOF hjälpare, so .xlsx files with images or macros rundtur through SaveAs/öppna without raising.
Version 2.17.40
- tillagt chart-sheet (full-page chart kalkylblad) stöd to the XLSX engine. TXLSXWorksheet exposes a new IsChartSheet flag plus a arbetsbok-level arbetsbok.AddChartSheet(Name, ChartType, Title) hjälpare that creates the sheet, flips the flag, and seeds Charts[0] with a sensible default anchor. SaveAs skriver 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/arbetsbok.xml.rels. Regular kalkylblad keep their existing xl/kalkylblad/sheetN.xml path. öppna recognizes chartsheets via the relationship type but currently loads them as plain kalkylblad (their chart data still arrives via the shared chart parts).
Version 2.17.39
- tillagt collapsed row / collapsed column rundtur for outline groups in the XLSX engine. TXLSXWorksheet exposes RowCollapsed[Row] and ColCollapsed[Col] Boolean egenskaper along with SetRowCollapsed / SetColCollapsed / ClearRowCollapsed / ClearColCollapsed hjälpare. SaveAs emits collapsed="1" on the matching <row> and <col> entries; öppna parses the attribute back. Together with the existing outlineLevel and hidden attributes, this lets the XLSX engine rundtur a fully collapsed grouping hierarchy.
Version 2.17.38
- tillagt hidden row / hidden column rundtur to the XLSX engine. TXLSXWorksheet exposes RowHidden[Row] and ColHidden[Col] Boolean egenskaper along with SetRowHidden / SetColHidden / ClearRowHidden / ClearColHidden hjälpare. SaveAs emits hidden="1" on the matching <row> and <col> entries; öppna parses the attribute back into the kalkylblad so hidden rows / columns survive the rundtur without forcing a anpassad width or outline level.
Version 2.17.37
- tillagt kalkylblad tab color rundtur to the XLSX engine. TXLSXWorksheet exposes TabColor (ARGB) and TabColorIsAuto egenskaper. SaveAs emits a <sheetPr><tabColor rgb="..."/></sheetPr> block as the first child of <kalkylblad> when the tab color is set; öppna parses <tabColor> back into the kalkylblad so colored sheet tabs survive the rundtur. Default arbetsböcker stay free of the extra block (TabColorIsAuto = True).
Version 2.17.36
- tillagt cell alignment rundtur to the XLSX engine. New TXLSXHorizontalAlignment and TXLSXVerticalAlignment token enums, TXLSXAlignment class (Horizontal, Vertical, WrapText, ShrinkToFit, Indent, TextRotation), and a arbetsbok-level TXLSXAlignments collection (arbetsbok.Alignments). TXLSXCell now carries an AlignmentIndex (1-based into arbetsbok.Alignments). SaveAs appends one cellXf with an inline <alignment/> child per arbetsbok alignment entry; öppna läser <alignment> attributes back into arbetsbok.Alignments and maps the cellXf back to TXLSXCell.AlignmentIndex. ParseWorksheetXml and ParseStylesXml grew a CellXfAlignMap parameter to carry the mapping across the two phases.
Version 2.17.35
- tillagt 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 öppna them; OpenEncrypted transparently falls back to plain öppna for unencrypted .xlsx files. The AES-128/256 + SHA + OLE Compound File pipeline itself is not yet wired up — both skriva and läsa 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 kalkylblad.Protect / arbetsbok.ProtectWorkbook for the visual lock.
Version 2.17.34
- Performance: replaced the O(N^2) WideString concatenation that built each kalkylblad's cell rows with a TXLSWideStringBuilder. Large sheets (10k+ celler) now stay linear in memory and CPU on SaveAs. tillagt a new WriteWorksheetXmlStreaming hjälpare and a TXLSXWorkbook.StreamingWrite opt-in flag — when enabled, SaveAs no longer holds every kalkylblad's XML in a sheetXmls cache at the same time; each kalkylblad 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.
Version 2.17.33
- tillagt cell-område 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 cell value, formel, four stil indices, and any rich-text payload; MoveRange skips overlap with the destination so partial overlaps still bevara their copied values. TXLSXCells also gains a Remove(Row, Col) hjälpare.
Version 2.17.32
- tillagt internal hyperlink anchors to the XLSX engine. TXLSXHyperlink now carries a Location egenskap (e.g. "Sheet2!A1") and an IsInternal hjälpare; TXLSXHyperlinks exposes AddInternal, and TXLSXWorksheet lägger till three AddHyperlinkToCell overloads. SaveAs emits internal hyperlinks with the inline location="" attribute and skips the kalkylblad rels entry; öppna recognizes location="" hyperlinks and routes them back through AddInternal. External URL hyperlinks continue to flow through the rels file unchanged.
Version 2.17.31
- tillagt rich-text rundtur 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 egenskap; SaveAs skriver the cell as a shared-string with multiple <r>/<rPr>/<t> runs and öppna rebuilds the TXLSXRichText from the parsed SST entry, with the cell's Variant Value still surfacing the concatenated plain text for callers that ignore formatting.
Version 2.17.30
- tillagt chart rundtur to the XLSX engine. New TXLSXChartType enum (column / bar / line / pie), TXLSXChartSeries (Name, CategoriesRange, ValuesRange), and TXLSXChart (ChartType, Title, axis titles, From/To anchor celler, Series) classes plus a per-kalkylblad TXLSXCharts collection (kalkylblad.Charts). TXLSXWorksheet exposes AddChart(Type, Title, FromRow, FromCol, ToRow, ToCol). SaveAs emits xl/charts/chartN.xml (arbetsbok-global numbering) and binds it to a twoCellAnchor / graphicFrame inside the shared xl/drawings/drawingN.xml; öppna parses both the anchor and the chart definition back into the collection. Chart titles, axis titles, series names and source områden rundtur.
Version 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.
Version 2.17.28
- Fixed TZipArchive.Exists, which was a stub that always returned false. The XLSX öppna path uses zip.Exists(...) to gate every part läsa, so every previously-claimed rundtur (celler, stilar, comments, drawings, doc props, defined names, protection, VBA, etc.) silently dropped its content on läsa. Exists now delegates to the existing Fcd.Entries.Exists lookup, matching the OpenFile / CreateFile pattern.
Version 2.17.27
- tillagt VBA project preservation to the XLSX engine. TXLSXWorkbook exposes a VbaProject byte payload plus LoadVbaProjectFromFile(FileName), ClearVbaProject, and HasVbaProject hjälpare. SaveAs skriver the bytes to xl/vbaProject.bin, registers the .bin content-type, switches the arbetsbok content-type to the macro-enabled variant, and lägger till a vbaProject relationship to the arbetsbok rels file; öppna läser xl/vbaProject.bin back into the egenskap. The bytes are not parsed or modified, so existing .xlsm projects rundtur exactly. Note: macro-enabled arbetsböcker must be saved with a .xlsm extension for Excel to enable macros.
Version 2.17.26
- tillagt arbetsbok and sheet protection to the XLSX engine. TXLSXWorksheet exposes Protect / Protect(Password) / UnProtect plus IsProtected and SheetProtectHash; TXLSXWorkbook lägger till ProtectWorkbook (with optional password, LockStructure, LockWindows flags) and UnProtectWorkbook plus IsWorkbookProtected / WorkbookProtectHash / LockStructure / LockWindows. SaveAs emits <sheetProtection> on each protected kalkylblad and <workbookProtection> on protected arbetsböcker; öppna parses both blocks back into the API. Passwords are stored as the standard 4-hex legacy hash for rundtur fidelity (the original plaintext is not recoverable).
Version 2.17.25
- tillagt document-egenskap rundtur to the XLSX engine. TXLSXWorkbook now exposes Title, Author, Subject, Keywords, Description, Category, LastModifiedBy, Created, Modified, Company, Application, and AppVersion egenskaper. SaveAs emits docProps/core.xml and docProps/app.xml (and registers them in [Content_Types].xml + _rels/.rels) when any egenskap is touched; öppna parses both files back so authors, modification stamps, and application metadata survive a spara-and-reopen.
Version 2.17.24
- tillagt Excel-stil tabell rundtur to the XLSX engine. New TXLSXTable class (Id, Name, DisplayName, område, Columns, StyleName, ShowFirstColumn / ShowLastColumn / ShowRowStripes / ShowColumnStripes) and a per-kalkylblad TXLSXTables collection. TXLSXWorksheet exposes tabeller plus AddTable(Name, område, ColumnNames). SaveAs emits xl/tabeller/tableN.xml (arbetsbok-global numbering), uppdateringar kalkylblad rels with tabell relationships, lägger till <tableParts> to the kalkylblad, and registers the tabell content-type. öppna parses tabell relationships and tableN.xml back into the kalkylblad so styled tabell bands survive a spara-and-reopen.
Version 2.17.23
- tillagt auto-filter rundtur to the XLSX engine. TXLSXWorksheet exposes an AutoFilterRange egenskap plus SetAutoFilter(Row1, Col1, Row2, Col2) / SetAutoFilter(område) / ClearAutoFilter hjälpare. SaveAs emits <autoFilter ref="..."/> after the merge-celler block when the område is non-empty; öppna parses the ref back into the egenskap so the filter band on a kalkylblad survives a spara-and-reopen.
Version 2.17.22
- tillagt page-setup rundtur to the XLSX engine. TXLSXWorksheet exposes Margin{Left,Right,Top,Bottom,Header,Footer}, PageLandscape, PaperSize, PageScale, FitToWidth, FitToHeight, HeaderText, and FooterText egenskaper plus SetPageMargins(L, R, T, B[, H, F]) convenience overloads. SaveAs emits the corresponding <pageMargins>, <pageSetup>, and <headerFooter> blocks between hyperlinks and drawings; öppna parses them back. Default-only kalkylblad stay untouched (PageSetupTouched flag gates output).
Version 2.17.21
- tillagt freeze-pane rundtur to the XLSX engine. TXLSXWorksheet exposes FreezePane(Col, Row) / UnfreezePane metoder plus läsa-only FreezeCol and FreezeRow egenskaper. SaveAs skriver a <sheetViews>/<pane state="frozen"> block before <sheetData> with the matching activePane and selection; öppna parses <pane state="frozen"> back into the freeze position so frozen-top/left/corner layouts survive a spara-and-reopen.
Version 2.17.20
- tillagt row and column outline (grouping) levels to the XLSX engine. TXLSXWorksheet exposes RowOutlineLevel[Row] and ColOutlineLevel[Col] indexed egenskaper plus SetRowOutlineLevel / HasRowOutlineLevel / ClearRowOutlineLevels and the matching column hjälpare. SaveAs emits outlineLevel attributes on <row> entries and merged <col> entries (combined with anpassad widths when present); öppna parses both attributes back into the kalkylblad so grouped row/column hierarchies survive the rundtur.
Version 2.17.19
- tillagt conditional formatting and data validation rundtur to the XLSX engine. New TXLSXCfOperator enum and TXLSXConditionalFormat class (område, Op, formel1, formel2) plus a TXLSXConditionalFormats collection on each kalkylblad (kalkylblad.ConditionalFormats). New TXLSXDataValidationType, TXLSXDvOperator, TXLSXDataValidation (område, ValidationType, Op, formel1, formel2, AllowBlank, ShowInputMessage, ShowErrorMessage), and a TXLSXDataValidations collection (kalkylblad.DataValidations) with an AddList(område, Items) shortcut for the common dropdown case. TXLSXWorksheet exposes AddConditionalFormat and AddDataValidation / AddListValidation hjälpare. SaveAs skriver <conditionalFormatting> blocks (with cfRule type="cellIs") and a <dataValidations> block after sheetData; öppna parses both blocks back into the collections.
Version 2.17.18
- tillagt defined-name rundtur to the XLSX engine. New TXLSXDefinedName class (Name, formel, SheetIndex) and a arbetsbok-level TXLSXDefinedNames collection (arbetsbok.DefinedNames) with Add(Name, formel[, SheetIndex]) overloads and IndexOfName lookup. SaveAs emits a <definedNames> block in xl/arbetsbok.xml; entries with SheetIndex >= 0 carry a localSheetId attribute (sheet-scoped) and entries with SheetIndex = -1 are arbetsbok-scoped. öppna parses <definedName> elements back into the collection so saved-and-reopened arbetsböcker keep their named områden intact.
Version 2.17.17
- tillagt image rundtur to the XLSX engine. New TXLSXImageFormat enum (png, jpeg, gif, bmp), TXLSXImage class (Row/Col anchor, WidthEMU/HeightEMU, Format, Data), and a per-kalkylblad TXLSXImages collection. TXLSXWorksheet exposes Images plus AddImage(Row, Col, Data, Format) and AddImageFromFile(Row, Col, FileName) hjälpare. SaveAs skriver 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 kalkylblad/drawing relationships, and emits a <drawing r:id="..."/> reference inside the kalkylblad. öppna parses drawingN.xml + drawing rels + media to rundtur images back into kalkylblad.Images.
Version 2.17.16
- tillagt anpassad number-format rundtur to the XLSX engine. New TXLSXNumberFormat class and a arbetsbok-level TXLSXNumberFormats collection (arbetsbok.NumberFormats) deduplicate format codes via Add(FormatCode). TXLSXCell exposes a new NumberFormatIndex egenskap; SaveAs emits a <numFmts> block in xl/stilar.xml (anpassad ids starting at the OOXML-reserved base 164) and pairs each format with a dedicated cellXf, öppna parses anpassad numFmts back and reverses the cellXf->numFmtId map into NumberFormatIndex on läsa. Precedence on conflict: FormatIndex > FontIndex > FillIndex > BorderIndex > NumberFormatIndex.
Version 2.17.15
- tillagt cell-border rundtur to the XLSX engine. New TXLSXBorderStyle enum, TXLSXBorderEdge class (stil + Color + ColorIsAuto for each side), TXLSXBorder class with Left/Right/Top/Bottom/Diagonal edges plus SetAll(stil[, Color]) hjälpare, and a arbetsbok-level TXLSXBorders collection (arbetsbok.Borders) with a Borders.AddBox(stil[, Color]) shortcut. TXLSXCell exposes a new BorderIndex egenskap; SaveAs emits each border into xl/stilar.xml and pairs it with a dedicated cellXf, öppna parses borders back and translates the cellXf->borderId map into BorderIndex on läsa. Precedence remains FormatIndex > FontIndex > FillIndex > BorderIndex when several are set on the same cell.
Version 2.17.14
- tillagt cell-fill rundtur to the XLSX engine. New TXLSXFillPattern enum and TXLSXFill class describe patternType, fgColor, and bgColor; the arbetsbok-level TXLSXFills collection is reachable via arbetsbok.Fills, with a Fills.AddSolid(color) convenience for the common solid-color case. TXLSXCell exposes a new FillIndex egenskap; SaveAs emits each fill into xl/stilar.xml and pairs it with a dedicated cellXf, öppna parses them back and reverses cell s attributes into FillIndex on läsa. FontIndex still takes precedence when both are set.
Version 2.17.13
- Completed the XLSX font rundtur. öppna now parses xl/stilar.xml back into arbetsbok.Fonts and a cellXf->fontId tabell; each cell's s attribute is mapped back into TXLSXCell.FontIndex so saved-and-reopened arbetsböcker bevara anpassad fonts (Name, Size, Bold, Italic, Strikethrough, Underline, Color).
Version 2.17.12
- tillagt a TXLSXFont class plus a arbetsbok.Fonts collection so XLSX celler can pick a anpassad font. TXLSXCell carries a new FontIndex egenskap; SaveAs emits the fonts list in xl/stilar.xml and one cellXf per font, then references the matching cellXf from each cell's s attribute. öppna rundtur of FontIndex is planned for the next release.
Version 2.17.11
- tillagt row-height rundtur to the XLSX engine. TXLSXWorksheet exposes a RowHeight[Row] egenskap plus SetRowHeight, HasRowHeight, and ClearRowHeights hjälpare. SaveAs skriver the ht and customHeight="1" attributes on each <row> with a customized height (including rows that only carry a height, with no cell data); öppna läser the ht attribute back into the row-height map.
Version 2.17.10
- tillagt column-width rundtur to the XLSX engine. TXLSXWorksheet exposes a ColWidth[Col] egenskap along with SetColWidth, HasColWidth, and ClearColWidths hjälpare. SaveAs emits a <cols> block with one <col> entry per customized column; öppna replays <col min/max/width> entries back into the kalkylblad so unmodified widths fall back to the Excel default.
Version 2.17.9
- tillagt cell-comment rundtur 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; öppna läser commentsN.xml back into the collection. kalkylblad rels, content types, and <legacyDrawing> wiring are handled automatically.
Version 2.17.8
- tillagt hyperlink rundtur to the XLSX engine. TXLSXWorksheet exposes a Hyperlinks collection and AddHyperlink(Row, Col, Url[, Display[, Tooltip]]) overloads. SaveAs skriver a <hyperlinks> block in each kalkylblad and emits a matching xl/kalkylblad/_rels/sheetN.xml.rels file with the external URL targets; öppna läser the kalkylblad rels first to resolve <hyperlink r:id="..."/> entries into URLs in the collection.
Version 2.17.7
- tillagt merged-cell rundtur to the XLSX engine. TXLSXWorksheet exposes a MergedCells collection and a MergeCells(R1, C1, R2, C2) convenience metod that mirror the BIFF facade stil. SaveAs emits a <mergeCells> block after sheetData, and öppna parses <mergeCell ref="A1:B2"/> entries back into the collection.
Version 2.17.6
- The XLSX engine now round-trips date values and formler. TDateTime cell values are serialized as Excel serial numbers and tagged with a built-in date cellXf so Excel renders them as dates; on öppna, celler whose stil references the date cellXf are decoded back to TDateTime variants. TXLSXCell exposes a new formel egenskap; SaveAs skriver the formel as a <f> child element and öppna parses <f> text back into the cell.
Version 2.17.5
- tillagt a stilar.xml scaffold to the XLSX engine. SaveAs now emits a minimum-valid xl/stilar.xml with default fonts, fills, borders, cellStyleXfs, and cellXfs entries, plus the corresponding content-type and arbetsbok-relationship registrations. celler carry a FormatIndex egenskap and emit the s="N" cell attribute when non-zero, and öppna läser s="N" back into FormatIndex. Concrete stil descriptors (fonts, fills, borders, cellXfs as arbetsbok-level collections) will be tillagt in follow-up commits.
Version 2.17.4
- tillagt shared strings (SST) stöd to the XLSX engine. SaveAs builds a deduplicated string tabell and emits xl/sharedStrings.xml, replacing inline string emission. öppna läser xl/sharedStrings.xml first and resolves t="s" cell references through the SST. Inline string celler from third-party XLSX files are still accepted on öppna.
Version 2.17.3
- Replaced the cell record array on TXLSXWorksheet with TXLSXCell objects and a TXLSXCells collection. The cell-access call site now läser kalkylblad.celler.Item[Row, Col].Value, matching the IXLSCells / IXLSRange shape on the BIFF facade. kalkylblad.celler.HasCell / celler.Count / celler.CellByIndex / celler.Clear are also available.
Version 2.17.2
- Introduced the TXLSXSheets collection class on TXLSXWorkbook, mirroring the IXLSWorkSheets collection on the BIFF facade. Code now läser arbetsbok.Sheets.Add / arbetsbok.Sheets.Count / arbetsbok.Sheets[i] / arbetsbok.Sheets.IndexByName instead of the previous arbetsbok.AddSheet / arbetsbok.SheetCount / arbetsbok.Sheet[i] metoder.
Version 2.17.1
- Renamed TXLSXWorkbook.SaveToFile to SaveAs and TXLSXWorkbook.LoadFromFile to öppna, matching the existing IXLSWorkBook naming stil. tillagt file-format and password overloads so the XLSX facade läser the same way as the BIFF facade. AddSheet now offers a no-argument overload that generates a default sheet name.
Version 2.17.0
- TXLSXWorkbook.SaveAs produces a minimum OOXML .xlsx archive with cell values (numbers, booleans, and inline strings). The archive contains content types, root relationships, arbetsbok + relationships, and a kalkylblad per sheet.
- TXLSXWorkbook.öppna läser back the minimum OOXML .xlsx archive — sheet names from xl/arbetsbok.xml and cell values from xl/kalkylblad/sheetN.xml. Shared strings, stilar, dates, and formler are not yet supported.
- tillagt OOXML namespace, content-type, and relationship constants plus reference / parsing / escape hjälpare (XlsxColumnLabel, XlsxCellRef, XlsxColumnIndex, XlsxParseCellRef, XlsxParseRangeRef, XlsxEscapeText, XlsxEscapeAttr) for use by future XLSX features.
Version 2.16.4
- The XLSX facade unit (lxHandleX) now defines its own arbetsbok and kalkylblad types (TXLSXWorkbook, TXLSXWorksheet), independent of the BIFF facade. spara and load entry points are reserved; the OOXML wiring will be filled in a follow-up release.
- tillagt a developer reference topic for the new XLSX facade, describing how lxHandle and lxHandleX coexist and which hjälpare units they share.
Version 2.16.3
- Introduced
lxHandleX, a dedicated XLSX facade unit that lives alongside the existinglxHandleBIFF facade. The two units share the same underlying infrastructure (stil 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 metod stubs accidentally tillagt 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.
Version 2.16.2
- tillagt 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 läsa/skriva engine is first enabled.
Version 2.16.1
- tillagt 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 skriva hjälpare);lxCacheStream(buffered stream wrapper that reduces underlying I/O calls);lxZlibStream(forward-only deflate/inflate stream, independent of the existingloZlibBIFF encryption binding);lxXmlReader(SAX-stil 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.
Version 2.16.0
- tillagt seven internal stil-infrastructure units as the foundation for the upcoming XLSX engine:
lxHashTable(generic hash tabeller 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 stilar covering all 12 BIFF line types and XLSX stil mappings);lxStyleXf(aggregates all five stil 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.
Version 2.15.1
- tillagt
lxRgbcolor utility hjälpare:RGBtoHLS,HLStoRGB,RGBTint, andGetRGBTintconvert between the RGB and HLS color spaces (0–240 HLS område). These underpin theme-color tint calculations, color-scale conditional formatting, and palette interpolation in XLSX output. - tillagt
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.
Version 2.15.0
- Reworked the HtmlHelp reference into a web-ready structure with dedicated topic, asset, script, stil, and source folders.
- tillagt a browser-friendly help home page and contents navigation page, with unified headers, topic shortcuts, and footers.