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