HotXLS 中文更新日志
面向 HotXLS 用户的中文版本历史,包含 XLS / XLSX 增强、修复、导出更新、兼容性变化和文档更新。
[Unreleased]
版本 2.88.111
- Classic XLS 工作表现在支持独立绘图 TextBox。 可使用
TXLSShapes.AddTextBox创建TXLSTextBox,并拥有独立的行列锚点、文本、text runs、线条/填充格式和普通 shape 删除能力,同时不会创建单元格批注。
版本 2.88.110
- ApiTour 例程现在覆盖更多 workbook 自动化模式。 Delphi 和 C++Builder ApiTour 示例展示了通过
WriteCells回调写入 range、通过ForEachCell扫描已加载单元格、通过FindText和ReplaceText更新模板文本、把选区导出到ApiTour-Range.html,以及 Delphi 端通过OnUserFunction处理自定义公式回调。
版本 2.88.109
- QuickStart 例程现在展示更完整的首个工作簿。 Delphi 和 C++Builder QuickStart 示例会生成带行汇总、列汇总公式、冻结窗格以及一致 XLS/XLSX 操作的样式化乘法表;例程目录现在也为每个示例提供美观的 HTML readme 页面。
版本 2.88.108
- XLSX range 现在提供直接 HTML 导出 helper。
TXLSXRange.SaveAsHTML(FileName)和TXLSXRange.SaveAsHTML(Stream)只把选定 XLSX range 导出为 UTF-8 HTML table,并复用 workbook HTML renderer 的转义、基础样式输出和合并单元格 span 处理。
版本 2.88.107
- XLSX 工作表现在提供文本查找和替换 helper。
TXLSXWorksheet.FindText与TXLSXWorksheet.ReplaceText按 row-major 顺序扫描已加载文本单元格,跳过公式和非文本值,并支持可选大小写敏感匹配,便于模板工作流。
版本 2.88.106
- BIFF8 Window2 view flags 现在会保留自定义网格线和冻结窗格状态。 当
Window2.icvHdr保存自定义 gridline color 时,HotXLS 现在会清除fDefaultHdr,open/save 期间保留 Excel 写入的fFrozenNoSplit,并在FreezePanes输出中写入fFrozenNoSplit。
版本 2.88.105
- CF12 公式阈值现在可在 BIFF8 Data Bar、Color Scale 和 Icon Set 规则中 round-trip。 基于公式的 threshold value 保存时会编译为 CF12 formula token bytes,重新打开 workbook 时会恢复到
TXLSCfValue.Value。
版本 2.88.104
- Classic XLS 公式和图标集阈值现在写出更紧凑的 BIFF8 记录。 公式里的整数常量在符合 BIFF unsigned-integer 范围时会使用紧凑的
tInttoken,TXLSIconSetSpec.ThresholdEqualsInclude[Index]现在可控制 CF12 icon-set threshold equals byte,让调用方选择 include 或 exclude 比较语义。
版本 2.88.103
- Classic XLS 工作表现在提供文本查找辅助方法。
IXLSWorksheet.FindText(SearchText, Row, Col[, MatchCase])可定位第一个匹配的已加载文本单元格,跳过公式和非文本单元格,并在未命中时清空返回坐标。
版本 2.88.102
- Classic XLS 工作表现在提供文本替换辅助方法。
IXLSWorksheet.ReplaceText(SearchText, ReplacementText[, MatchCase])会替换已加载文本单元格中的匹配内容,跳过公式和非文本单元格,并为模板填充流程返回已修改单元格数量。
版本 2.88.101
- Range 现在提供直接 HTML 导出辅助方法。
IXLSRange.SaveAsHTML(FileName)和IXLSRange.SaveAsHTML(Stream)通过既有 HTML 渲染器导出选定区域,常见区域片段导出不再需要调用方创建TXLSHTMLExport实例或显式传入xlHTML。
版本 2.88.100
TXLSWorkbook.GetSheetNames(Stream, AList)现在既能读取 XLSX package 流,也能读取 Classic XLS 流。应用程序可把内存流、数据库 BLOB 流或下载得到的 XLSX 流传给 classic facade,无需先保存为文件即可取得按顺序排列的工作表名称。
版本 2.88.99
- 工作表查找、超链接创建和多区域选择 API 现在更易用。Classic XLS 和 XLSX 的工作表集合新增
TryGetSheetByName,Classic XLS 工作表新增AddHyperlink便捷重载,IXLSWorksheet.SelectAreas可写入活动的多区域选择。
版本 2.88.98
- Classic XLS 工作簿现在公开 saved-by 字段的
UserName别名。IXLSWorkbook.UserName映射到与LastSavedBy相同的 WRITEACCESS 值,因此采用UserName命名习惯的代码可以直接读取和更新工作簿审计名称。
版本 2.88.97
- XLSX 工作表现在也提供回调式单元格扫描和区域写入 helper。
TXLSXWorksheet.ForEachCell按行顺序枚举已载入单元格并传出值和公式文本;TXLSXWorksheet.WriteCells可用回调填充数字区域或 A1-style 区域,并支持逐单元跳过和取消。
版本 2.88.96
- Classic XLS 工作表现在支持回调驱动的区域写入。
IXLSWorksheet.WriteCells按行顺序填充 1-based 数字区域或 A1-style 区域,让回调提供每个单元格的值,支持逐单元跳过,并可提前取消长时间写入循环。
版本 2.88.95
- Classic XLS 工作表现在可以通过回调枚举已载入的单元格。
IXLSWorksheet.ForEachCell按行顺序遍历工作表中实际存在的单元格,传入 1-based 的工作表、行和列坐标以及值和公式文本,并允许回调提前取消长时间扫描。
版本 2.88.94
- 公式计算现在可以调用应用程序定义的函数。
TXLSWorkbook.OnUserFunction和TXLSXWorkbook.OnUserFunction允许Calculate将自定义或尚不支持的工作表函数交给应用代码处理,传入已求值的参数,并在处理后使用返回的Variant结果。
版本 2.88.93
- Classic XLS 工作表保护现在公开了按操作控制的权限标志。
IXLSWorksheet新增AllowDeleteRows、AllowInsertRows、AllowFormatCells、AllowSort、AllowAutoFilter以及其余 SheetProtect 权限属性,并通过现有保护记录写入和读回 BIFF8 选项。
版本 2.88.92
- Classic XLS VBA payload 现在提供显式 load/save/clear helper。
IXLSWorkbook.LoadVBAProjectFromFile、SaveVBAProjectToFile、HasVBAProject和ClearVBAProject公开保留的 OLE VBA storage payload;VBAProject仍作为只读解析模块视图。
版本 2.88.91
- Classic XLS AutoFilter 条件现在可以通过字段集合检查。
IXLSWorksheet.AutoFilterColumns会公开当前 BIFF8 AutoFilter 字段数和 1-based 字段项,包括 active 状态、operator,以及存储的Criteria1/Criteria2DOPER 值。
版本 2.88.90
- Classic XLS worksheets 现在支持一次调用完成 AutoFilter 条件设置。
IXLSWorksheet.ApplyAutoFilter会在同一次调用中设置 worksheet AutoFilter 区域并写入字段条件,支持 A1-style 和 1-based 数字区域重载,也支持可选的双条件 operator。
版本 2.88.89
- Classic XLS shapes 现在可以按单元格区域删除。
TXLSShapes.DeleteInRange会删除 OfficeArt client anchor 与 1-based 工作表区域相交的 anchored picture 或 shape,并返回删除的 shape 数量。
版本 2.88.88
- Classic HTML export 的 table layout attributes 现在可以配置。
TXLSHTMLExport.TableBorderWidth、CellPadding和CellSpacing可控制 styled 与 simple HTML output 生成的<table>attributes,默认仍为旧的 0 值。
版本 2.88.87
- Classic HTML export 现在支持 minimal table output。
TXLSHTMLExport.SimpleExport会写出普通 HTML table,不生成 CSS classes、hyperlink anchors 或 comment title attributes,同时保留转义后的 display text 和 merged-cell spans。
版本 2.88.86
- Classic HTML export 现在可以写入 document title。
TXLSHTMLExport.Title会在生成的 style block 之前写出转义后的 HTML<title>element;默认空值保持既有输出不变。
版本 2.88.85
- Classic HTML export 现在会把 cell comments 导出为 tooltip。
TXLSHTMLExport.Options现在默认包含xhComments,会把 cell comment text 作为转义后的titleattribute 写出;调用方仍可移除该 option,得到普通 cell output。
版本 2.88.84
- Classic HTML export 的 hyperlink 输出现在可以配置。
TXLSHTMLExport.Options默认是[xhHyperlinks],保持既有行为;调用方可以移除xhHyperlinks,把带 link 的单元格导出为普通转义文本。
版本 2.88.83
- Classic HTML export 现在会保留单元格 hyperlink。
SaveAsHTML会把带 link 的单元格包装成 HTML anchor tag,将 hyperlink address 作为转义后的href输出,把 ScreenTip text 作为转义后的titleattribute 输出,并保持显示的 cell text 在 link 内正确转义。
版本 2.88.82
- Classic XLS workbook 现在可以控制 saved-by 用户名。
IXLSWorkbook.LastSavedBy公开 WRITEACCESS saved-by 字段,让生成或编辑后的 workbook 可以保存明确的审计名称,同时未编辑的源 workbook 继续保留原始 metadata。
版本 2.88.81
- Classic XLS 工作表现在可以控制显示网格线的颜色索引。
IXLSWorksheet.GridlineColorIndex公开 Window2icvHdr字段,让保存后的工作表能以指定网格线颜色重新打开,同时不改变网格线可见性或打印网格线设置。
版本 2.88.80
- Classic XLS workbook 现在可以按索引设置 active sheet。
IXLSWorkbook.ActiveSheetIndex公开基于 WINDOW1 active sheet 字段的 1-based active-tab 属性,让保存后的 workbook 可以在指定 worksheet 上重新打开,而不改变 first visible tab。
版本 2.88.79
- Classic XLS worksheet outline 现在可以控制 automatic outline styles。
TXLSOutline.ApplyStyles公开 WSBool 的 outline style 标志,让保存后的 worksheet 可以保留或显式启用 Excel outline style application,而不改变 outline levels 或 summary 位置。
版本 2.88.78
- Classic XLS page setup 现在可以控制 automatic page breaks。
IXLSPageSetup.AutoPageBreaks公开 worksheet WSBool 的 automatic page-break 标志,让保存后的 worksheet 可以保持 automatic page breaks 启用,或显式禁用它,同时保留 manual page breaks。
版本 2.88.77
- Classic XLS workbook 现在可以控制 AutoFilter 日期分组。
IXLSWorkbook.AutoFilterDateGrouping以正向 Boolean API 公开 Window1 的 date-grouping 标志,让保存后的 workbook 可以保持 Excel 日期筛选分组启用,或显式禁用它。
版本 2.88.76
- Classic XLS workbook 现在可以直接设置 workbook window 位置和尺寸。
IXLSWorkbook.XWindow、YWindow、WindowWidth和WindowHeight公开 Window1 geometry 字段,保存后的 workbook 可按指定 window rectangle 重新打开。
版本 2.88.75
- Classic XLS workbook 现在可以直接保存 workbook window hidden 状态。
IXLSWorkbook.WindowHidden映射到 Window1 hidden 标志,保存后的 workbook 可在不改变 worksheet 可见性的情况下以 workbook window hidden 状态重新打开。
版本 2.88.74
- Classic XLS workbook 现在可以直接保存 workbook window minimized 状态。
IXLSWorkbook.Minimized映射到 Window1 minimized 标志,保存后的 workbook 可在重新打开时让 workbook window 保持 minimized。
版本 2.88.73
- Classic XLS workbook 现在可以直接隐藏或显示垂直滚动条。
IXLSWorkbook.ShowVerticalScroll映射到 Window1fDspVScroll标志,保存后的 workbook 可在打开时隐藏或显示垂直滚动条。
版本 2.88.72
- Classic XLS workbook 现在可以直接隐藏或显示水平滚动条。
IXLSWorkbook.ShowHorizontalScroll映射到 Window1fDspHScroll标志,保存后的 workbook 可在打开时隐藏或显示水平滚动条。
版本 2.88.71
- Classic XLS workbook 现在可以直接隐藏或显示 sheet tab bar。
IXLSWorkbook.ShowSheetTabs映射到 Window1fDspTabs标志,保存后的 workbook 可在不改变 worksheet 可见性的情况下隐藏或显示 sheet tabs。
版本 2.88.70
- Classic XLS workbook 现在可以直接设置 workbook tab bar 比例。
IXLSWorkbook.TabRatio公开 Window1wTabRatio值,调用方可以调整 sheet tabs 与水平滚动条之间预留空间的比例。
版本 2.88.69
- Classic XLS workbook 现在可以直接设置第一个可见 sheet tab。
IXLSWorkbook.FirstSheet将 Window1itabFirst值作为 1-based 属性公开,调用方可以选择 Excel 打开 workbook 时显示在左侧边缘的 sheet tab。
版本 2.88.68
- Classic XLS worksheet 现在可以保留并设置 outline symbols 可见性。
IXLSWorksheet.DisplayOutlineSymbols映射到 BIFF WINDOW2fDspGuts标志,保存后的 sheet 可在窗口视图中隐藏 outline 和 grouping 符号。
版本 2.88.67
- Classic XLS worksheet 现在可以保留并设置行列标题可见性。
IXLSWorksheet.DisplayHeadings映射到 BIFF WINDOW2fDspRwCol标志,保存后的 sheet 可在窗口视图中隐藏行号和列标。
版本 2.88.66
- Classic XLS worksheet 现在可以保留并设置显示公式视图。
IXLSWorksheet.DisplayFormulas映射到 BIFF WINDOW2fDspFmla标志,让 Excel 打开 sheet 时显示公式文本而不是计算结果。
版本 2.88.65
- Classic XLS worksheet 现在可以独立设置 Normal view 缩放。
IXLSWorksheet.NormalViewZoom公开 WINDOW2 Normal zoom 缓存,因此 sheet 处于 Page Break Preview 时也能保存不同的缩放级别。
版本 2.88.64
- Classic XLS worksheet 现在可以直接设置 Page Break Preview 缩放。
IXLSWorksheet.PageBreakPreviewZoom公开 WINDOW2 preview zoom 缓存,调用方可保存不同的 Normal 和 Page Break Preview 缩放级别。
版本 2.88.63
- Classic XLS worksheet 现在提供拆分窗格辅助入口。
IXLSWorksheet.SplitPanes(Width, Height)通过既有 BIFF pane writer 创建可拖动窗格拆分,UnsplitPanes会在保存前清除 pane record。
版本 2.88.62
- Classic XLS worksheet 现在提供更简单的冻结窗格辅助入口。
IXLSWorksheet.FreezePanes(Cols, Rows)可冻结指定的左侧列和顶部行,UnfreezePanes会在保存前移除 pane record。
版本 2.88.61
- Classic XLS sheet 名称发现现在接受流。
TXLSWorkbook.GetSheetNames(Stream, List)可从调用方提供的 XLS stream 读取 BIFF sheet 名称,不加载 worksheet 内容,让内存中的 workbook 数据也能使用与文件名辅助入口一致的快速读取方式。
版本 2.88.60
- Worksheet collection 现在提供按名称直接查找对象的辅助入口。
IXLSWorkSheets.SheetByName(Name)和TXLSXSheets.SheetByName(Name)返回匹配的 worksheet 对象或nil,调用方不再需要先解析 index 再访问 sheet。
版本 2.88.59
- XLSX facade 现在可以直接从流读取 sheet 名称。
TXLSXWorkbook.GetSheetNames(Stream, List)从xl/workbook.xml按顺序读取名称,而不加载 worksheet XML,与文件名重载一样适用于内存和 BLOB 存储的工作簿。
版本 2.88.58
- XLSX facade 现在公开快速 sheet 名称读取入口。
TXLSXWorkbook.GetSheetNames(FileName, List)从xl/workbook.xml按顺序读取名称,而不加载 worksheet XML。
版本 2.88.57
TXLSWorkbook.GetSheetNames现在支持 XLSX 包。该方法会从.xlsx、.xlsm、.xltx和.xltm文件读取xl/workbook.xml,并在不加载 worksheet XML 的情况下按顺序返回 sheet 名称。
版本 2.88.56
- 经典 XLS 工作簿现在可以不加载工作表即可读取 sheet 名称。
TXLSWorkbook.GetSheetNames(FileName, List)扫描 workbook globals stream,并从 Excel 97-2003.xls文件按顺序返回 sheet 名称。
版本 2.88.55
- 经典 XLS range AutoFilter 条件现在会写出 BIFF8 筛选记录。
TXLSRange.Autofilter(Field, Criteria)会在需要时创建筛选范围,并为简单字符串、数值、Boolean、空白、非空白以及带比较前缀的条件写出AUTOFILTER条件。
版本 2.88.54
- 经典 XLS worksheet 现在提供 worksheet 级 AutoFilter 辅助入口。
IXLSWorksheet.SetAutoFilter、ClearAutoFilter和AutoFilterRange可直接管理 BIFF8 筛选下拉区域,并复用现有AUTOFILTERINFO与筛选数据库名称写出路径。
版本 2.88.53
- 经典 XLS worksheet 现在支持创建列表型数据验证。
IXLSWorksheet.AddListValidation(Range, Items)会写入 BIFF8DVAL和DV记录,默认保留下拉列表,支持逗号分隔的内联列表,并能在Open/SaveAs往返后保留规则。
版本 2.88.52
- 公式计算现在可在 XLS 和 XLSX 入口之间保持一致。
TXLSWorkbook.Calculate现在接受类似 Excel 的前导等号公式,例如=SUM(A1:B1)+C1。XLSX 外观接口新增TXLSXWorkbook.Calculate和TXLSXWorksheet.Calculate。XLSX 路径会共享 HotXLS 公式标记解析器和求值器,用于单元格与区域引用、被公式引用的单元格、跨工作表引用,以及工作簿或工作表作用域的定义名称区域。
版本 2.88.51
- XLSX range 现在支持 Excel 风格的 merge across。
TXLSXRange.Merge(True)会按每行写出一个<mergeCell>条目,对齐经典 XLSRange.Merge(True)行为;无参Merge和Merge(False)仍创建一个覆盖完整 range 的合并矩形。
版本 2.88.50
- BIFF8 HeaderFooter 与 HFPicture 的位置现在对齐当前 MS-XLS 规则。 HotXLS 会保留 Excel 写入的
HeaderFooter($089C) 记录,用于奇偶页 / 首页不同的页眉页脚文本,并按 worksheet ABNF 在 worksheet dimensions 与 drawing objects 之后回放HFPicture($0866) 记录,因此 .xls 打开/保存往返不再丢失这些页面布局细节。
版本 2.88.49
- 批注富文本 run 现在提供 typed API。
TXLSComment.TextRuns暴露 BIFF8TXOFormatRun条目,调用端可以检查或设置 .xls 批注里的逐字符字体边界,同时 HotXLS 仍保留底层 run 字节以保证安全 round-trip。
版本 2.88.48
- PivotTable supplemental SX records 现在可通过 typed API 查看。 HotXLS 现在会把已加载的 BIFF8 pivot 记录(例如
SXIVD、SXLI、SXFormat、SXEx、SXVDEx、SXRule、SXFilt、SXAddl)挂到TXLSPivotTable.SupplementalRecords供调用方检查,同时保存时仍保留原始 raw bytes 以确保往返安全。
版本 2.88.47
- 外部工作簿 cached values 现在可在 .xls 打开/保存往返中保留。 HotXLS 现在会保留已加载
SUPBOOK条目附带的 BIFF8XCT和CRN记录,因此外部工作簿链接的 cached cell values 不再在保存时丢失。
版本 2.88.46
- 内置样式 outline level 现在可在 .xls 打开/保存往返中保留。 HotXLS 现在会读取并保留内置样式的 BIFF8
STYLEiLevel字节,因此 Excel 的 RowLevel_1..7 和 ColLevel_1..7 样式元数据不再在保存时被重置为默认值。
版本 2.88.45
- 定义名称元数据现在可在 .xls 打开/保存往返中保留。 HotXLS 现在会在定义名称未被编辑时保留已加载 BIFF8
NAME记录的 option bits 和 shortcut 字节,因此 Excel 写入的 function、object、procedure、calculated-expression、binary-name 等元数据不再在保存时被清空。
版本 2.88.44
- ObProj 工作簿 marker 现在可在 .xls 打开/保存往返后保留。 HotXLS 现在会保留读取到的 BIFF8
ObProj记录,即使对象模型没有暴露 VBA storage,也不会在保存时丢失工作簿级 VBA project marker 和第三方元数据。
版本 2.88.43
- 工作表选项 flag 现在可在 .xls 打开/保存往返后保留。 HotXLS 现在会保留未建模的 BIFF8
WSBOOL位,例如对话框工作表、自动分页、样式应用和 outline gutter 显示 flag,同时仍通过公开 API 更新现有的适合页面和 outline 汇总设置。
版本 2.88.42
- 更多工作簿元数据记录现在可在 .xls 打开/保存往返后保留。 HotXLS 现在会保留读取到的 BIFF8
COUNTRY、BOOKBOOL、BACKUP、FNGROUPCOUNT、USESELFS和RECALCID记录 body,而不是用默认值重写,从而保持工作簿级兼容性和计算元数据稳定。
版本 2.88.41
- 多区域选择和活动窗格焦点现在可在 .xls 打开/保存往返后保留。 HotXLS 现在会保留读取到的 BIFF8
SELECTION记录和PANES活动窗格值,除非通过 API 修改工作表选择或窗格,因此 Excel 的拆分/冻结窗格焦点和多区域选择不再在保存时被折叠。
版本 2.88.40
- 外部工作簿名现在可在 .xls 打开/保存往返后保留。 HotXLS 现在会保留挂在外部
SUPBOOK项下的 BIFF8EXTERNALNAME记录,包括 DDE/OLE/链接元数据和公式尾部,因此保存时不再丢失外部名称和链接定义。
版本 2.88.39
- 受密码保护的 BIFF8 .xls 文件现在会写入并读取 RC4 CryptoAPI FILEPASS 记录。 HotXLS 现在为加密 .xls 工作簿写出 Excel 2007/2010 风格的
FILEPASSvMajor=2 元数据,并可读取旧 RC4 vMajor=1 与 RC4 CryptoAPI vMajor=2/3/4 文件,因此受密码保护的工作簿不再因该加密头失败,也不会继续降级到旧式加密头。
版本 2.88.38
- Excel 写入的 .xls 超链接元数据现在可在打开/保存往返后保留。 HotXLS 现在对读取到且未被编辑的超链接保留 BIFF8
HLinkrecord body,使源文件中的streamVersion、hlstmfoption bits(例如fIcon)、moniker 数据和相关目标元数据在保存后保持稳定。
版本 2.88.37
- 工作簿窗口状态现在可在 .xls 打开/保存往返后保留。 HotXLS 现在读取并保留 BIFF8
WINDOW1记录中的窗口位置、尺寸、可见/最小化 flags、首个显示的工作表标签、选中标签数量以及标签滚动条比例,不再在每次保存时改写为默认值。
版本 2.88.36
- BIFF8 WriteAccess 的 saved-by 用户现在可在 .xls 打开/保存往返后保留。 HotXLS 现在读取并保留
$005C WRITEACCESSrecord body,不再把 Excel 写入的 saved-by 用户替换为HotXLS,因此工作簿审计元数据在保存后保持稳定。
版本 2.88.35
- Excel comment author 现在能在 .xls open/save round-trip 后保留。BIFF8
Note记录的stAuthor字段现在会被解析并传入 drawing note model,而不是被替换成空字符串,因此 Excel 写入的 comment "Created by" 作者名在 HotXLS 再次保存 workbook 时不会丢失。
版本 2.88.34
- Shape OfficeArt FOPT options 现在通过低层 option bag 暴露。
TXLSShape.OfficeArtOptions允许高级调用方把任意已保存的 FOPT PID 作为LongWord或WideString检查、设置和删除,同时现有高层Line、Fill、颜色和可见性 API 保持不变。
版本 2.88.33
- 更多 OfficeArt solver-container 规则记录现在可以往返保留。除了强类型
msofbtConnectorRule($F012),HotXLS 现在会把OfficeArtFArcRule($F014) 和OfficeArtFCalloutRule($F017) 等非 folder solver children 作为原始 OfficeArt 记录保存在msofbtSolverContainer($F005) 内,因此高级 Excel drawing 在保存时不再丢失非连接线 solver 关系。
版本 2.88.32
- OfficeArt ClientData marker 不再因 unknown-record preservation 被重复写出。MS-XLS 将
OfficeArtClientData($F011)定义为零长度 marker,后续Obj仍是独立 BIFF record。v2.88.32 会识别该 marker,而不是把它当作 unknown SpContainer leaf 捕获,因此解析后的 shape 保存时只写出一个 $F011 marker;不符合 XLS 规范的 container-style 假设仍不进入 XLS 路径。
版本 2.88.31
- OfficeArt connector rule 现在能 round-trip。Excel 创作的 .xls drawing 会在
msofbtSolverContainer($F005)下保存msofbtConnectorRule($F012)子记录。v2.88.31 通过TMsoConnectorRules解析并写回这组 $F005/$F012 记录,在 save/reload 间保留起点 shape、终点 shape、连接线 shape 与两端连接点。早前 audit note 写成 $F121,但 MS-ODRAW 将OfficeArtFConnectorRule定义为 $F012。
版本 2.88.30
- OfficeArt SpContainer 内未识别的 leaf 记录现在能 round-trip。Excel 创作的 .xls 文件常在每个 shape 的 SpContainer 内嵌入
msofbtClientTextbox($F00D),OfficeArtFPSPL($F11D), andOfficeArtUDefProp($F122)等 leaf Fbt。v2.88.30 将 shape-level unknown leaf 捕获为TMsoFbtUnknown,并在 shape 的ClientAnchor与尾部零 bodymsofbtClientDatamarker 之间按 parse 顺序 re-emit。 - 范围与后续。其他 drawing-level unknown leaf 仍 defer;connector-rule solver-container 场景已由 v2.88.31 处理。Container 形态 unknown,例如
msofbtClientData($F011)作为 container 而非 sibling marker 使用,仍保留到 audit-round Slice 3。
版本 2.88.29
- ComboBox 和 ListBox OBJ 未知子记录现在能 round-trip。TMSOShapeComboBox.ParseObj 和 TMSOShapeListBox.ParseObj 已经把 FtSbs ($000C)、FtSbsFmla ($000E) 和 FtLbsData ($0013) typed-parse 到专门字段,但出现在 CMO 与 FtLbsData 之间的其他源文件子记录(FtMacro $0004、ObjLinkFmla、FtNts $000D 等)在 case fall-through 时被静默丢弃。v2.88.29 加同 v2.88.28 Picture 的 else 分支,把未知子记录的 4 字节 header + body 捕获到
FObjTailRaw。两个 AddObj 方法在 CMO body 与 FtSbs 子记录之间输出捕获的字节,匹配 BIFF8 spec 的子记录排序。 - FtLbsData 的吞噬全部行为限制了范围。现有的
$0013case 覆盖RecLen := Len - offs把 FtLbsData header 之后的所有字节吸入FObjRec_LBSData的 blob,所以出现在 FtLbsData 之后的子记录(通常只是 FtEnd)仍然通过该机制 round-trip 不变。新的 FObjTailRaw 整合专门针对 FtLbsData 之前的间隙,FtMacro 和 ObjLinkFmla 通常在那里。通过 Drawing API 新创建的 combo / list 框FObjTailRaw为空 → 与 v2.88.28 字节级一致输出。
版本 2.88.28
- Picture 形状 OBJ 未知子记录现在能 round-trip。TMSOShapePicture.ParseObj 已经把 FtCf ($0007)、FtPioGrbit ($0008) 和 FtPictFmla ($0009) typed-parse 到专门字段,但其他源文件子记录(FtMacro $0004、FtNts $000D 等)在 case fall-through 时被静默丢弃。v2.88.28 加 else 分支把未识别子记录的完整 4 字节 header + body 追加到
FObjTailRaw;TMSOShapePicture.AddObj 在其 typed 子记录输出之后、FtEnd 标记之前按字节输出这些字节。带有 macro hooks 的源文件 picture 对象在 resave 后能保留。 - typed + raw 共存模式。与 PictureFrame(v2.88.27)使用 if/else 在 typed 与 raw emit 之间切换不同,Picture 把两者结合:typed 字段保留 API 表面(调用方仍可调整
ftCfValue等),而 raw tail 只保留未知字节。通过 Drawing API 新创建的图片FObjTailRaw为空,所以输出与 v2.88.27 字节级一致。
版本 2.88.27
- OBJ 尾部子记录 round-trip 扩展到 PictureFrame 形状。TMSOShapePictureFrame.AddObj 之前只在 CMO 和 FtEnd 之间输出 legacy 硬编码 FtCf ($0007, body $FFFF) 和 FtPioGrbit ($0008, body $0000) 子记录。对新创建的图片框,新代码仍输出这些默认值;对从源 .xls 解析的图片框,捕获的
FObjTailRaw字节按字节输出替代,保留源文件的 FtPictFmla / 非默认 FtCf / 非默认 FtPioGrbit 内容。 - 调研笔记 — Flush 自动修正 sz。
TMsoShapeContainer.Flush在 commit 时通过Data.SetWord(Data.DataLength - 4, 2)重写 Obj 记录的 size 头部,意味着多年来存在于 HotXLS AddObj 实现中的硬编码sz := $1A值其实不是 spec bug —— Flush 自动修正它们。v2.88.27 仍精确计算 sz 用于代码可读性,但运行时行为从该视角看没变化。
版本 2.88.26
- OBJ 尾部子记录 round-trip 扩展到 Chart 和 CheckBox 形状。v2.88.25 引入了对 Obj 记录 CMO($0015)与 FtEnd($0000)标记之间字节的原始字节保留,但只有 TMSOShapeTextBox.AddObj 输出捕获的尾部。本版本把同样 pattern 应用到 TMSOShapeChart.AddObj 和 TMSOShapeCheckBox.AddObj —— 它们都与 TextBox 共享简单的"CMO + FtEnd" 输出结构,所以改动只是一行变量替换(
sz := $1A + Word(Length(FObjTailRaw)))加 FtEnd 标记前的一个字节级 emit 循环。 - Chart 的尾部子记录(如嵌入图表对象 macro 的 FtMacro)与 checkbox 的状态子记录(FtCbls + FtCblsData + ObjLinkFmla,MS-XLS §2.5.140-141 / §2.5.149)现在能保留 HotXLS 保存/重载。通过 Drawing API 新创建的 chart 和 checkbox 仍然输出默认 26 字节 CMO+FtEnd(与 v2.88.25 字节级一致),所以现有调用方看不到行为变化。Picture / ComboBox / ListBox / PictureFrame 有自己的动态 typed-subrecord 输出,与 FObjTailRaw 冲突 —— 它们的整合留待后续 commits。
版本 2.88.25
- OBJ 记录的尾部子记录现在能保留过保存周期(针对注释)。BIFF8 Obj 记录($005D)在强制 CMO($0015)之后串接一系列类型化子记录,以 FtEnd($0000)标记终止,参见 MS-XLS §2.4.181。对 Note(注释)形状,尾部块通常是一个 26 字节的 FtNts(§2.5.149),携带 GUID 与 fSharedNote 标志 —— 当 Excel 后续在共享工作簿中跨用户合并注释时两者都至关重要。HotXLS 之前在读端丢弃 CMO 后面的所有字节,在写端只输出空 FtEnd,所以源文件的 FtNts 在 HotXLS 每次另存后丢失。
- 基类捕获,仅 TextBox 输出(R5-3 first slice)。TMsoShapeContainer.ParseObj 现在把 CMO 体结束到 FtEnd 标记之间的字节范围捕获到新内部字段
FObjTailRaw: TBytes;TMSOShapeTextBox.AddObj 把这些字节插入到其 CMO 输出和 FtEnd 标记之间,并相应调整 Obj 记录头部 size。新创建的注释(没有源字节)保持与 v2.88.24 字节级一致输出。其他 shape 类(Picture / CheckBox / ComboBox / ListBox / Chart)继承捕获但它们的类型化 AddObj 覆写保留"从头合成"行为 —— 对这些 shape 类型的 raw-bytes 输出留待后续 commits。
版本 2.88.24
- 多字体多颜色单元格批注现在能往返保留。BIFF8 TXO 记录的格式化运行块(
rgTxoRuns+TxOLastRun,参见 MS-XLS §2.5.272)携带每个 run 的字体和颜色覆盖,赋予批注其富文本样式。HotXLS 之前在读端丢弃整个块,在写端输出单个空的默认 run + LastRun —— 把红色高亮的"重要!"或批注文本中加粗的词在 HotXLS 每次另存后压平为统一默认格式。 - TMSOShapeTextBox 的字节级保留。ParseTXO 把文本后的 Continue 字节按字节存到新的内部
FFormatRunsRaw: TBytes字段;Store 将其作为格式化运行 Continue 写回,并调整基础记录的cbRuns头部以匹配。新创建的批注(通过AddComment)保留旧的单个默认运行输出不变,所以默认工作簿保留字节级一致输出。对单个格式运行的类型化 Excel-API 访问仍延后 —— 现有单 WideString 批注 API 未变。
版本 2.88.23
- 打印分辨率与份数现在能往返保留 —— Setup 记录字段全覆盖。Setup 记录中三个 Word 字段(
iRes偏移 12、iVRes偏移 14、iCopies偏移 32,参见 MS-XLS §2.4.257)携带 Excel "页面设置 → 页面 → 打印质量"和"打印份数"选择。HotXLS 之前在读端把三者都丢弃,写端输出硬编码值(600 DPI / 600 DPI / 1 份)—— 所以用户调整的分辨率或份数在每次 HotXLS 另存后悄悄回到默认。 - 新增三个 TXLSPageSetup 属性。
PrintResolution: LongWord、PrintVResolution: LongWord和Copies: LongWord—— 默认值都与写入器之前的硬编码值一致(600 / 600 / 1),所以不触碰这些属性的工作簿对 v2.88.22 保持字节级一致输出。Setter 钳到High(Word)防止越界值在写出时发生回绕。 - Setup 记录 round-trip 工作收官。本次修复后,BIFF8 Setup 记录($00A1)的每个用户可见字段都能端到端 round-trip —— 纸张大小 / 缩放 / 起始页号 / 适应页面宽高 / 方向 / 打印顺序 / 黑白 / 草稿 / 打印注释 / 单元格错误 / 分辨率 / 份数。剩下只有两个 spec hint grbit bits(
fNoPls、fNoOrient)未暴露 —— HotXLS 都写零,与 Excel 默认行为一致。
版本 2.88.22
- 自定义"起始页码"现在能往返保留。BIFF8 Setup 记录把工作簿的 页面设置 → 页面 → "起始页码" 选择以两个相关字段携带:grbit bit 7(
fUsePage)在 Excel 的"自动"默认值与显式起始页号之间选择,offset 4 的 signed Word(iPageStart)保存自定义值,参见 MS-XLS §2.4.257。HotXLS 之前两者都在读端丢弃,写端输出iPageStart = 1且 bit 清零 —— 所以用户输入的"起始页码: 100"在 HotXLS 每次另存后悄悄回到"自动"。 - 新增两个 TXLSPageSetup 属性。
UseFirstPageNumber: Boolean反映该 bit(False = "自动",默认);FirstPageNumber: Integer携带 iPageStart 值(默认 1,setter 钳到 spec signed Word 范围 -32768..32767)。HotXLS 即使在UseFirstPageNumber为 False 时也把iPageStart按字节往返,所以在 Excel 中切换自动与自定义时保留最后用户输入的值。
版本 2.88.21
- "在工作表末尾打印批注"选择现在能保留过保存周期。BIFF8 Setup 记录的 grbit bit 9(
fEndNotes,参见 MS-XLS §2.4.257)携带 页面设置 → 工作表 → 注释下拉框中"显示在工作表中"(默认)与"工作表末尾"的区别。HotXLS 已经能往返 PrintNotes(bit 5)控制注释是否打印,但 bit 9 在读端被丢弃、写端输出零 —— 所以用户选择的"工作表末尾"在 HotXLS 每次另存后悄悄回到"显示在工作表中"。 - 新增 TXLSPageSetup.PrintNotesAtEnd 布尔属性。默认
False,与 Excel UI 默认值一致。读写两端按字节往返该 bit(即使PrintNotes = False),所以临时禁用批注的工作簿在用户重新启用批注时仍保留"末尾"偏好 —— 与 Excel 自身行为一致。
版本 2.88.20
- 工作簿"将精度设为所显示的精度"选择现在能往返保留。BIFF8 CalcPrecision 记录($000E)携带工作簿级 文件 → 选项 → 高级 → "将精度设为所显示的精度"复选框,参见 MS-XLS §2.4.35。HotXLS 之前没有 $000E 的 dispatcher case,TXLSWorkbook.StorePrecision 输出硬编码
1(= 保留全精度)。用户勾选的"将精度设为所显示的精度"在 HotXLS 每次另存后悄悄回到"全精度"—— 隐藏了用户希望后续重算时永久把单元格值截断到 cell 格式显示位数的意图。 - 新增 TXLSWorkbook.UseFullPrecision 布尔属性。默认
True(与 BIFF8 默认值和 Excel UI 默认 未勾选状态一致)。设置False等同勾选破坏性的"按显示精度"选项 —— HotXLS 本身不在 round-trip 期间截断任何 cell 值,但该标志现在被准确写回,所以 Excel 下次重算时会遵守。本次修复后,每个 BIFF8 calc record(CalcCount / CalcMode / CalcPrecision / CalcDelta / CalcIter / CalcSaveRecalc)都能端到端 round-trip。
版本 2.88.19
- "保存前重新计算工作簿"复选框现在能往返保留。BIFF8 CalcSaveRecalc 记录($005F)携带工作簿的 文件 → 选项 → 保存 → "保存前重新计算工作簿"布尔值,参见 MS-XLS §2.4.37。HotXLS 之前没有 $005F 的 dispatcher case,StoreCalculationSettings 输出硬编码
1—— 所以用户禁用的"保存时重算"在 HotXLS 每次另存后被悄悄重新启用。这对手动计算工作簿尤其重要,因为用户已经手动冻结了磁盘上的单元格值。 - 新增 TXLSWorkbook.RecalcOnSave 布尔属性。默认
True(与 Excel UI 默认值和旧硬编码值一致),所以不动该属性的工作簿对 v2.88.18 保持字节级一致输出。setter 接受任何 Boolean;读取器把任意非零源字节归一化为True。
版本 2.88.18
- 迭代计算设置(启用 + 最大迭代次数 + 最大变化值)现在能往返保留。BIFF8 的 CalcIter($0011)、CalcCount($000C)和 CalcDelta($0010)三个记录共同携带 Excel "启用迭代计算"三件套选项(文件 → 选项 → 公式),参见 MS-XLS §2.4.33 / §2.4.31 / §2.4.32。三者之前都没有 dispatcher case,StoreCalculationSettings 用硬编码值输出(关 / 100 / 0.001)。用户配置的 1000 次迭代 + 0.0001 收敛阈值在 HotXLS 每次另存后悄悄重置为"迭代关、100、0.001"—— 破坏循环引用公式和对收敛敏感的财务模型。
- 新增三个 TXLSWorkbook 属性。
EnableIteration: Boolean对应复选框;MaxIterations: LongWord是迭代上限(setter 将其钳到 spec 合法的 1..32767 范围);MaxIterationChange: Double是收敛 delta(负值会回到 spec 默认 0.001)。默认值与写入器之前硬编码的值一致,所以不触碰新属性的工作簿产生与 v2.88.17 字节相同的输出。
版本 2.88.17
- 工作簿计算模式(手动 / 自动 / 自动除数据表)现在能往返保留。BIFF8 CalcMode 记录($000D)携带工作簿级"公式 → 计算选项"选择,参见 MS-XLS §2.4.36。HotXLS 之前根本没有 $000D 的 dispatcher case,源文件的值在加载时被丢弃,写入器总是输出硬编码的
$0001(自动)。用户选择的"手动"模式会在每次 HotXLS 另存时悄悄回到"自动"—— 这对大型工作簿尤其糟糕,因为"手动"是为性能特意设置的。新的 ParseCalcMode 处理器把源值存到工作簿上,StoreCalculationSettings 现在写出存储的值而非常量。 - 新增 TXLSWorkbook.CalculationMode 属性。读写
LongWord属性,接受xlCalcManual(0)、xlCalcAutomatic(1,默认)或xlCalcAutomaticExceptTables(0xFFFF)—— 从lxTNC.inc导出的三个新常量。setter 将未知值钳制到 spec 默认值,使损坏的源文件无法让工作簿进入未定义状态。不动该属性的现有代码保留旧的"自动"默认值,默认工作簿的旧输出字节级一致。
版本 2.88.16
- 页面设置中 "单元格错误为" 的选择现在能保留过保存周期。BIFF8 Setup 记录($00A1)把"页面设置 → 工作表 → 单元格错误为: 显示 / <空白> / <短划线> / <N/A>"下拉框打包到其 grbit word 的 bits 10-11 即
iErrors,参见 MS-XLS §2.4.257。HotXLS 之前在读端丢弃这两个 bit,写端总是输出 0,所以用户配置成把#DIV/0!打印为#N/A的工作簿在 HotXLS 每次另存后悄悄回到"显示"。读取器现在解码iErrors到新的TXLSPageSetup.PrintCellErrors属性,写入器再从该字段重新合成。 - 新增 TXLSPageSetup.PrintCellErrors 属性。读写
LongWord属性,接受xlPrintErrorsDisplayed(0,默认)、xlPrintErrorsBlank(1)、xlPrintErrorsDash(2)或xlPrintErrorsNA(3)—— 从lxTNC.inc导出的四个新常量。不动该属性的现有 PageSetup 调用方保留默认值("显示"),旧打印行为不变。
版本 2.88.15
- 批注的对齐与方向现在能往返保留。BIFF8 TXO base 记录($01B6)的
grbitword 携带五个 typed 标志(hAlignment、vAlignment、fLockText、fJustLast、fSecretEdit),另外有独立的rotword 表示文本方向,参见 MS-XLS §2.4.329。读取器之前把这些全部丢弃,写入器把grbit钉死在硬编码的0x0012(左+顶),rotation 也固定为 0 —— 所以每次保存都会把居中或旋转的批注重置为左+顶+水平,无论源文件如何。读取器现在解码这些 typed 字段,写入器从字段重新合成grbit,布局可以经受 save/reload 往返。 - TMSOShapeTextBox 新增六个 properties 用于显式批注样式。
HAlignment、VAlignment、Rotation、LockText、JustLastLine、SecretEdit都暴露为每个批注 shape 的 read-write properties;AddComment默认初始化为左+顶+水平+不锁定,调用方不动这些属性时外观与之前一致。 - TXO 写入器现在按 spec 字段边界布局 reserved4 / reserved5。旧代码把 base 记录 offset 2-9 用两个 long 写出(rot+reserved4 然后 reserved5);写入器现在拆成
Wordrot、Wordreserved4、Longreserved5 —— 字节内容没变(Note shape 仍是全 0),但源代码结构现在匹配 MS-XLS §2.4.329 的字段偏移,今后修 TXO 不容易再认错 offset。
版本 2.88.14
- 修正 TXO cchText 偏移 —— v2.88.13 的批注长度修复现在才真正生效。上一个版本为 TXO base 记录加了 sanity 检查从 offset 8 读
cchText,但 MS-XLS §2.4.329 明确cchText在 offset 10(grbit、rot 与 6 字节 reserved / controlInfo 之后)。offset 8 落在 reserved5 长字段内,对 Note 形状的对象始终为 0,所以每条批注都静默掉进 defensive fallback —— 等于退回 v2.88.13 之前的行为。本次把偏移修正为 10,长批注真正能跨 Continue 记录拼接,短批注末尾不再带 padding。除 v2.88.13 本该带来的行为外没有别的变化。
版本 2.88.13
- 长单元格批注现在能完整读回。BIFF8 TXO 记录($01B6)把文本 body 切到 base 记录加一个或多个 Continue 记录,字符数公布在 base 记录 offset 8 处的
cchText。之前的批注读取器完全跳过 base 记录,把 DataList[1] 当作全部文本,到此为止 —— 超过约 4100 个宽字符的批注就被静默截断,而较短批注若其 Continue 记录尾随了填充字节也会把这些 junk 当文本读入。读取器现在按cchText作权威字符数,按 MS-XLS §2.4.329 逐段消费 Continue(rgb 在字符边界拆分所以无需 partial-character 簿记),一旦预算用尽就停下,确保紧随文本之后的 formatting-runs 块不会渗进字符串。base 记录损坏或缺失的批注仍走旧的"消费所有剩余字节"回退路径。
版本 2.88.12
- 来自字符串型公式的、长度超过约 4100 字符的缓存字符串现在能够跨 Continue 记录完整保留。v2.88.11 把 BIFF8 String 记录($0207)的读侧接通,但只消费第一条记录的 body,导致 UCS-2 字节超出 8224 字节 BIFF 限制并溢出到一个或多个 Continue 记录($003C)的缓存字符串被静默截断。处理器现在遍历整个 dispatch 层的 DataList:从 base 记录读 cch 和 fHighByte,复制能装下的 body,然后按 MS-XLS §2.5.293 字符边界保证把后续每个 Continue 段作为裸字节拼接 —— XLUnicodeString 不会在字符串中途重发 fHighByte。每段都受剩余字符预算约束,确保异常超长的 Continue 段不会让结果超过 cch。单记录字符串(常见情况)走和以前完全相同的快路径。
版本 2.88.11
- 返回字符串的公式现在能在往返保存中保留 Excel 计算的缓存文本。上一个版本覆盖了 BIFF8 FormulaValue 缓存(MS-XLS §2.5.133)的数值、布尔、错误和空四个 variant,但字符串 variant 留作 to-do,因为它的缓存值放在紧跟 Formula 之后的独立 String 记录($0207)。ParseFormula 现在看到字符串 variant Formula 时记下单元格坐标,新的 ParseString 处理器按 MS-XLS §2.4.268 解码紧跟的 $0207 记录,把 WideString 路由到
FCachedFormulaValue。当 HotXLS evaluator 无法复现 Excel 计算的字符串时,GetCellValue现在能回退到 Excel 计算的文本。ParseFormula 顶部加了防御性重置,丢弃任何过期的 pending anchor,防止源文件缺失 String 记录时把后续的错误关联。超过 8224 字节并溢出到 Continue 块的记录仍以 known limitation 回退到 evaluator 输出。
版本 2.88.10
- BIFF8 Formula 记录现在能够保留 Excel 计算的缓存值。ParseFormula 之前完全跳过 offset 6 处的 8 字节 FormulaValue 负载,所以加载 .xls 时每个公式的缓存结果(数值、布尔、错误、空)都被丢弃,HotXLS 必须用自己的公式引擎重算每一个单元格。当该引擎无法复现 Excel 的结果(不支持的 XLM 函数、坏掉的外部链接、引擎尚未实现的公式)时,单元格会静默变空或显示 0。读侧现在按 MS-XLS §2.5.133 解码 number / boolean / error / empty 四种 variant,存到新增的
TXLSCellRef.FCachedFormulaValue字段;GetCellValue只在 evaluator 失败时回退到该缓存,新建的公式仍按以往走 evaluator 路径。string variant 仍依赖 evaluator,因为紧随其后的 String record ($0207) 解析器尚未接入。
版本 2.88.9
- BIFF8 Formula 记录在值无法解析时现在设置 fAlwaysCalc 而非 reserved1。当 HotXLS 的 evaluator 在保存时无法计算公式,写侧曾用
grbit = 0x0002(bit 1,MS-XLS §2.4.127 的 reserved1 字段要求读侧忽略)。Excel 按规忽略它,把占位 cached value 0 当作权威值,静默显示 0 而非重算。写侧现在设置grbit = 0x0001(fAlwaysCalc,bit 0),Excel 在下次重算时重新运行公式,单元格显示正确结果。
版本 2.88.8
- PageSetup.PrintTitleColumns / PrintTitleRows 在收到非法输入时现在会抛异常。先前给这两个属性设置畸形范围字符串(
ColDiapasonToValues/RowDiapasonToValues无法解析的任何输入)会静默丢弃赋值 —— 工作簿保留原有 Print_Titles 范围或保持未设置,调用方无从得知出错。Setter 现在用Exception.Create抛带详细信息的异常并指出非法值,与TXLSRange非法索引路径使用的 raise 风格保持一致。
版本 2.88.7
- Row miyRw 字段现在保持在 MS-XLS spec 范围内。BIFF5 时代 Excel 通过把 bit 15 OR 进 miyRw 表达"使用默认行高",HotXLS 在 BIFF8 写出时延续了这一习惯,即便 MS-XLS §2.4.221 把 miyRw 上限定在 8192 twips。现代 Excel 在同样场景下写出普通的 255(12.75pt 默认),并用 fUnsynced grbit bit 表达手动 override。bit 15 hack 让 HotXLS 输出与权威 .xls 文件偏离("default"被编码为 32 959 = 0x80FF,技术上超出 spec)。写侧现在去掉 OR,直接写 255;读侧仍剥离 bit 15 以兼容 v2.88.6 及更早版本的文件,以及少数复制 BIFF5 习惯的第三方生成器。
- BIFF8 spec audit round 2 加入勘误说明。重新核对 [MS-XLS] 字段边界后澄清原报告(
dev-notes/XLS-BIFF8-Spec-Audit-Round2.md)中两项 P2 实际并非 bug:BOF history flag $000080C9 中 bit 15 设置属于 verXLHigh 字段(bits 14-17,值 2 = "Excel 2002"),而非 reserved1 尾部(bits 19-31);ParseFormula 用首 PtgExp token 检测 shared / array formula 与 spec 描述一致,并通过后续 ShrFmla / Array record 正确消歧。两项现在都标注为撤回。
版本 2.88.6
- 宏表和 VBA 模块现在保留它们的 BoundSheet8 序号位置。读侧先前丢弃
dt字段为 1(宏表)或 6(VBA 模块)的 BoundSheet8 记录,HotXLS 的 Sheets 集合因此缺这些条目。任何 ExternSheet 中 XTI 按文件顺序引用"宏表之后"位置的 sheet,经 HotXLS SaveAs 后都解析到错误的 worksheet。读侧现在为每个 BoundSheet8 记录都添加一个 placeholder sheet,把原始dt字节存到新的Sheet.SheetTypeRaw属性;写侧回写原始字节。宏 substream BOF 记录($0040)在解析时也按 worksheet substream 处理,宏表内的单元格因此被保留而非静默并入上一个 sheet。
版本 2.88.5
- BIFF8 Row 记录现在往返保留 fCollapsed、fExAsc、fExDes 和 fPhonetic。先前读侧丢弃 fCollapsed(grbit bit 4),写侧仅靠相邻行的 outline 等级跳变推断,对源文件显式 collapse 或标记为边界的行会判错。高三位 fExAsc (bit 28)、fExDes (bit 29)、fPhonetic (bit 30) 也从未读取,写出时因为 4-byte grbit 被截断到单个 16-bit ixfe 槽而恒为 0。读侧现在按 MS-XLS §2.4.221 消费这四个 bit 并把 fCollapsed 标记为 explicit,写侧的推断不再覆盖 Excel 设置的值。写侧把 ExAsc / ExDes / Phonetic 打包进 ixfe Word 的 bit 12-14,并将 ixfe 屏蔽到 spec 允许的 12-bit 范围避免 XF 索引与新标志相撞。往返副作用:ExAsc / ExDes 驱动的厚顶 / 中底边框提示在 HotXLS SaveAs 后仍保留,日文工作表上的拼音注音可见性不再每次保存时重置。
版本 2.88.4
- BIFF8 Window2 fPaged 位现在仅标记活动 sheet。先前版本把
fPaged(MS-XLS §2.4.346 bit 10)写在所有可见 sheet 上,与 Excel 自身输出不一致(spec 规定该 bit 含义是"该 sheet 当前显示在工作簿窗口中",因此只有活动 sheet 的 substream 应携带)。Excel 读取器会回退到Window1.itabCur找到真正的活动 sheet 所以容忍了误用,但 Apache POI 严格模式以及其他把fPaged当作主要信号的工具现在能拿到正确标记的 sheet。
版本 2.88.3
- BIFF8 Window2 缩放比例和网格线颜色现在往返保留。先前版本读侧丢弃 WINDOW2 记录 offset 6 之后所有字段,写侧硬编码零,Excel 中设置的工作表缩放(75%、125% 等)和自定义网格线颜色在 HotXLS SaveAs 后全部回到默认。读侧现在按 MS-XLS §2.4.326 解析
icvHdr、wScaleSLV和wScaleNormal:当前视图缩放进入Sheet.Zoom,对侧视图的缓存缩放进入新增的缓存槽,这样在 Excel 中切换 Normal 与 Page Break Preview 时能恢复之前的缩放。写侧根据Sheet.View把Sheet.Zoom写到对应槽位,对侧写缓存值,同时回写保留的网格线颜色索引。
版本 2.88.2
- 修正 BIFF8 HFPicture 记录的 opcode。保存的 .xls 文件现在按 MS-XLS §2.4.138 用正确的
rt = 0x0866写出页眉 / 页脚背景图记录。先前版本使用0x086C(CellWatch 的 opcode),Excel 把嵌入的 OfficeArt BLIP 按 watched-cell 引用解析失败、静默丢图(偶尔在图片字节恰好破坏 CellWatch 期望的 16 字节结构时拒绝打开文件)。经 HotXLS 往返保存的带页眉 / 页脚图片的工作簿现在能保留图片。
版本 2.88.1
- 修正 BIFF8 Theme 记录的 opcode。保存的 .xls 文件现在按 MS-XLS §2.4.326 用正确的
frtHeader.rt = 0x0896写出 Theme 记录。先前版本使用0x0892(StyleExt 的 opcode),Excel 把嵌入的 OOXML 主题数据当作 cell-style 扩展解析,静默回退到内建 Office 主题;带自定义主题色的工作簿经 HotXLS 往返保存时会丢失自定义色板。
版本 2.88.0
- [MS-XLSX] 交叉审计第四轮 — theme part + sheet 名 setter。清理 round 1-3(v2.51.0 / v2.52.0 / v2.54.1)之后遗留的 2 处问题。两项都不破坏既有调用方;一项扩展 setter 行为,一项新增"始终发射"的 OOXML part。
- 保存的 .xlsx 包现在包含
xl/theme/theme1.xml。styles.xml 一直会为通过 theme-index 路径设置的字体 / 填充 / 边框 / 标签颜色(以及解析输入 .xlsx 透传过来的 theme 色)发射<color theme="N"/>引用,但 theme part 从未写出,引用都悬挂。Excel 通过回退到内建 “Office” 主题静默容忍,但 Office File Validation 把每条引用都标 “theme part missing”,Apache POI 严格模式在第一次查找时直接拒收。SaveAs现在发射规范 Office (2007+) 主题:12 槽 color scheme(系统windowText/window、4 个 Excel 默认色、6 个 accent、2 个 hyperlink 色)、Calibri Light / Calibri font scheme、最小合法 format scheme(每个 fill / line / effect / background-fill 列表 3 个条目,符合CT_StyleMatrix)。[Content_Types].xml加配套Override;xl/_rels/workbook.xml.rels加theme/theme1.xml关系,rId 落在 rid 范围尾端,sheets / sst / styles / vba / externalLinks 的XlsxFirstExternalLinkRid算式不变。 - 直接
Sheet.Name := '...'赋值现在也走 sanitize + dedup。Round 3(v2.54.1)在TXLSXSheets.Add(AName)入口加了 Excel 命名规则校验,但TXLSXWorksheet.Nameproperty 的 setter 是裸write FName,那一轮没覆盖到的最常见 mutation 路径 —lxXlsxExport.pas:122 Target.Name := Source.Name在 XLS → XLSX round-trip 里 — 让 BIFF8 源中任意命名(含禁字符: \ / ? * [ ]、超长 > 31、首尾单引号、保留名History、与现有 sheet 的大小写不敏感重名)原样落到 .xlsx。Property setter 现在转发到新SetName方法,复用XlsxSanitizeSheetName+' (N)'后缀 dedup(大小写不敏感、排除自身),针对父 workbook 的 sheet 集合校验。Worksheet 处于游离状态(FWorkbook还没设)时跳过 dedup 仅 sanitize — 后续TXLSXSheets.Add接入时会再保证唯一性。Idempotent on 合法名,所以 reader 侧FSheets.Add(names[i])仍是纯 round-trip。
版本 2.87.4
- XLS 共享公式现在写出有效的
ShrFmla记录体。 BIFF8 共享公式输出会在共享解析公式前写入必需的cUse字节,启用UseSharedFormulas保存时不再让公式 token 流整体错位 1 字节。 - XLS 表格样式和筛选元数据现在符合最新 MS-XLS 布局。
AddTable现在按List12TableStyleClientInfo写出LIST12,在Feature11中设置表级和字段级 AutoFilter 标志,并写出 Excel 期望的空Feat11FdaAutoFilter列块。 - BIFF8 CF12 数据条 / 色阶 / 图标集规则现在不再写入规范禁止的 DXF payload。 HotXLS 遵循 MS-XLS 对这些 CF12 类型的空 DXF 要求,同时继续通过 CF12 类型专用尾部保存规则本身的设置。
版本 2.87.3
- XLS 工作表表元数据现在遵循 MS-XLS
Feature11表布局。 对于 .xls 文件的AddTable输出,现在会写入FeatHdr11表头,以及Feature11TableFeatureType/Feat11FieldDataItem数据,移除了旧的$0867 FeatHdr表标记,并将表和列名称存储为XLUnicodeString值。 - XLS 表读取现在理解规范正确的字段布局。 HotXLS 解析
TableFeatureType表名称、范围、总计行状态和字段标题,同时保留了对旧版 HotXLS 生成的表记录的兼容性。
版本 2.87.2
- XLS BIFF8 continuation 记录现在会写出正确的基础记录长度。写入器拆分超长 XLS 记录时,会把首个记录长度改为 8224 字节,不再把原始超长长度留在 BIFF header 中。
- 大型 XLS 工作表表格现在使用符合规范的
ContinueFrt11分块。宽AddTable输出产生大型Feature11payload 时,现在会写出$0875 ContinueFrt11continuation 记录,并且重新打开后保留表格元数据,匹配 [MS-XLS] 的Feature11/ContinueFrt11布局。
版本 2.87.1
- XLSX 工作表网格上限现在包含 Excel 的最后一行和最后一列。
TXLSXRange、RCRange、EntireRow和EntireColumn现在允许第 1048576 行和第 16384 列(XFD),与 [MS-XLSX] 对 row-number / column-number 的边界一致。此前内部 clamp 使用了从零开始的最大值,导致XFD1048576以及触及最后行 / 最后列的范围被静默夹到前一行或前一列。 - XLSX 加密文档和测试现在与已实现的写入路径一致。帮助页和回归测试现在明确:非空密码调用
SaveAsEncrypted会写出 ECMA-376 Standard Encryption 输出;OpenEncrypted对加密包仍会抛异常,对普通 .xlsx 仍会回退到普通打开流程。
版本 2.87.0
- XLSX 密码保护保存现在可用了(wave J 第二阶段,backlog #29)。
TXLSXWorkbook.SaveAsEncrypted(FileName, Password)现在可以真正写出符合 ECMA-376 Standard Encryption 规范的密码保护 .xlsx 文件(Office 2007+ 格式)。完整 [MS-OFFCRYPTO] §2.3.4 pipeline 已经就位:第一阶段的 SHA-1 50000 轮密码派生 + AES-128 verifier blocks + AES-CBC 包体加密 + 二进制EncryptionInfoserializer,加上第二阶段新增的 4 个\005DataSpaces元数据流(Version / DataSpaceMap / DataSpaceInfo / TransformInfo)和 OLE Compound File Binary writer,把所有内容写入 Excel 可识别的 CFB 容器。流程:caller 调用SaveAsEncrypted并传入非空密码 → HotXLS 在内存里序列化出明文 .xlsx zip → 用随机 16 字节 salt 和 verifier 通过 AES-128 CBC 加密 → 通过StgCreateDocfile写 CFB 输出。Excel 2007+ 打开:输入密码 → 内容打开;错误密码:拒绝。OpenEncrypted(解密侧)仍是另一 backlog 项,遇到加密文件继续抛EXlsxEncryptionNotImplemented。
版本 2.86.1
- XLSX Standard Encryption——加密原语基础(wave J 第一阶段,backlog #29)。新增两个内部单元,提供 ECMA-376 Standard Encryption 写入路径中所需的加密 / 派生算法层。
lxAES.pas包装 Brian Gladman 的 AES 实现(链接thirdparty/Win32/aes*.obj+thirdparty/Win64/aes*.obj),对外暴露 AES-128 ECB 单块加密和 AES-128 CBC 加密入口。lxXlsxStdEncrypt.pas实现纯 Pascal 的 SHA-1(FIPS-180-4)、[MS-OFFCRYPTO] §2.3.4.10 的 50000 轮密码派生、§2.3.4.7 的 verifier 块(EncryptedVerifier+EncryptedVerifierHash)、包体的 AES-CBC 加密(8 字节 LE 长度前缀 + 补零到 16 字节边界 + 全零 IV),以及 §2.3.4.6 的二进制EncryptionInfo序列化器。TXLSXWorkbook.SaveAsEncrypted仍然抛EXlsxEncryptionNotImplemented——wave J 第二阶段会补 OLE Compound File Binary writer(\005DataSpaces容器流)并把 pipeline 接到SaveAsEncrypted。在此之前,新单元属于库内部脚手架,调用方不应依赖。
版本 2.86.0
- QueryTable 与外部数据连接 round-trip(wave I,backlog #28)。Excel 创建的 QueryTable 和外部数据连接(数据 → 自 Web / SQL / OLEDB 获取外部数据)现在能完整通过 HotXLS 的保存/打开循环。此前 BIFF8 读取器会跳过
QsiSXTag($0802)、QsiSXTagExt($0810) 与DConn($0876) 三个记录,导致描述上游查询的元数据在保存时丢失、表格退化为普通单元格数据。读取器现在按原样捕获这些记录,写入器在 worksheet substream(按 [MS-XLS] §2.1.7.20.5 紧邻 PIVOTVIEW 块)和 workbook globals(按 §2.1.7.20.3 在 EOF 前的后期 globals 块附近)原样重放它们。HotXLS 仍未提供 QSI / DConn 的类型化编程模型 — 通过 caller 代码创建新 QueryTable 延后到后续 wave — 但既有 workbook 不再丢刷新元数据。仅影响 BIFF8 (.xls);BIFF5 不变。
版本 2.85.1
- 恢复 Win32 / Win64 库的可编译性。wave H5.3 多数据字段 SXLI 发射器中的两个辅助变量被声明为各自独立的
array of array of Word匿名类型,Delphi 编译器把它们视作两个不同的未命名类型,对直接赋值返回E2008 Incompatible types。自 v2.84.1 起 HotXLS 库在 RAD Studio 12.0 到 37.0 上一直编译失败。现在这两个变量声明在同一行,共用一个匿名类型,赋值成立、Win32 和 Win64 的 .dcu / .bpl 输出恢复正常。运行时行为无变化 — 发射出的 SXLI 字节序列与 v2.85.0 完全一致。
版本 2.85.0
- Pivot subtotal 类型化 API (wave H5.4)。typed 模型
TXLSPivotField现在新增Subtotals: TXLSPivotSubtotals集合属性,与原有 rawSubtotalMask: Word并存。Caller 可以直接Field.Subtotals := [xlpsSum, xlpsAverage];代替手动 bit-pack SXVDgrbitSub字段。12 种 subtotal 类型 (xlpsDefault, xlpsSum, xlpsCount / CountA, xlpsAverage, xlpsMax, xlpsMin, xlpsProduct, xlpsCountNums, xlpsStdDev, xlpsStdDevP, xlpsVar, xlpsVarP) 各占 grbitSub 一位 (per [MS-XLS] §2.4.279)。RawSubtotalMask仍是 round-trip source of truth — 12-15 位保留 bit 在 read / write 时保留不变。关闭 wave H4.3 known limit “row field subtotal SXVD.grbitSub 配置 API 不可用”,完成 wave H5 pivot follow-up 全部子项。
版本 2.84.1
- 多 data field SXLI 展开 (wave H5.3)。当 pivot 有多个 data field 且 data-field 轴与当前 SXLI 轴匹配 (
DataFieldAxisIsRow = True且 row 轴,或DataFieldAxisIsRow = False且 column 轴) 时,writer 现在把每个 cartesian-product 组合连续 emitDataFieldCount次,iData = 0 .. DataFieldCount - 1,grand-total 同样按DataFieldCount次展开让每个 data field 有独立总计行。另一轴不变。Excel 与其它 reader 现在按 caller 预期布局渲染多 data field pivot,不再按 “每组合一条iData = 0line” 近似。单 data field pivot 与 v2.84.0 输出 bit-identical。Delta compression (H5.1) 把重复 combination 压缩到每条 replica ~8 字节,展开字节代价极小。关闭 wave H4.3 known limit “multi-data-field SXLI 不正确”。
版本 2.84.0
- Pivot page 轴预选 API (wave H5.2)。typed 模型
TXLSPivotField现在带PageItemIndex属性,程序化构建的 pivot 可以预选 page 轴 filter 上特定的 cache item。DefaultxlPageItemAll(= $7FFD) 保持 “(All)” filter,从未设置过PageItemIndex的 caller 与 v2.83.2 输出 bit-identical。SXPI ($00B6) writer 读Field.PageItemIndex代替原来硬编 $7FFD,typed reader 也从 SXPI 解读PageItemIndex,Open 时可以 introspect 保存的 page filter 状态。关闭 wave H4.3 known-limit “page filter caller-pre-selection unavailable from API”。
版本 2.83.2
- Pivot SXLI 记录 delta 压缩 (wave H5.1)。Pivot writer 现在按 spec 的 cSic 字段对 SXLI line items 做 delta 压缩 — 每条 line 与同一 SXLI 记录前一条 line 共享前缀的 cache-item 索引折叠成 shared-prefix count,只 emit 尾部变化的索引。典型 row-axis SXLI (几个 row 字段 × 几十个 items) 字节数缩小 30–60%,语义不变。输出仍按 8224 字节 BIFF 记录上限 chunk 分片。每条 SXLI 记录的第一条 line 永远 cSic = 0 (record-local,不跨 record 反向引用),grand-total line 不做 delta 压缩。
版本 2.83.1
- RGB 设置的单元格填充/字体/边框颜色现在能通过 .xls save/open 正确 round-trip。BIFF8 XFExt ($087D) writer 之前用内存中 XF 数组位置作为每条记录的 ixfe 字段,但对应的 cell 记录在磁盘上的 ixfe 用的是 prune 后 SaveIndex 排序。任何 XF 在 save 时被裁掉 (常见于一个 cell 从临时 XF 迁移到最终 XF) 都会让 XFExt 的 ixfe 偏移裁掉的槽数,reload 后每个 cell 的 rich color 漂移到邻近 cell。Writer 现在为每个有 rich-slot 的 XF 解析 SaveIndex 并发出对应的 on-disk ixfe,HotXLS 写入的 RGB cell 颜色 — 内部填充、字体颜色、边框颜色 — 都能干净通过 save / reload。完全被裁掉的 XF 对应的 XFExt 记录现在跳过,避免发出指向无效 XF 的 ixfe。
版本 2.83.0
- Pivot line items + page item state (wave H4.3)。程序化构造的 pivot tables 现在 emit SXLI ([MS-XLS] §2.4.275, $00B5) 覆盖行 + 列轴,加上 SXPI ($00B6) 覆盖 page 轴。让 pivot view layout 保真:非 Excel reader 看到 writer 确定的显示顺序;大 pivot Open 更快 (Excel 不必从头算 line layout);page filters 默认 "(All)" 选择持久化。
- 行 + 列 SXLI enumeration。Writer 枚举轴字段 cache items 的笛卡尔积 (内层字段变化最快,对齐 Excel 嵌套行布局),每组合 emit 一条 line,末尾追加 grand-total 线 + 设 SXLI nTypes fGrandTotal 位。每行 cSic = 0 (无 delta-compression — 简单,代价多几字节 / line)。Line 数超 8224 BIFF 限时分多条 SXLI records;16384 行安全上限防止病态输入下数组爆炸。
- SXPI page 轴状态。仅当至少有一个字段 Axis = xlpfaPageField 时 emit。每条 entry 10 字节 (isxvd + iCache + ipos + objId),iCache = $7FFD 表示 "(All)" — 预选特定 page item 的 API surface 留 wave H5。无 page field 的 pivot 不 emit SXPI (worksheet ABNF 中 SXPI 是 optional)。
- 关闭 wave H3 known limit "SXLI / SXPI not emitted"。配合 H4.1 (DataField number formats) 和 H4.2 (SXDBB per-record stream),wave H4 关闭了 H3 pivot-table writer 三个 known limits 全部。通过
IXLSWorksheet.AddPivotTable建的 pivot tables 现在出货完整 self-contained cache + 完整 layout 元数据。
版本 2.82.0
- Pivot cache 自包含 per-record 流 (wave H4.2)。程序化构造的 pivot caches 现在 emit SXDBB records ([MS-XLS] §2.4.272, cache context $00C5),按 spec 的 bit-packed 编码携带每行 / 每字段值索引。没有 SXDBB 时,Excel Open 必须从 source range 刷新 cache —— 当 source 数据原封不动还在时能用,但 source 被改名 / 删除 / 内容漂移后就坏。现在 cache 是自包含的。
- 按 spec bit-packed 编码。每个字段用
ceil(log2(itemCount + 1))比特 / 条记录 (含 sentinel 空间)。记录字节对齐 — 每条新记录从新字节边界开始。Writer 把流分块为多条 SXDBB records 保持每条 ≤ 8224 字节,所以含数万行 source 数据的 cache 也能正确序列化。 - Round-trip 路径不变。从磁盘读来的 pivot caches (FromRawBlobs = True) 继续按 wave H1 的 raw-byte 路径 round-trip — 新 SXDBB writer 只对
IXLSWorksheet.AddPivotTable创建的 typed caches 触发。混合 workbook (一个 round-tripped cache + 一个新建 cache) 两条路径都干净 emit。
版本 2.81.0
- Pivot data field 数字格式 (wave H4.1)。Pivot 数据字段现在可以携带 Excel 数字格式字符串,Open 时按货币 / 百分比 / 日期等正确字形渲染,不再显示原始 General 格式。新
IXLSWorksheet.PivotSetDataFieldFormat(DataField, FormatStr): Word把格式字符串注册到 workbook NumFormats 表 (auto-add 或复用),返回的 ifmt 索引写到TXLSPivotDataField.NumberFormat。typed writer 已经 emit SXDI.ifmt,链路闭合。 - TXLSWorkbook 上的公开 NumFormats helper。
Workbook.RegisterNumFormat(FormatStr): Word在 workbook 级暴露同一 auto-add 行为,给非 pivot 场景的 caller 拿 ifmt 索引用。空 FormatStr 短路到索引 0 ('General')。 - Caller 用法。
df := pivot.AddDataFieldByName('Revenue', xlpaSum); Sheet.PivotSetDataFieldFormat(df, '$#,##0.00'); df := pivot.AddDataFieldByName('GrowthPct', xlpaAverage); Sheet.PivotSetDataFieldFormat(df, '0.00%');
版本 2.80.1
- Icon Set 条件格式现在能正确通过 HotXLS save/open 往返。v2.49.0 audit 把 CF12 writer 对 Icon Set 规则改成按 [MS-XLS] §2.4.43 emit
ct=$06(规范正确值;$05是 Filter 规则保留位),但对应的 reader 路径仍只识别旧的$05。结果 HotXLS v2.49.0..v2.80.0 写出的 .xls 文件重新打开后 Icon Set 规则会丢失 — kind 降级成普通 cell-is 规则,icon-set 类型 / Reverse / ShowOnly 标志重置为默认。Reader 现在同时接受$05(v2.49.0 之前的旧 HotXLS) 和$06(规范 / v2.49.0+),让任一代的 workbook 都能干净重开。
版本 2.80.0
- 程序化 pivot table 创建 API (wave H3)。新
IXLSWorksheet.AddPivotTable(SourceRangeA1, DestRow, DestCol, Name): TXLSPivotTable方法扫描源 range,按列推断字段类型,自动构建TXLSPivotCache(或复用同 range 已存在的 cache),在目标 sheet 上建立 typed pivot table,每个 cache 字段对应一个 TXLSPivotField (轴初始为 None)。 - Caller 通过 convenience 方法配置轴 / 数据。
pivot.AddRowField('Region')、pivot.AddColumnField('Quarter')、pivot.AddPageField('Year')、pivot.AddDataFieldByName('Revenue', xlpaSum)。还暴露SetFieldAxis+AddDataField给细粒度场景。Axis 枚举:xlpfaRowField / xlpfaColumnField / xlpfaPageField / xlpfaDataField / xlpfaNone。11 种聚合:Sum、Count、Average、Max、Min、Product、CountNums、StdDev、StdDevP、Var、VarP。 - Typed writer emit SX* records + cache substream。
pivot.FromRawBlobs = False(程序化创建的默认状态) 时,writer 把 typed model 序列化为 SXView ($00B0) + 每字段 SXVD ($00B1) + 每 item SXVI ($00B2) + 行/列索引 SXIVD ($00B4) + 每数据字段 SXDI ($00C5) + SXEx ($00C6) 写入 worksheet footer。匹配的 pivot cache (cache.FromRawBlobs = False) 输出新 BOF (dt=$0006) + SXDB ($00C6) 头 + SXFDB ($00C8) + SXFDBType ($00FB) + 逐项 SXSTRING / SXNUM / SXBOOLEAN / SXERR / SXDATETIME / SXEMPTY + EOF substream,追加到 worksheet bodies 之后。 - Round-trip 安全仍保留。从磁盘读来的 pivot tables / caches 保持 wave H1 的
FromRawBlobs = True标记,继续走 raw-byte 路径 round-trip。只有程序化新建的 pivots 走 typed writer。混合 workbook (一个 round-tripped pivot + 一个 AddPivotTable 新建 pivot) 两条路径都干净 emit。 - Wave H3 limitation。非矩形 A1 (named ranges、外部 workbook refs) 的源 range 不在范围内。typed pivots 不 emit SXLI / SXPI (line items / page items) — Excel Open 时自动计算。formatting customisation (per-field NumberFormat 之外的 data field format) 字段已暴露但 writer 当作 0 (general)。多 pivot 共享 cache 已支持,但 caller 必须每次传同样 source range 字符串。
版本 2.70.0
- Pivot table typed read model (wave H2)。在 wave H1 raw-byte 保留之上,reader 现在还构建有类型的对象模型,让 caller 能 introspect pivot table 结构而无需自己解析字节流。新类型 —
TXLSPivotTable、TXLSPivotField、TXLSPivotItem、TXLSPivotDataField、TXLSPivotCache、TXLSPivotCacheField、TXLSPivotCacheItem、TXLSPivotCaches、TXLSPivotTables— 通过新增的IXLSWorksheet.PivotTables与TXLSWorkbook.PivotCaches属性暴露。 - 模型抓取的内容。每个 pivot table:位置 (FirstRow / Col / LastRow / Col / FirstDataRow / FirstDataCol)、Name、DataCaption、CacheId、有序
Fields列表 (每个字段含 Name、Axis ∈ {xlpfaRowField、xlpfaColumnField、xlpfaPageField、xlpfaDataField、xlpfaNone}、Items[]、SubtotalMask、CacheFieldIndex)。Data 轴还有并行的DataFields列表,每个携带 11 种TXLSPivotAggregation之一 (xlpaSum / Count / Average / Max / Min / Product / CountNums / StdDev / StdDevP / Var / VarP)。 - Cache 模型。每个
TXLSPivotCache持有 CacheId、SourceRange (Sheet + 0-based row/col 边界)、RecordCount,以及Fields列表。每个 cache field 携带类型 (xlpcftNumber / String / Boolean / Error / Empty / DateTime / Mixed)、Name、NumberFormat 索引、unique-value Items[]。Per-record 索引到每个字段 Items[] 通过Cache.RecordIndices[Record, Field]暴露,程序化构造时用得到;从磁盘 round-trip 的 cache 该索引留空,fidelity 依赖 raw-byte 路径。 - Round-trip 安全。从 raw bytes 读来的 pivot tables 标
FromRawBlobs = True— writer 继续按 wave H1 原样回放 raw blobs。typed model 仅作为 caller introspection 的 best-effort 投影。从 typed model 反向生成 wire bytes 的 writer 是 wave H3 (程序化 AddPivotTable API) 的范围。 - 新 lxPivot.pas unit。所有 pivot 类型放在独立 unit,与 lxChart / lxFormula / lxNames 同级。lxHandle re-export 公开类型,既有 import 不需要改。
版本 2.69.0
- Pivot table round-trip 保留 (wave H1)。HotXLS 现在能完整保留 Excel 创建的 pivot table — Open → Save 不再丢数据。此前 reader 静默丢弃所有未识别的 SX* records (SXView、SXVD、SXVI、SXIVD、SXLI、SXPI、SXDI、SXAddl 等),并跳过整个 Pivot Cache substream,所以含 pivot 的 Excel 文件经 HotXLS 重写后 Excel 再打开看到的是损坏的 pivot table。现在 reader 把这些都捕获为 opaque bytes,writer 原样写回,Save / Reload 后 pivot table 仍正常渲染。
- Worksheet PIVOTVIEW 块。SX* view records ($00B0–$00B2、$00B4–$00B6、$00C5–$00C8、$00D0–$00D2、$00D5、$00E3、$00F0、$00FB、$0100、$0864) 按流式顺序捕获,writer 在 per-sheet footer 中 emit (Tables 块之后、尾部 EOF 之前),对齐 [MS-XLS] §2.1.7.20.1 worksheet ABNF 给 PIVOTVIEW 的位置。超大的 SXAddl payload 走 HFPicture 同样的 Continue ($003C) 拆分管道。
- Pivot Cache substreams。BOF (dt=$0006) 后跟 SXDB / SXFDB / SXFDBType / SXSTRING / SXNUM / SXBOOLEAN / SXERR 一直到匹配 EOF 的整段记录被捕获为一个 cache bucket;同一 workbook 多个 caches 各自一桶。Save 时 writer 为每个 bucket 重建完整 BOF / records / EOF substream,追加到 Workbook OLE stream 在 per-sheet bodies 之后,符合 [MS-XLS] §2.1.7.20 的位置要求。
- 范围:只做 raw-byte 保留 (H1)。Wave H1 刻意不把 pivot 数据解析成有类型的模型 —— TXLSPivotTable / TXLSPivotField / TXLSPivotCache 以及程序化 AddPivotTable API 留给后续 wave H2 / H3。在此之前 HotXLS caller 无法读写 pivot table 结构,但 Excel 创建的 pivot tables 可以无损通过 HotXLS round-trip。
版本 2.68.0
- Chart backlog wave F 子功能 3:Series 误差线。
TXLSChartSeriesInfo新增ErrorBars: array of TXLSChartErrorBarsInfo字段。每个 entry 在父 Series block 内 emit 一条 SerErrBar ([MS-XLS] §2.4.105, $105B),位于 Trendlines 之后、Series End 之前,按 caller 顺序。柱状图加 Y 误差线常用两条 (Sertm=1 Y+ 和 Sertm=2 Y-);散点 / 气泡图加 X+/X- 对 (Sertm=3 / 4)。 - 五种数据源。
Ebsrc选择 1=百分比、2=固定值、3=标准差、4=标准误差、5=自定义。NumValue承载量级 (Ebsrc=1 时 10.0=10%,Ebsrc=2 时为原始标量,Ebsrc=3 时为标准差倍数)。自定义 (Ebsrc=5) 时Cnum是自定义数据点的数量;spec 要求其他 Ebsrc 时 MUST=0,builder 对非自定义强制 Cnum=0,忽略 caller 传入。 - T-cap 渲染开关。
FTeeTop控制 Excel 是否在 bar 末端渲染 T 形帽 (Excel 视觉默认 = 开)。caller 想要简约 "tick-only" 风格时关掉。 - 自定义 (Ebsrc=5) 限制。最小 builder emit SerErrBar record 时按 caller 设的 Cnum 写入,但**还未** emit 配套指向自定义数据数组的 BRAI cluster。所以自定义误差线目前用默认 magnitude 渲染,等下个 phase 补 BRAI follower。百分比 / 固定值 / 标准差 / 标准误差 (Ebsrc 1..4) 完整可用。
版本 2.67.0
- Chart backlog wave F 子功能 2:Series 趋势线。
TXLSChartSeriesInfo新增Trendlines: array of TXLSChartTrendlineInfo字段。每个 entry 在父 Series block 内 emit 一条 Trendline ([MS-XLS] §2.4.328, $2050),位于 SerToCrt 之后、Series End 之前,按 caller 顺序。同一 series 上可挂多条趋势线,Excel 都会渲染。 - 六种回归类型。
Regt选择 0=多项式、1=指数、2=对数、3=幂函数、4=移动平均、5=线性。多项式时NOrder指定阶数 (2..6);移动平均时指定周期 (2..N)。其他类型忽略NOrder,但 spec 要求 1..6,builder 把 0 默认为 1、把 >6 截到 6。 - 方程 / R² 显示 + 预测。
FDispEq/FDispRSqr切换图上方程与 R² 标签。NumForecast/NumBackcast指定前向 / 后向预测周期 (Double, ≥ 0)。NumIntercept设 y 轴截距;传 NaN ($7FF8000000000000) 表示 "自动"。 - 趋势线名作为内嵌 LPWideString。
Name字段写入 Trendline record 的 sName 槽位 ([MS-XLS] XLUnicodeString:cch:2 + grbit:1 + UTF-16 body)。空 Name 让 Excel 自动生成 legend 项如 "Linear (Series1)"。 - AddSeries 内部重构。内部
AddSerieshelper 现在接收单个TPreparedSeriesInfo,不再是 (Name, CatArea, ValArea) 三元组。后续 Series-attached record (下个 phase:error bars) 可通过一个参数传入,无需再次改签名。
版本 2.66.0
- Chart backlog wave F 子功能 1:3D chart 类型。程序化构造的 chart sheet 现在可以通过
AddChartSheet(Name, ChartType, ...)选择xlsChartType3DColumn、xlsChartType3DBar、xlsChartType3DLine、xlsChartType3DPie。3D 变体复用与 2D 相同的 BARCHART / LINECHART / PIECHART chart-type record,但外层 CHARTFORMAT 块额外 emit 一条 Chart3d ([MS-XLS] §2.4.46) 让 Excel 切换到 3D 渲染流程。 - 默认 3D 几何参数对齐 Excel "Insert > 3D Column"。20° 旋转、15° 仰角、perspective 关、cluster 开、autoscale 开、高度和深度都为宽度的 100%、间隔 150%。墙面与直角坐标对齐 Excel 默认。当前 hard-code,无 caller 可调旋钮;下个 phase 可以扩展为可覆盖。
- 条件恢复 Chart3DBarShape ($105F)。v2.55.0 删除了无条件 Chart3DBarShape emit,因为 [MS-XLS] §2.4.47 规定 "MUST be ignored if the current substream does not contain a Chart3d record",而 2D chart 没有 Chart3d。Wave F 仅对 3D Bar / 3D Column 恢复 (riser=矩形、taper=无),紧贴 Chart3d 在 CHARTFORMAT 内 emit,使 spec 关系在 wire 层一目了然。3D Line 与 3D Pie 仍跳过 (没有 riser/taper 概念)。
- 3D Pie 跳过双轴。axes-used 计数与轴 emit 路径现在把
xlsChartType3DPie与xlsChartTypePie同等对待 —— axes-used = 0,不 emit category / value 轴。无此 gate 时 Excel 渲染 3D 饼图会有杂散的轴线穿过图形。
版本 2.65.0
- 公式 array constant 在读写两端保留数据。公式 token 流里的
PtgArray($20 / $40 / $60 — V / R / A class)现在能把PtgExtraArray数据通过读端与写端完整 round-trip。SUM({1,2,3})、=MMULT(...)、{=COUNTIF(...)}等含数组字面量的公式在 HotXLS 输出的.xls中会保留实际数值,而不是写出空 rgcb 段。 - Array 数据直接挂在 syntax tree 上。
TXLSSyntaxItem新增ArrayCols/ArrayRows/ArrayValues属性(配套TXLSArraySerValrecord 描述 num / str / bool / err / empty 五种元素,遵循 [MS-XLS] §2.5.198.122 SerAr)。遍历 syntax tree 的工具可以直接看到 array constant 的内容,不再依赖独立的 external-data 容器。 - 支持 API 手工构造 array literal。通过 API 构造
TXLSSyntaxItem的代码可以在SA_ARRAY节点上调SetArrayDimensions+ArrayValues[i]写入数组,HotXLS 会自动在 rgcb 段输出对应的 PtgExtraArray。Wire 顺序遵守 [MS-XLS] §2.5.198.59 规则:PtgExtraArray 条目按其 PtgArray token 在 rgce 流里的位置排列。 - 对混合 rgcb 现有读路径不破坏。新代码只消费与已解析 PtgArray 对应的 PtgExtraArray 条目;其他 extra 数据(例如尚未支持的 PtgMemArea / PtgMemFunc 的 PtgExtraMem)留给下游处理。rgcb 损坏时回落到留空 ArrayValues,而非丢弃整棵已解析的 tree。
版本 2.64.0
- Chart backlog wave D phase 7:drawing theme color 在单个进程内 get / set round-trip。Phase 5 引入的
XlsApplyThemeColorToDrawing是 set-only helper,因为 BIFF8 OfficeArt 是 pre-Office-2007 binary 格式,磁盘上没有 theme color 槽位。Setter 仍把 RGB down-cast 写入 OfficeArt opt blob,但 workbook 现在额外维护一张 in-memory side-table,按(TMsoShapeContainer, OfficeArt property id)配对记住原始 theme idx + tint。新的XlsGetDrawingThemeColorreader 查这张 side-table,让同一进程能把刚写入的 theme 意图读回 —— 对那些想突出 theme-driven 颜色或在属性面板上展示的应用渲染代码有用。Save / Open 之后 side-table 重新为空,getter 返回 False,回落到ColorFormat.RGB。 - 新 caller API。
XlsGetDrawingThemeColor(ColorFormat, Workbook, out ThemeIdx, out Tint): Boolean与已有的XlsApplyThemeColorToDrawing配对。Setter 签名不变;它现在还把 entry 记录到TXLSWorkbook.FDrawingThemeColors(动态数组的 record,以 container 指针 + property id 为 key)。同一 slot 上后续XlsApplyThemeColorToDrawing覆盖原 entry,所以表里跟踪的是最新意图而非历史累计。 - 通过新内部 property 提供稳定身份。
TXLSColorFormat加 read-only_Container和_Pid访问器,helper 可以组装 side-table key 而无需 caller 去 fish 类的 private 字段。下划线前缀标记这与_StringTable/_XFList/_BiffTheme同级内部 API —— 库内部胶水代码用足够稳定,但不属于公开契约。 - 为什么仅"单进程 round-trip"。BIFF8 OfficeArt format 4 字节 ColorRef 只存 indexed / RGB / scheme / sysColor,没有像 XFExt $087D 那样的 future-extension record 给 theme idx + tint 落脚。磁盘 round-trip cap 是格式性约束,不是 HotXLS 缺失。Phase 7 side-table 在 in-process gap 上架了座桥,让 app-internal 代码在单个 workbook session 内可以假装该格式支持 theme color。
版本 2.63.0
- Chart backlog wave D phase 6:复合 border selector 通过 XFExt round-trip RGB / theme。最后一个 theme color known-limit 关闭:
Border[xlAround]、Border[xlInsideVertical]、Border[xlInsideHorizontal]、Border[xlInsideAll]现在把同一 RGB / theme color 注册到它们所针对的每个物理 edge slot,不再回落 indexed-only 路径。新TXLSXfRichSlotSet(set of TXLSXfRichSlotID)把 pending-rich stash 从单 slot 升级到 set,一次SetRangeXFBordersPropertycell-loop 即可注册最多 4 个 XFExt slot。 - 复合 selector 映射。新
BorderEdgeSlotSet(BorderIndex): TXLSXfRichSlotSethelper 集中 selector → slot 翻译:xlEdgeLeft / Right / Top / Bottom→ 单元素 set(phase 2 即支持)xlDiagonalDown / Up→[rsDiag](BIFF8 FullColorExt 只载一个对角色)xlAround→[rsTop, rsBottom, rsLeft, rsRight](外边框)xlInsideVertical→[rsLeft, rsRight](cell 之间的垂直分隔)xlInsideHorizontal→[rsTop, rsBottom](水平分隔)xlInsideAll→[rsTop, rsBottom, rsLeft, rsRight]
Border.SetColor与Border.SetThemeColor共用同一映射,所以 RGB 和 theme 路径在所有 selector 上行为一致。 - TXLSBorders.SetColor 收回到单次 dispatch。Phase 2 因为 pending-rich stash 一次只能带一个 slot,被迫把
Borders.Color := V拆成 4 次 per-edgeGetBorder(edge).Color := V。set 形式落地后,Borders.SetColor现在 stash 完整{rsTop, rsBottom, rsLeft, rsRight}set 然后调一次SetColorIndex——SetBordersColorIndex走最优 wire 路径(单次 cells loop,BorderMask=15),ConsumePendingRichSlot在每个触及的 XF 上一次注册 4 个 XFExt slot。比 phase-2 fan-out 少 ~4x cell-loop 迭代,XFExt 结果字节级相同。 - ConsumePendingRichSlot 遍历 set。Slot 注册循环走 8 个 enum 元素,把
FPendingRichSlot中存在的每个 slot 通过RegisterXFExtSlot注册。复合 selector 更新中 XF 未实际改变的边界 cell 仍触发 callback —— 无害,因为 XFExt slot 仅在 cell 真正带对应 border line 时才有视觉影响,indexed wire 已由 Excel 理解的 per-cellBorderMask设好。
版本 2.62.0
- Chart backlog wave D phase 5:自定义 theme XML round-trip + drawing theme helper。三部分关闭 phase 4 留下的最后 theme color 缺口。Excel 中通过"页面布局 → 颜色"设置的自定义 theme palette 现在加载时能恢复:parser 走 BIFF8
$0892Theme record 中内嵌的 OOXML<a:clrScheme>,就地更新 workbook 的 12-slotFBiffTheme。对应的 writer 在 palette 与 default Office scheme 不同时 emit 同一 record,让 caller 自定义的 theme 通过 HotXLS 不再 fall back default。新增XlsApplyThemeColorToDrawinghelper 让 chart / shape caller 用 cell 已有的 theme idx + tint 词汇寻址 drawing 颜色。 - 读端:OOXML theme XML 解析。
ParseTheme把 record body(frtRefHeaderU + dwThemeVersion + 变长 XML payload,可跨 Continue records)拼成单个字节缓冲区,对 12 个<a:clrScheme>子标签(dk1, lt1, dk2, lt2, accent1..6, hlink, folHlink)做 targeted 子串扫描。每个 slot 优先匹配<a:srgbClr val="RRGGBB"/>,fall back<a:sysClr ... lastClr="RRGGBB"/>,然后把RRGGBB转 HotXLS COLORREF layout 调FBiffTheme.SetThemeRGBColor。不像 OOXML 的 body(缺<a:clrScheme>sentinel、假设的 ZIP-compressed 变体等)保持 palette 默认 scheme 不变,确保常见渲染仍正确。 - 写端:Theme record 仅在 palette 非默认时 emit。
TXLSWorkbook.StoreTheme通过IsBiffThemeDefault判断 palette 是否还是 Office default scheme,只在 drift 时 emit$0892record。OOXML body 用确定性模板构建:12 条<a:srgbClr>entry(对 dk1/lt1 选 srgbClr 而非 Excel 原生 sysClr 形式,因为同一 parser 能 round-trip 这种形式且无需 sysColor 名字解析),加 schema 要求的最简<a:fontScheme>/<a:fmtScheme>stanza。未触碰的 workbook 不 emit record,字节流与 pre-Phase-5 完全一致。 - Drawing theme color helper。新 free function
XlsApplyThemeColorToDrawing(ColorFormat, Workbook, ThemeIdx, Tint)通过 workbook palette 解析 theme idx + tint 后把 RGB 写入TXLSColorFormat(shape fill / line / chart color)。BIFF8 OfficeArt 是 pre-Office-2007 binary format,无原生 theme color 编码,所以这是 set-only:read-back 返回解析后的 RGB 而非 theme slot,round-trip theme 引用在磁盘上丢失。完整 theme round-trip 应该用 cell 上的IXLSInterior.SetThemeColor/IXLSFont.SetThemeColor/IXLSBorder.SetThemeColor,它们走 XFExt $087D。 - Wave D 5 phase 完整闭环。Phase 1(v2.58.1)加 case 表 acknowledge、Phase 2(v2.59.0)写 RGB cell color XFExt、Phase 3(v2.60.0)闭环 RGB reader、Phase 4(v2.61.0)在 cell 上落地 theme color path、Phase 5(本次)用自定义 theme XML round-trip 加 drawing 侧 helper 收尾。Cell 现在 round-trip BIFF8 spec 能表达的 palette / RGB / theme 任意组合时与 Excel 渲染 pixel-perfect;drawing 通过 helper 把视觉意图传过去,但代价是 OfficeArt format 的 RGB-only 读回特性。
版本 2.61.0
- Chart backlog wave D phase 4:BIFF8 theme color 支持(theme idx + tint 通过 XFExt $087D)。Office 12 槽位 theme palette(lt1、dk1、lt2、dk2、accent1..6、hlink、foHlink)现在在 .xls 侧完整 round-trip:caller 可以通过新 API
Interior.SetThemeColor(themeIdx, tint)/Interior.SetPatternThemeColor/Font.SetThemeColor/ 各边Border.SetThemeColor直接寻址 theme color,cell color getter 读时通过 workbook BIFF theme palette 把同一 theme idx + tint 还原回去。XF 记录仍接收最匹配的 indexed icv(让 Excel 2003 等旧版 reader 仍能渲染一个近似色),而 Excel 2007+ 通过 XFExt FullColorExt(xclrType=3)future-extension record 还原出准确的 theme 意图 —— 这正是微软"另存为"把 theme-styled .xlsx 降级为 .xls 时使用的同一个 backward-compatibility 技巧。 - 新 caller API。5 个新
SetThemeColor入口与现有 RGB / index setter 并列:IXLSInterior.SetThemeColor(ThemeIdx, Tint)、IXLSInterior.SetPatternThemeColor(ThemeIdx, Tint)、IXLSFont.SetThemeColor(ThemeIdx, Tint)、 以及每条 border edge 的IXLSBorder.SetThemeColor(ThemeIdx, Tint)。ThemeIdx是 0-based theme 槽位(0=lt1、1=dk1、2=lt2、3=dk2、4..9=accent1..6、10=hlink、11=foHlink);Tint是 spec 风格的 -1.0..+1.0 加亮/加深调整值,被编码到 FullColorExt.nTintShade 作为 Q15 signed int。 - Workbook BIFF theme palette。
TXLSWorkbook现在带一个FBiffTheme: TXLSThemeColors,初始化为 XLSX 侧多年来通过TXLSColorManager.FTheme使用的默认 Office theme scheme。Cell color getter 通过GetThemeRGBColor(idx, tint)(已经在lxRgb.GetRGBTInt中应用 HSL-based tint 调整)从该 palette 解析 theme idx + tint。内部_BiffThemeproperty 为 parser 侧后续更新预留接口。 - Theme record($0892)读时 acknowledge。
lxRead.ParseTheme把$0892从 default-skip 路径移出,让 workbook-globals case 表把它当作已知 record。内嵌 OOXML theme XML body 暂不解析 —— 12 个默认 Office theme color 已经匹配大部分 source,Excel 设置的 theme cell 通过它能正确渲染。带完全自定义 theme 的 workbook 会在这里通过 default palette 浮出 theme cell(known limit;基于 XML 的 theme 解析留给后续 wave)。 - 为什么写时不发 Theme record。HotXLS 保存的 .xls 文件不发 Theme record。Excel 2007+ 在无 $0892 时回落到默认 Office theme —— 这与 HotXLS
FBiffTheme的默认 scheme 完全一致,所以用SetThemeColor设置的 cell 在 Excel 中能正确渲染,不需要我们 ship 内嵌 XML。文件因此更紧凑,writer 侧也不依赖 XML emit。
版本 2.60.0
- Chart backlog wave D phase 3:XFExt($087D)读端 RGB / theme 恢复闭环 round-trip。Phase 1 的 acknowledgement 和 Phase 2 的 emitter 现在与一个真正消费每条
$087D记录写到 workbook XF rich-color side-table 的 parser 配对。Excel 写出的带 RGB cell 颜色文件(fill、font、各边)现在通过cell.Interior.Color/Interior.PatternColor/Font.Color/ 各边Border.Color返回 Excel 写入的精确 RGB,而非 HotXLS 之前对同样 cell 返回的 indexed palette 近似值。Wave D 在两个方向都完整闭环。 - 读端:
ParseXFExt遍历 ixfe + cexts + rgExt。解析 8 种颜色 ExtProp extType($0004 fillFg、$0005 fillBg、$000D font、$0007/$0008/$0009/$000A/$000B 对应 top/bottom/left/right/diagonal),解码每条 FullColorExt body(xclrType、nTintShade 作 signed Q15、xclrValue)。xclrType 2(RGB)和 3(theme)按记录的ixfe注册到 workbook side-table;其它 extType($0006 FillGradient、$000E FontScheme、$000F TextIndent)干净 skip 不破坏 case 表,留给未来 wave。cb防御性边界检查使畸形记录在声明长度内终止解析,不读越界字节。 - Cell color getter 优先查 side-table。8 个颜色 getter 原来直接走 indexed-palette 路径(
GetCustomColor(GetColorIndex)),现在先解析 XF index,调TlxFormatList.TryGetRichSlot查对应 rich-color slot,slot 携带 RGB 时通过现有GetRGBTInthelper 应用nTintShade。xclrType=3(theme)回落到 indexed 路径:BIFF workbook 在该调用链上没有 theme color 模型,palette 近似仍是该 cell 的最优答案。XF 没被 Phase 2 setter 触碰也没被 parsed XFExt 命中的 cell 读出结果与之前字节级相同。 - Wave D 完整闭环。Save 保留 caller 设的 RGB(Phase 2)。Load 保留 Excel 设的 RGB(Phase 3)。不带 rich color 信息的 workbook 字节流与之前完全一致。剩下的限制仍为 known limit:theme color 仍走 BIFF palette 降级(因为该 codebase 这一侧没有 theme color manager),复合 border selector(
xlAround/xlInside*)绑定单一 side-table slot 而非 per-edge —— 这两种 case 都罕见到可留给后续 wave。
版本 2.59.0
- Chart backlog wave D phase 2:BIFF8 cell 颜色现在通过 XFExt($087D)写出。应用代码在 BIFF8 路径执行
cell.Interior.Color := $00FF6633(或任意 RGB)时,写出端现在会在 indexed-palette XF entry 旁边同时发一条$087DXFExt record,Excel 重开 workbook 时看到的就是 caller 传入的精确 RGB,而不再退化为 HotXLS 之前的 56 色 palette 近似。覆盖 4 类单元格颜色面:Interior.Color/Interior.PatternColor/Font.Color/ 每边的Border.Color(top / bottom / left / right / diagonal),以及便利接口Borders.Color—— 后者现在自动分发到 4 条主要边,每条都填到自己的 XFExt slot 上。 - Round-trip 怎么不破坏。BIFF8 cell setter 链仍产出与以前完全一致的 indexed-palette XF wire 输出 —— 任何忽略
$087D的 reader(HotXLS 自己或其他工具)看到的仍是原来的近似色。XFExt 紧跟在 XF 旁边,把原 RGB 装进 16 字节 FullColorExt(xclrType=2, xclrValue=$00BBGGRR, nTintShade=0),包在带 spec-正确 extType 的 ExtProp 里($0004 fillFg / $0005 fillBg / $000D font / $0007/8/9/A/B 对应 top/bottom/left/right/diagonal 边)。从未走过颜色 setter 的 cell 仍不会发 XFExt —— 不带 rich color 的 workbook 字节流与之前完全一致。 - 存储与簿记。
TlxFormatList加 per-XF rich-color side-table 保存 cell setter 传入的原始 RGB / theme 信息,按 hash 解析后的 XF index 做 key。TXLSRange.SetXFProperty/SetRangeXFBordersProperty加可选OnNewIndex回调,cell setter 可以把 rich color 注册到这个 cell 最终落到的每个 XF index 上(多 cell range 经哈希后落到多个不同 XF 时全部覆盖)。StoreWorkbook在 STYLES 之后、PALETTE 之前消费 side-table 发 XFExt,符合 [MS-XLS] §2.1.7.20.3 Workbook Globals ABNF 中*XFExt的位置。xlExcel5 输出不变(BIFF5 没有 XFExt)。 - 已知限制。读端仍停留在 wave-D-phase-1 的 acknowledgement:
ParseXFExt消费$087Drecord 但**还没**把恢复的 RGB 回填到 workbook 的 style 对象上,因为在 hash-keyed style 模型里这样做有破坏现有 XF entry 的风险。HotXLS 自己保存的文件现在在 Excel 里显示正确;从 Excel 来的文件再用cell.Interior.Color读取时仍看到 indexed-palette 近似。读端的精度恢复留给后续(Phase 3),需要重构 style hash 让 per-XF rich color 在 hash anchor 之前先 admit 进来。
版本 2.58.1
- Chart backlog wave D(只完成读端 acknowledge):XFExt($087D)不再走 default-skip 路径。BIFF8 workbook-globals case 表新增
ParseXFExt分支,正式消费 Excel 在 RGB/theme 颜色 cell 旁边写出的$087D记录。读端**不再**修改 indexed-color XF 记录 —— 完整的 RGB/theme 精度恢复到 workbook 的 hash-key 样式模型上,推到独立 wave 处理,因为这需要 BIFF 写端样式类增加目前不存在的 RGB/theme 颜色字段。从 Excel 来的带富色文件继续按 HotXLS 一直以来的 indexed 近似加载,但"把$087D当成未知 record"的 spec-conformance 缺口被关闭了。 - 为什么不做完整 wave-D。Plan 设想的是 write+read 配对实施,但调查发现 BIFF 写流水线(
TXLSWorkbook.FXFList: TlxFormatList)把 XF 样式数据编码成 string-key 加 hex-packed indexed color slots,完全没有 XLSX 端TXLSStyleColor(带ColorType/ColorValue/TintAndShade)的对应物。要加 XFExt emission,要么桥接两套样式模型,要么给TlxFormatList加 per-XF 富色 side-table,两种方案都比单个 wave 能承担的重构更大。所以本次改动保持微创:lxRead 识别该 record,lxStyleXf 和 lxHandle 不变。
版本 2.58.0
- Chart backlog wave C:SST 富文本与音标 round-trip(BIFF8 XLUnicodeRichExtendedString)。Excel 中设置的富文本格式(单元格内不同字符带各自字体 / 颜色 —— Format Cells 对话框里"两种颜色同一格"那种效果)存在共享字符串表的
XLUnicodeRichExtendedString里,带一个rgRunFormatRun 数组。日语音标(汉字上方标的假名注音)挂在同一 record 的rgExtRst块。HotXLS 之前读时全丢、写时按 plain text 重新发,所以打开再保存一次 workbook,所有多格式单元格都被压成单一字体 / 颜色。共享字符串解析现在按 unique string 保留这两块尾部,写时当单条记录装得下就把它们重新附加上。 - 读端跨 Continue 边界时不重读 flag byte。
ParseSST内新增的CollectRawTailhelper 按原始字节抓rgRun(cRun × 4 字节每条 FormatRun)再抓rgExtRst,跨 Continue($003C)按需续读 —— 按 [MS-XLS] §2.4.58,这两块在 Continue 边界**不会**重新带上 string 的 flag byte,而旧的逐字节 skip 逻辑在rt或sz超过当前 record 时无法正确处理。保留下来的尾部通过新方法TXLSStringTable.AddWithExtras注册到 workbook SST,该方法故意不增加 cell 引用计数,所以后续LabelSST解析仍能产出正确的cstTotal用于写回。 - 写端在单条 BIFF 记录装得下时附加 fRichSt / fExtSt + cRun / cbExtRst + rgRun + rgExtRst。
AddSSTItem现在在 overflow 检查里把富文本 / 音标尾部大小计算进去;string body + 尾部能整体放进单个 8224 字节 SST chunk 时发完整保留布局,Excel 重新打开 workbook 时原始格式不丢。超出此长度的字符串回落为 plain text(splitter 否则要在 rgRun 仍在续写时插入 Continue flag byte,当前 writer 没有这层状态机) —— 这是 wave-C 计划明确标注的 known limit,只影响很长的富文本字符串(> ~4000 wide char)。 - Continue flag byte corner case 修复(从 v2.54.0 SST 审计延续过来)。按 [MS-XLS] §2.4.58,SST Continue 记录开头的 flag byte 只有
fHighByte(bit 0)有效;fExtSt(bit 2)和fRichSt(bit 3)**必须**忽略,因为这些字段在第一条记录开头出现且仅出现一次。ParseSST现在把 Continue flag byte 用$01掩码,避免某个杂散高位让 reader 多跳 2 或 4 字节找根本不存在的 cRun / cbExtRst,后续字节全部错位。
版本 2.57.0
- Chart backlog wave G:Header / Footer 图片 round-trip 保留(BIFF8 HFPicture)。当 Excel 给 worksheet 设了 header/footer 背景图(Insert → Header & Footer → 公司 logo 那种用法)时,图片数据保存在
HFPicture($086C) record 里,内嵌一个 OfficeArt BLIP。HotXLS 之前 case 表没有这个 record 分支,所以读取时整个 payload 被丢掉,再次保存就找不到 header/footer 图片了。读端现在按每 sheet 完整保留 record body(所有 Continue 段拼接),写端在 spec 要求的位置把它原样发回,Excel 重新打开就还能看到原来的图片。 - 读端先把所有 Continue 段拼接再存。
ParseWorksheetRecord里新增的ParseHFPicture分支会遍历 collator 已经合并好的DataList(slot 0 是 $086C body,后面若干是 $003C body),把所有字节拼成一个TBytes存到 sheet。一个 sheet 可能带多条 entry —— Excel UI 最多 6 张(默认 / 首页 / 奇偶页 × 左 / 中 / 右),所以存储是数组,而不是单字段。 - 写端紧跟 PageSetup 之后发射 HFPicture record,后续 Continue 拆分交给现有 splitter。新的
StoreHFPictures步骤插入到 per-sheet 写入序列中StoreSetup紧后面,对齐 [MS-XLS] §2.1.7.20.2 worksheet ABNF 中*HFPicture的位置。每条保留的 body 用一个新的 $086C header 包装,送进AppendData—— 已有的AddContinuehelper 在 BLIP 超过 8224 字节时接管,所以一张 30-50 KB 的 JPEG 会被拆成一条 $086C 加 4-6 条 $003C,跟 Excel 写出来的形状一致。 - 没有新公开 API。Wave G 是 round-trip 保留特性;HFPicture 内容对应用代码不透明(不提供给 caller 注入新 header 图的 setter)。从未带 HFPicture record 的工作簿写出的字节与之前完全一致。内部 helper
TXLSWorksheet._AddHFPictureBlob专给 reader 用,下划线前缀与_Drawing/_Autofilter同惯例。
版本 2.56.0
- Chart backlog wave B:Worksheet tab 颜色 round-trip(BIFF8 SheetExt)。Excel 中通过右键 标签颜色 设置的 sheet tab 颜色,现在 BIFF8 路径既能读又能写。
TXLSWorksheet.TabColor是新加的公开 property,接受 HotXLSLongWord颜色(low byte=R, mid=G, high=B, 顶字节=0,与Font.Color/Interior.Color同惯例);默认值0表示"自动 / 无 tab 颜色",此时整条 record 不写出。 - 写出端每个有色 sheet 发射一条
SheetExt($0862)。对每个TabColor非零的 sheet,在 workbook globals 流 EOF 之前追加一条 48 字节 record。布局按 [MS-XLS] §2.4.282 SheetExt v1 + §2.5.108 FullColorExt:12 字节frtRefHeaderU+ 4 字节cb+ 4 字节保留flagsTab1+ 16 字节 FullColorExt 块(xclrType=2 RGB, nTintShade=0, xclrValue=tab 颜色) + 4 字节iTabId(对应 BoundSheet8 在流中 0-based 序号) + 4 字节保留flagsTab2。iTabId遍历顺序与 BoundSheet 循环对齐,确保多 sheet workbook 中两段编号一致。xlExcel5 输出不变(BIFF5 没有 SheetExt record)。 - 读端在打开时恢复 tab 颜色。
ParseWorkbookRecordcase 表新增ParseSheetExt分支:读iTabId和 FullColorExt 块,把解析后的 RGB 值写回Sheets[iTabId + 1].TabColor。xclrType=2(RGB)直接存原值;xclrType=1(indexed icv)通过 workbook palette(Colors[icv, 0])解出 RGB,这样无论 Excel 用哪种方式编码,应用层都看到具体 RGB 值;xclrType=0(自动)和xclrType=3(theme)让TabColor保持默认0,与写出端"无 tab 颜色"语义一致。 - Round-trip 示例。SaveAs .xls 前
Workbook.Sheets[1].TabColor := $00FF00(绿色:B=0, G=$FF, R=$00),生成的工作簿在 Excel 中打开时 tab 显示为绿色;再次 SaveAs 后重新打开,property 仍返回$00FF00。从 Excel 来的带 tab 颜色的文件现在打开时不再把每个 tab 退化成自动色。
版本 2.55.1
- 恢复 main 分支可编译状态。两处 pre-existing 标识符错误让 HotXLS 在 RAD Studio 12+ 上彻底无法编译,现在修好。两处问题都是早期 bug-fix release 留下的回归,但因为没有编译 gate,只有下个 contributor 试图重新编译时才会暴露。
- 共享公式多列写出不再引用缺失的 record 字段。v2.50.0 的 SHRFMLA wire-format 修复在
WriteShrfmla中加了Data.AddByte(Group.LastCol),但忘记同步在TXLSShrfmlaGrouprecord 上加该字段,导致 package 编译失败 "Undeclared identifier: LastCol"。Record 现在和原有FirstCol并列声明了LastCol,并由CollectSharedFormulas.OpenGroup用 group 的 anchor 列填充。因为 collector 当前只产出单列 group,运行行为不变 —— 但 spec 要求的colLast字节现在写入的是真正的值,而不是colFirst的别名。 - XLSX cell 写出通过 forward declaration 引用
XlsxFloatToStr。v2.51.0 的 locale-safety 修复在 cell-value 分支(line 2718) 引入了 XlsxFloatToStr 调用,但该 helper 定义在几百行之后(line 2910)。Delphi 单遍编译器没有 forward declaration 时报 "Undeclared identifier: XlsxFloatToStr"。lxHandleXimplementation 段顶部现在放了 forward declaration,使早期调用点和原有定义都能干净编译。
版本 2.55.0
- Chart backlog wave A:多 series 缓存 wiring + 图表 / 坐标轴标题 caption。两处 chart-builder 长期限制现在补齐;均来自 v2.54.0 审计 backlog。第一处是 wire-format-only(公开 API 不变);第二处把已经存在但被忽略的
AddChartSheetTitle / CatAxisTitle / ValAxisTitle 参数串到输出流。 - per-series values 缓存不再被 Series[0] 截断。[MS-XLS] §2.1.7.20.1 chart-sheet ABNF 允许
*(SIIndex *NUMBER)—— 每 series 一个SIIndex(1) + N×NUMBER块。Phase-1 builder 只发一个按Series[0].ValArea大小的 cache 块,其它有更长 value range 的 series 缓存被静默截掉。Builder 现在 (a) 计算所有 series 中最大的 point count 作为DIMENSIONS的行范围,(b) 对每个准备好的 series 单独发射一个SIIndex(1)块,其 NUMBER 数量等于该 series 自己的AreaPointCount(ValArea)。缓存槽位仍是 zero-valued (BRAIPtgArea3d引用在绘图时仍解析到真实 source cells);改动只是为了让 Excel 严格 parser 看到完整的 cache footprint。 - Chart Title / CatAxisTitle / ValAxisTitle caption 现在能写出。Phase-1 实现接收
AddChartSheet重载里的三个 Title 参数但静默丢弃("Junk := Length(...)" 占位)。现在在CHART容器 End 之前的 spec-正确位置(按 [MS-XLS] §2.1.7.20.1 CHARTTITLES ABNF)发射一个完整 attached-label 块 ——TEXT($1025) +POS+BRAI-literal-tStr +SeriesText($100D) +OBJECTLINK($1027) + End。OBJECTLINK.wLinkObj按 [MS-XLS] §2.4.182 分别为 1 = 图表标题、2 = value-axis 标题、3 = category-axis 标题。Caller 传Title := 'Quarterly Sales'时,Excel 终于能在 plot area 上方渲染出 "Quarterly Sales"。
版本 2.54.1
- [MS-XLSX] 交叉审计后续。v2.52.0 审计"deferred"列表里的两个定点修复。两项都对用户可见;都不破坏既有调用方。
- 日期单元格 + 任意单一非 numFmt 维度,日期格式不再丢失。带
FontIndex/FillIndex/BorderIndex/AlignmentIndex/ProtectionIndex但没有显式NumberFormatIndex的TDateTime单元格之前会被路由到该单维度对应的 cellXf,其numFmtId是 0(General),Excel 把单元格渲染为原始序列号(如46038)而不是1/15/2026。XLSX style engine 现在把"隐式日期"当虚拟维度:任意其它维度被设置都会把单元格升级到 composite cellXf,并附带numFmtId=14。无任何样式的纯日期单元格仍按以前路由到XlsxXfIndexDate。新增公开 surface:TXLSXWorkbook.RegisterCompositeXf/GetCompositeXf各增加 7-arg 重载接受 OOXML 内建numFmtIdoverride;既有 6-arg 签名不变,内部转发到新重载并把 override 设为 0。 - 违反 Excel 命名规则的 sheet 名自动 sanitize。Excel 拒绝长度超过 31 字符、包含
: \ / ? * [ ]、首尾带单引号、等同保留名History(大小写不敏感)、或与另一个 sheet 名冲突(大小写不敏感)的 sheet。HotXLS 之前把用户输入原样透传,所以Workbook.Sheets.Add('Q1:Q2 Sales')这种调用产生的工作簿打开时弹"输入的名称无效"。TXLSXSheets.Add现在用新 helperXlsxSanitizeSheetName标准化(禁用字符替换为_、剥外层单引号、限长 31、空 / 保留名退化为'Sheet'),冲突时追加' (2)'/' (3)'后缀(不区分大小写比较)。对合法名 idempotent,所以从规范 .xlsx 解析出的 sheet round-trip 不变。
版本 2.54.0
- 对照 [MS-XLS] v20250520 / [MS-OFFCRYPTO] v20240820 的深度审计 round 2。8 个并行 code-reviewer agent 聚焦 corner cases 与既有功能合规深度核查,覆盖 Worksheet shell records / SST Continue 边界 / 公式 PTG 深度 / 加密 padding / Chart / Drawing+Comment / Pivot+Table。本轮落地 8 处真实 bug 修复;另有较大功能缺口(XFExt / PtgArray rgcb / Chart 标题 / Pivot 等)写入 backlog 留作后续 feature 工作。公开 API 不变,现有代码无需改动即可重新编译。
- Comment Note record 现在符合规范。在
TMsoDrawing.StoreNotes中两处独立修复(按 [MS-XLS] §2.4.179 Note):(1)idObj现在按 Word 写出(2 字节)而非 LongWord(4 字节),纠正了 idObj 之后所有字节的 2 字节偏移漂移;(2) 之前完全缺失的stAuthorXLUnicodeString 字段现在按FAuthor正确序列化(cch + flags + UTF-16 body)而不是被替换为一个裸Word(0)。Excel 严格 parser 在stAuthor结束 Note 解析,缺失该字段会让 round-trip 时 comment 元数据被损坏,即使 Excel 仍能打开文件。 - Comment
Visible属性不再反向。TMSOShapeTextBox.GetVisible/SetVisible之前在fHidden被设置时返回 True,在 caller 要求 comment 可见时写入fHidden—— 与 bit 的语义完全相反([MS-XLS] §2.4.179 grbit bit1: 1=hidden)。之前Comment.Visible := True实际让 comment 隐藏;现在读写两侧都与属性名一致。 - RC4 密码派生对 16 字符及以上密码正确。[MS-OFFCRYPTO] §2.3.6.1 把 MD5 单 block padding 的消息长度字段存到 bytes 56-63,作为 64-bit little-endian 位数。读路径(
lxDecryption)和写路径(lxEncrypter)之前都只通过SetByte写低字节,对 16+ 字符密码(位数 >= 256)悄悄丢掉高字节。长密码文件现在两侧派生出同一个 ValDigest;之前正确的长密码会被拒收,HotXLS 加密的长密码文件也无法重新打开。 - 公式
tFuncVartoken 现在屏蔽fCeFuncbit 以查函数名。[MS-XLS] §2.5.198.63 把末尾 Word 拆为tab(15 低位)+fCeFunc(1 高位);reader 之前把整个 Word 存进Item.IntValue作为哈希表 key,带 user-prompt 标志(macro/UDF 调用者)的函数被哈希到$8000 | iftab返回空函数名,整条公式失败。现在用$7FFFmask。 - 第二个 FILEPASS record 现在被忽略。[MS-XLS] §2.4.117 规定 Workbook 中最多一个 FILEPASS;恶意或损坏的 Workbook 出现第二个 FILEPASS 时,之前会 free 当前的 decrypter 并重新派生 keystream,与已经消费的数据脱节。现在 encryption armed 状态下后续的 FILEPASS 会被静默丢弃。
- PtgArray V-class opcode 正确发射。
GetArrayData(aClass=0)之前 fall through 到 A-class opcode($60);按 [MS-XLS] §2.5.198.32,V-class 应为$20、R-class 为$40、A-class 为$60。aClass=0现在正确映射到$20。 - Chart3DBarShape 不再写到 2D 图表里。[MS-XLS] §2.4.47 明确 Chart3DBarShape "MUST be ignored if the current substream does not contain a Chart3d record"。HotXLS 暂无 3D 图表类型(不发 Chart3d),所以在每个 DataFormat 块里写空的 Chart3DBarShape 既冗余也不符合规范(空 payload 也不满足 spec 要求的 2 字节 riser+taper 布局)。现在完全不写。
- 审计 backlog 写入
TechnicalNotes.md。本轮审计暴露的较大功能缺口(XFExt 不发射 / PtgArray 常量数组数据不序列化 / Chart Title 等参数被丢弃 / 单 series 缓存模式 / Pivot Table / QueryTable / DConn 不支持)作为已知 gap 记录,供后续 feature 工作参考。
版本 2.53.0
- OpenOffice excelfileformat.pdf 二次交叉审计。v2.50.0 完成首轮交叉审计后再次对照规范,针对首轮覆盖较浅的模块(公式 token 解码器、XF 对齐字节、ROW 大纲折叠边界判断)再发现并修复 3 个 BIFF8 wire-format 缺陷。公开 API 不变。
- 含用户提示标志的宏命令公式不再破坏 token 解析(§3.7.2 tFuncVar)。
tFuncVaroffset+1 字节的 bits 6-0($7F)是参数计数,bit 7($80)是"宏命令用户提示"标志。原读取代码直接把整字节当成参数计数,任何置位 bit 7 的 tFuncVar 都被读成 128+N 个参数,把公式栈撑爆并使整条公式返回 nil。修复后按规范用$7F掩码。 - JustifyLastLine 对齐标志现在能正确 round-trip(§5.115 XF)。BIFF8 XF body 第 6 字节的对齐字段打包 HorAlign + WrapText + VerAlign + JustifyLastLine 四项。原代码只写出前三项,遗漏了 bit 7(
$80,JustifyLastLine)。设置JustifyLastLine = True的单元格保存后该位丢失,Excel 中分散 / 两端对齐的最末行渲染回退为默认行为。 - row 0 / row 65535 不再被误标为大纲组边界(§5.88 ROW)。fCollapsed 位(
$10)在某行大纲级别与上下相邻行不同时设置。边界行的相邻"行"不存在,但OutlineLevel[-1]与OutlineLevel[65536]都返回默认 level 1,导致任何 row 0 / row 65535 显式大纲级别 > 1 的情况被误判为折叠大纲组边界。修复后边界行将不存在的邻居视为与本行同级,仅在真实大纲边界触发 transition。
版本 2.52.0
- [MS-XLSX] 交叉审计 — 第二轮。v2.51.0 审计后对 XLSX writer 的 3 处后续精修。每项都对应一条 ECMA-376 或 W3C XML 规范条款;累计提升与第三方 OOXML 消费者的互操作性、降低严格校验器的告警。
- 单元格字符串两端空白可正确往返。
XlsxFormatCellValue的 inline-string 兜底分支之前发射<is><t>...</t></is>时没带xml:space="preserve";XML 1.0 §3.3.3 规范化会剥掉前后空格,所以 “ Pending ” 这种值在重新加载时变成 “Pending”。SST、富文本 run、comment 文本路径之前都已带这个属性,inline-string 现在补齐。 - 每个 worksheet 都带
<dimension>提示。ECMA-376 §18.3.1.35 将<dimension ref="..."/>元素标记为可选,但每个 Excel 写的 .xlsx 都带它;读它的消费者(Apache POI / NPOI / OOXML SDK)会用该提示预分配单元格缓冲区,免去动态扩容。Writer 现在在行分组扫描时同时计算填充单元格的包围矩形,把元素作为<worksheet>的第二个子元素发射(在<sheetPr>后,在<sheetViews>前)。空 worksheet 退化为<dimension ref="A1"/>。 <sst count="...">报告单元格总引用数,而非唯一字符串数。ECMA-376 §18.4.8 定义count为总引用计数、uniqueCount为唯一字符串数;writer 之前把两者都写成FStrings.Count(永远相等),误导消费者对引用密度的判断。TXLSXSharedStrings现在单独跟踪RefCount,每次Add/AddRich调用无视去重都 +1,属性如实反映总引用数。
版本 2.51.0
- [MS-XLSX] 交叉审计批次。对照 Microsoft [MS-XLSX] — Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format 文档(v20260108)与底层 XML 1.0 / OOXML schema 要求,复审 XLSX writer 并修复 5 处 wire-format 与 locale 安全缺陷。公开 API 不变;现有应用无需修改即可重新编译与导出。
- 保存的 .xlsx 文件现在能在任意 Windows 区域设置下打开。页边距、列宽、行高、字号、颜色 tint、主题色 tint、富文本 run 字号,以及每个单元格
<v>包裹的数值,之前都通过 Delphi 区域感知的FloatToStr序列化。在小数分隔符为 ',' 的 Windows 区域(欧洲大部分、部分亚洲与拉美地区),writer 会发射width="8,43"、top="0,75"这种 OOXML 不允许的属性值,Excel 弹"我们发现 <file>.xlsx 中某些内容有问题"并在恢复过程中清掉页面设置、列宽与数值单元格。所有 double 类型 OOXML 属性现在统一使用与区域无关的 '.' 分隔符。同时修正了内存中列宽 / 行高缓存(之前存的是带区域格式的字符串),在受影响区域下SetColWidth/SetRowHeight之后立刻GetColWidth/GetRowHeight会回到0.0的问题已解决。 - 含控制字符的单元格不再破坏整个工作簿。XML 1.0 §2.2 禁止 ASCII 编码 0x00–0x08、0x0B、0x0C、0x0E–0x1F(以及 U+FFFE / U+FFFF)出现在 XML 文档任何位置,连数字字符引用也不允许。之前若单元格内含这些字节(历史数据 feed、日志 dump、Escape 键标识符),writer 会原样写到
<t>...</t>里,生成 Excel 拒打开且无法恢复的 .xlsx。现在 writer 静默丢弃这些被禁码点,保留合法空白(TAB / LF / CR)。 - 属性值中的换行能正确往返。XML §3.3.3 在交给应用前会把属性值内的原始 TAB / LF / CR 规范化为单个空格。之前多行页眉 / 页脚、定义名注释、多行数据验证提示、超链接显示文本里的换行重新加载时会塌成单个空格。
XlsxEscapeAttr现在把这些字符以	/
/
数字字符引用形式发射,Excel 读回时能还原原始空白。 - <col> 条目按列序号升序发射。ECMA-376 18.3.1.4 / 18.3.1.13 要求每个
<col min="..."/>条目按min升序出现。之前用的 TStringList(Sorted=True)按字典序排整数列号字符串("10" 排在 "2" 之前),同时自定义了第 2 列和第 10 列的 sheet 会产出<col min="10"/>在<col min="2"/>之前。Excel 容忍这种布局但 Office File Validation 会标红;严格 OOXML 消费者(Apache POI 严格模式、启用严格校验的 LibreOffice)直接拒收。列条目现在在发射前先按数值升序排好。
版本 2.50.0
- OpenOffice excelfileformat.pdf 交叉审计批次。在 v2.49.0 [MS-XLS] 审计后,再次对照 OpenOffice Microsoft Excel File Format 文档复审 BIFF8 写入器与读取器,发现并修复 8 处 wire-format 与对象生命周期问题。公开 API 不变,现有应用无需修改即可重新编译与导出。
- 共享公式正确覆盖完整列范围(§5.94 SHAREDFMLA)。
SHRFMLA记录中colLast字段被错写成了colFirst,导致 Excel 把所有多列共享公式组都识别成单列组。现在跨多列填充的公式在重新打开后能正确展开到目标单元格。读取侧colLast宽度也已修正(原来按 16 位读,会把后一个保留字节当作高位)。 - 共享公式 Boolean / Error 缓存结果可正确回读(§5.50 FORMULA)。v2.49.0 修过的
FormulaValue字节布局问题在共享公式写入路径(携带tExp令牌指向SHRFMLA主公式的成员单元格)中仍然存在。缓存的TRUE/FALSE、#REF!/#DIV/0!等结果现在会按写入值显示,而不是统一被读回为FALSE/#NULL!。 - FORMULA 选项标志标识共享公式成员(§5.50 FORMULA)。共享公式组中的单元格现在会在 FORMULA 记录的选项标志里置
fShrFmla位(0x0008),严格解析器据此识别tExp作为对主公式的回引,而不是尝试把它作为不透明 opcode 直接求值。 - 严格 reader 能正确识别加粗 / 下划线字体(§5.45 FONT)。FONT 选项标志现在除独立的
bls/uls字段外,还会在 bit 0(加粗)和 bit 2(下划线)置位。读 grbit 的 LibreOffice 导入路径与 Office File Validation 不再把加粗 / 下划线字体误判为普通字体。 - CFRULE 选项标志携带规范要求的固定位(§5.16 CFRULE)。当至少存在一个格式块时,选项标志 DWORD 现在 OR 上 bit 7(
0x00000080,"Always 1")和 bits 21-19(0x00380000,"Always 111")。严格 CFRULE 解析器下条件格式规则现在能 round-trip;"无格式块"特例(选项标志全 0)的特殊语义予以保留。 - CHOOSE() 公式可正确回读(§3.10.5 tAttrChoose)。原
tAttr解析器对所有子类型固定跳 4 字节;tAttrChoose($04)是变长的(header + 跳转表 + 错误跳转),解析器之前会跳进跳转表内容并破坏所有后续 token。现在解析器先读nc,然后按6 + 2·nc字节推进,与规范一致。 - 数据校验与条件格式销毁时不再越界访问。两个
Destroy析构函数(TDataValidator、TCondFormatter)在合法索引为0..cnt-1的列表上用了0..cnt循环,销毁时多访问一个越界槽位。长时间构造 / 销毁大量 CF / DV 容器的应用退出时不再偶发 AV。
版本 2.49.0
- 对照 [MS-XLS] v20250520 的全面规范审计修复。覆盖 BIFF8 writer、公式解码器、加密路径、chart builder、条件格式与数据验证运行时、SST/ExtSST 索引、VBA storage reader、OLE 流打开路径共 16 处 wire-format / 行为缺陷。公开 API 不变;现有代码无需改动即可重新编译。要点如下。
- BIFF8
Formularecord 的 Boolean / Error 公式结果现在能正确往返。[MS-XLS] §2.5.133FormulaValue把类型标识写在 byte[0]、bool/error 编码写在 byte[1];writer 之前以 Word 形式写$0001/$0002然后把值塞进 byte[2],所以缓存的 Boolean 公式都被读成 False,Error 公式都被读成 #NULL!。 SetColorRGB设置的单元格颜色现在能正确显示。颜色管理器把 RGB 值写成 ColorType=1(主题色),把主题色写成 ColorType=2(RGB),两条代码路径完全互换。两个 setter 现在都走对应的 ColorType 分支,RGB 走 RGB 解析、主题索引走主题解析。- XOR Obfuscation 与 RC4 解密修正。XOR Method-1 解密循环现在符合 [MS-OFFCRYPTO] §2.3.7.3(先 XOR 再 rotate-right 5;XorArray 索引以进入时的 stream 位置为起点,而非处理完之后的位置)。RC4
Skip现在跨越每个 1024 字节边界连续推进 keystream,而不是直接跳到目标 block —— 保证之后每个Decrypt调用的密钥流与文件位置对齐。 - Chart sheet wire format 对齐规范。SIIndex records 按 numIndex=1 → 2 → 3 顺序发射([MS-XLS] §2.4.262;之前是 2 → 1 → 3,严格 parser 拒收),DEFAULTTEXT 数量限制为规范上限 2 个([MS-XLS] §2.1.7.20.1;之前 4 个),Chart3DBarShape 占位 record 使用正确的 id
$105F(之前$1066)。 - HLink tooltip records 现在能正确加载。
HLinkTooltip($0800) body 解码器之前读 FrtRefHeader 的 anchor 字段在 offset 2/4/6/8 而不是 4/6/8/10,导致 anchor-range 比对永远失败、所有单元格 tooltip 都被静默丢弃;现在 tooltip 能正确关联到 hyperlink。BIFF8 range-reference 解码器也修正了 BIFF5/7 fallback 路径中FFirstColRel/FLastColRel的 typo,该 typo 错误处理负 last-column 相对偏移的符号扩展。 - 条件格式 / 数据验证运行时修正。
TCondRange与TDVRange的IsContainRow之前只在 range 退化为单行时才返回 true(比较被写反),按行清除 CF / DV 规则在多行 range 上几乎从不命中。三个析构函数(CondFormat、formatter、DVRangeList)在for i := 0 to cnt循环中越界一次(合法索引是 0..cnt-1),off-by-one 已修;长时间运行场景在 teardown 时不再偶尔 AV。CF12 图标集规则现在发射 ct=$06(IconSet,按 [MS-XLS] §2.4.43)而非 ct=$05(Filter),含图标集规则的 workbook 在 Excel 中能完整保留规则。 - ExtSST 快速查找索引对超大 workbook 也符合规范。
dsst字段现在按 [MS-XLS] §2.4.107 计算为max((cstUnique / 128) + 1, 8),而非静态 8;含约 900+ 个唯一字符串的 workbook 现在生成正确的rgISSTInfbucket 数组,Excel 的 SST 快速查找索引正常工作。 - WriteAccess record 符合 [MS-XLS] §2.4.349 cch <= 54 的硬性要求。
userName.cch字段现在写实际用户名长度("HotXLS"=6),剩余字节用规范定义的"unused"尾段填充。之前 cch=109 被 Office File Validation 视为格式硬性违规。 - BIFF8 Workbook 流打开路径符合规范拼写。OLE
OpenStream首次尝试用 'Workbook'(首字母大写,按 [MS-XLS] §2.1.7.20),而不是全小写;大小写敏感的 OLE 实现(Wine 等)上的 compound file 容器首次尝试即成功打开。 - VBA 模块读取器不再丢弃每个 stream 的最后一字节。seek-to-end 长度之前用
trunc(l) - 1而非trunc(l),截断了压缩源代码的最后一字节,某些模块的 RLE 容器解压器会提前终止。
版本 2.48.10
- HotXLS 写出的 .xls 文件现在包含 Excel 期待的两个 OLE compound-file 属性集流:
\005SummaryInformation与\005DocumentSummaryInformation。v2.48.10 之前只有 TRIAL build 才写(用于 trial 横幅 stamping);release build 写出的 .xls 文件 Workbook 流是合法 BIFF8,但 OLE 容器缺标准 Office 元数据流。Excel 2003 严格 parser 把这种情况识别为 "File error: data may have been lost"(现代 Excel 保留保护视图"此文件存在问题"横幅)。加上流就消除 chart workbook 上的对话框,无需改动任何 BIFF8 record。 - 两个流通过 Win32 的
StgCreatePropSetStg+IPropertySetStorage.Create+IPropertyStorage.WriteMultiple路径写出 —— 跟 Microsoft Office 自己用的代码同一条,所以 Office File Validation 接受字节布局。SummaryInformation 流以默认AppName="HotXLS"与空 Author 创建;TRIAL build 仍会在默认 stamp 之后通过lxTrial.XlsTrialStampXlsSummary覆盖 Author / AppName 成 trial 横幅,所以 trial 文件在 Excel 文件 > 信息 > 属性面板仍可识别。DocumentSummaryInformation 流以空创建(Win32 仍发射 property-set header + CODEPAGE 属性,这对 Excel 严格 parser 来说已"存在且格式正确")。 - 本次修复是通用性的 —— 每个 HotXLS 写出的 .xls 现在都带上标准 OLE 元数据,不限于 chart workbook。早期 release 只输出 worksheet 的文件之所以没暴露这个症状,是因为 Excel 对 metadata 缺失的 worksheet workbook 比 chart-sheet workbook 更宽容;但技术上它们一样缺。新增
Lib/lxXlsSummary.pas单元持有两个 helper 过程;lxHandle.pas 在TXLSWorkbook.SaveWorkbook中StoreWorkbook填好 Workbook 流之后、FDocStorage.Commit之前无条件调用它们。 - 本次 release 收尾了 chart Phase 2 长达八个版本的 follow-up 序列(v2.47.0 — v2.48.10):从
tArea3Dseries 绑定开始,经过 BRAI id 重对齐、sdtX/cValx 用 Excel 实际值、SERIESTEXT 位置、Workbook 流 padding 移除、sheet 级 shell records,最后到 OLE metadata 流。结果是一份在 Excel 2003 与现代 Excel 中打开都无任何"文件存在问题"警告的 chart .xls,字节级跟 Excel 为同样数据写出的版本对齐。
版本 2.48.9
- BIFF8 chart sheets 现在携带 Excel 2003+ 要求的完整 sheet 级 shell records。v2.48.8 的 chart_phase2_demo.xls 柱状图渲染正确,但 Excel 2003 仍弹出 "File error: data may have been lost" 对话框(新版 Excel 保留保护视图横幅),因为 chart substream 缺少 worksheet substream 通常携带的同一批 sheet 级 records。真实 Excel 文件(from-scratch 与重保存版本)都把 chart records 包在以下 shell 里:
- chart records 之前(BOF 与 UNITS 之间):
HEADER($0014,空)、FOOTER($0015,空)、HCENTER($0083,值 0)、VCENTER($0084,值 0)、SETUP($00A1,34 字节页面设置)、PRINTSIZE($0033,值 3)。 - chart records 之后(最外层 CHART END 后,EOF 前):
DIMENSIONS($0200,14 字节)声明缓存数据范围,三个SERIESINDEX($1065)分别标记 categories / values / bubble-size 缓存槽位,每个缓存数据点一条NUMBER($0203,14 字节),末尾WINDOW2($023E,10 字节 chart sheet 短版本)。
dev-notes/biffview-refs/excel_column_chart_resaved.xls(Excel 保存的柱状图 reference,本地保留)逐字节复制。 - chart records 之前(BOF 与 UNITS 之间):
- Values 缓存目前写零值占位(每个数据点
0.0),跟 Excel 自己重保存 source cache 未预填的 chart 时写的一致。Chart 仍正确绘制真实数据,因为 BRAI 的PtgArea3d引用在绘图时解析到 source worksheet cells —— 缓存的作用是让 Excel parse chart sheet 时不报警,不是用来喂图。后续 release 可以把缓存填上Values范围的真实数字;wire 格式已就位。 - 端到端冒烟测试:在 Excel 2003 打开重新生成的
Demo/Delphi/XlsCreateChart/chart_phase2_demo.xls—— "File error: data may have been lost" 提示不再出现,column chart 渲染跟之前完全一致。同一文件在新版 Excel 中打开也不再有保护视图横幅。
版本 2.48.8
- BIFF8 (.xls) writer 不再在 Workbook stream 末尾追加零字节填充。
TXLSWorkbook.StoreOleFile以前会在最后一个 sheet records 之后调StoreExtraSpace(Book),把 stream length 填充到下一个 512 字节(OLE sector)边界。Excel 严格 parser 把这些尾部零字节当作"伪造的0x0000id record 流",触发"文件存在问题"保护视图提示 —— v2.48.7 chart_phase2_demo.xls 即使 BRAI / sdtX / SERIESTEXT wire 格式都对了、chart 也渲染正确,这个提示依然出现。删掉这个调用让 padding 从 Workbook stream 内容中消失;OLE sector padding 仍然存在,但发生在 CFB 容器层(stream 之下),跟 Excel 自己的做法一致(每个 Excel 保存的 .xls 的 Workbook stream length 都不是 sector 对齐的)。 - 症状历史:任何 HotXLS 写出的 .xls,只要 valid records 总长不恰好对齐 512 字节边界,就带尾部零 stream。这个 bug 从仓库 bootstrap commit 起就存在,但很少暴露 —— 多数 workbook 因为 records 多,padding 落得很小(≤ 4 字节 Excel 容忍)。chart sheet workbook 的 records 量正好远小于 sector 边界(v2.47.0 — v2.48.7 demo padding 420 字节),所以这是 Protected-View 提示稳定出现的场景。
StoreExtraSpace方法本身保留在lxHandle.pas作为 private dead code,以防未来某个 code path 真的需要 sector 对齐的 stream;StoreOleFile中的调用点被移除。Workbook stream length 现在精确等于所有 valid records 的字节总长(chart demo: 3164 字节;Excel from-scratch reference: 4419 字节 — 两者都不对齐 sector)。Reader code paths 不受影响 —— HotXLS 一直能正确读取 Excel 保存的非 sector 对齐 Workbook stream。
版本 2.48.7
- BIFF8 chart series 记录终于在 Excel 中正确渲染。修复是把 BRAI id 编号 跟 [MS-XLS] §2.4.51 对齐 —— 父实施计划文档把 id 含义写反了,从 v2.41.0 到 v2.48.6 每个 chart release 都受这个 bug 牵累。正确的 id 语义是:
id = 0— series name / legend 标签(计划说:categories)id = 1— values(对的)id = 2— categories(计划说:name)id = 3— bubble sizes(计划说:errBars)
- 同时对齐 Excel-saved column chart wire 格式的其他字段:
SERIES.sdtX改0x0003(Excel 对文本 categories 实际写的值,不是 [MS-XLS] §2.4.252 文档化的0x0001),cValx写实际 category 数量而不是0。"sdtX∈ {1, 3} 时cValxMUST = 0" 这条 spec 规则被检查过的每个 Excel sample 否决。 SERIESTEXT($100D)literal name carrier 回来了,但位置正确:紧跟id = 0BRAI 之后,仍在 SERIES BEGIN/END 块内。这是真实 Excel 文件的做法 —— v2.48.5 的发射位置(BRAI 簇之后、DataFormat之前)是错的,会让 chart parsing 出错;正确位置是紧挨 series-name BRAI。- v2.41.0 — v2.48.6 写出的 chart 文件都带着 BRAI 反向的 wire 格式。Excel 能打开不报错,但表现为上述 legend / X 轴症状。用 v2.48.7+ 重新保存即可迁移;API 不变 —— 同样的
AddChartSheet调用现在产出的 chart 跟 Excel 自己为同样数据写出的 chart 字节级一致。 - 新增字节级检视工具
dev-notes/biffview-refs/dump_chart_substream.py,可 dump 任意 BIFF8 .xls 的 chart substream 并 per-record 解码(SERIES / BRAI / SERIESTEXT / AXIS / CATSERRANGE / LEGEND / OBJECTLINK / POS / TEXT)。本次 release 期间用于把 HotXLS 输出跟 Excel-saved reference sample 做 byte-diff;给后续 chart spec follow-up 备用。
版本 2.48.6
- BIFF8 chart sheet substream 撤回 v2.48.5 的修改。Excel 实测 v2.48.5 demo 完全不显示 chart —— 比 v2.47.0 基线还糟(v2.47.0 至少 chart 能画出来,只是 X 轴标签不对)。v2.48.5 的两个改动正是元凶:
SERIES.sdtX = 4实际不被 Excel 接受,尽管 Apache POI 暴露了CATEGORY_DATA_TYPE_TEXT = 4。[MS-XLS] §2.4.252 严格要求sdtX必须是0x0001或0x0003。- 在 SERIES BEGIN/END 块内加
SERIESTEXT($100D)是结构性违规 ——SERIESTEXT属于 TEXT 块(chart title / axis title / data label 上下文),不属于 SERIES 块内。放错位置让 Excel chart parser 拒绝整个 substream。
- v2.48.6 恢复 v2.47.0 的 wire 格式,**额外**加一项 spec 合规修复:
sdtX = 1时SERIES.cValx现在写0([MS-XLS] §2.4.252 spec MUST 规则)。v2.48.6 前写cValx = count(demo 中为 4)违反此规则,可能是 Excel "文档存在问题" 保护视图提示的根因之一。cValy仍按实际 value count 写(sdtY=1 没有 zero 规则)。 - 新增 XlsCreateChart Delphi demo,位于
Demo/Delphi/XlsCreateChart/,创建两 sheet workbook:Data 工作表 4 行 (Region, Sales) + Chart1 柱状图 sheet,series 绑定Data!$A$2:$A$5/Data!$B$2:$B$5作 Categories / Values。这个 demo 永久替代了 v2.47.0 — v2.48.5 期间放在仓库根的临时chart_phase2_demo.xls(根目录文件已删除),新 demo 把输出写在自己的 .exe 目录旁边。 - 已知未解:v2.48.6 的 wire 格式下,Excel 仍然把 X 轴 categories 标签画成 0,legend 仍 fallback 到拼接 categories 文本(而不是用 BRAI id=2 PTG tStr literal
'Q1 Sales')。这是真实的 wire 格式缺口,需要拿一个 Excel 自己保存的 reference 柱状图做字节比对才能修 —— 标记为 follow-up。4 柱的 plot area 本身渲染正确(高度 100/150/200/175 与 Values 匹配)。
版本 2.48.5
- BIFF8 chart series 记录现在在 Excel 中正确渲染。v2.47.0 接通了 Categories / Values 范围的
tArea3D绑定,但 Excel 仍把 X 轴标签全画成0,把拼接的类别文本("North South East West")同时当 legend 和自动标题,而不是用户传入的 series Name。两项修正恢复了预期效果: SERIES记录的sdtX字段从1改为4(text categories)。[MS-XLS] §2.4.252 只写了1(dates)和3(BIFF7 sequence),但 Excel 自己保存的柱状/条形/折线 chart 文件对文本类别一律写4(对应 Apache POI 的CATEGORY_DATA_TYPE_TEXT常量)。sdtX=1让 Excel 把'North'/'South'当数字解析失败 → 落回 0;改成sdtX=4后文本标签可直接显示。此前的 wire format 也违反了 spec 规定的 "sdtX=1时cValx必须为零"。- 当用户传入 literal series Name 时,会在 SERIES BEGIN/END 块内(BRAI 簇之后、
DataFormat之前)写一条SERIESTEXT($100D)记录。Phase 2 前半段的 BRAI id=2 + PTGtStr方式保留以求 spec 完整,但 Excel 实际是从SERIESTEXT拿 legend 标签和自动标题;只有 BRAI 变体时 Excel 会 fallback 到拼接类别文本。修正后 legend 显示真实 Name(如'Q1 Sales'),空 chart title 不会再被类别文本污染。 - 升级建议:v2.42.0 — v2.47.0 写出的 chart sheet 在 Excel 仍能打开但渲染表现如上。用 v2.48.5+ 重新保存即可得到修正的 wire 格式;
AddChartSheetAPI 不变,同样的调用现在就能产出正确的 chart。
版本 2.48.4
- BIFF8 CFEX ($087B) emit 退役。HotXLS 不再在每条 CF12 ($087A) 之后写配对的 CFEX —— 所有 Data Bar / Color Scale / Icon Set 配置现在都内嵌在 CF12 的 kind tail(v2.48.1 — v2.48.3)。HotXLS 写出的 .xls 文件更小,且与 Excel 自身输出完全一致(Excel 保存的样本如
poi_ConditionalFormattingSamples.xls里 CFEX 记录数为 0)。Apache POI / NPOI 一直不读 CFEX,所以这是纯简化,没有可读性损失。 - BIFF8 CF12 读路径现在直接从 CF12 kind tail 解析配置,不再回退到 CFEX。
ParseCfEx成为 no-op;lxRead 对 $087B 的 dispatch 入口保留以保证 HotXLS v2.34..v2.47 写出的文件不会崩溃,但 CFEX 内容被忽略(这些文件 CF12 header 也是 v2.48.0 前的旧布局,无法正确 round-trip —— 需要通过 Excel 或 HotXLS v2.48.x 重新打开保存做迁移)。 - 本版完成 Gap #6 wire-format 重写的 5 个 PATCH(v2.48.0 header + v2.48.1 data_bar + v2.48.2 color_gradient + v2.48.3 multistate + v2.48.4 CFEX retire)。HotXLS 写出的 Excel 2007+ 条件格式记录现在与 Excel 自身的 wire format 字节级一致(除 formula 内容外),可被 Apache POI / NPOI 及任何符合 spec 的 BIFF8 reader 正确解析。
版本 2.48.3
- BIFF8 CF12 ($087A) 的 Icon Set 规则现在内嵌 NPOI 兼容的
multistate子记录,使 Apache POI / NPOI 可直接从 CF12 读出图标家族、每个 stop 的阈值、reverse / show-icon-only 标志,不再依赖遗留 CFEX 记录。字节布局完全匹配 NPOIIconMultiStateFormatting.Serialize():reserved(2) + reserved(1) + num(1) + iconSet.id(1) + options(1)+ 各 stop 的IconMultiStateThreshold(cfvo + equals byte + 4 字节 reserved)。 - HotXLS
TXLSIconSetType的 0..16 值与 NPOIIconSetid 枚举 1:1 对应(3Arrows / 3TrafficLights1 / 4RedToBlack / 5Quarters 等),既有使用 icon-set 常量的用户代码 round-trip 不变。ShowOnly置 options bit 0(iconOnly),Reverse置 bit 2。 - 默认每个 stop 的阈值(HotXLS 用
cfvPercent等分值:3-icon=0/33/67, 4-icon=0/25/50/75, 5-icon=0/20/40/60/80)写为 NPOI RangeTypePERCENT(4)+ value Double + equals byte(暂固定EQUALS_INCLUDE=1)。本版完成 Gap #6 CF12 重写的所有 kind tail;CFEX emit 退役由 v2.48.4 完成。
版本 2.48.2
- BIFF8 CF12 ($087A) 的 2-stop / 3-stop Color Scale 规则现在内嵌 NPOI 兼容的
color_gradient子记录,使 Apache POI / NPOI 可直接从 CF12 读出每个 stop 的阈值 + 颜色 + 插值位置,不再依赖遗留 CFEX 记录。字节布局完全匹配 NPOIColorGradientFormatting.Serialize():reserved(2) + reserved(1) + numI(1) + numG(1) + options(1)+ 各 stop 的ColorGradientThreshold(cfvo + position 8 字节 Double)+ 各 stop 的step + ExtendedColor。 - Stop 位置使用 NPOI 公式
step = 1 / (N-1),所以 3-stop ColorScale 是 0.0 / 0.5 / 1.0,2-stop 是 0.0 / 1.0。每个 stop 的颜色(RGB 或SetThemeColor设置的主题色)通过与 v2.48.1 Data Bar 相同的 ExtendedColor 块写入。 - 3-stop ColorScale 默认 kind(cfvMinOfRange / cfvPercentile=50 / cfvMaxOfRange)映射到 NPOI RangeType
MIN(2) / PERCENTILE(5) / MAX(3);中间 stop 的 value(50.0 Double)与各 stop position 已与poi_ConditionalFormattingSamples.xlsrecord 215 字节对照在测试套中验证。
版本 2.48.1
- BIFF8 CF12 ($087A) Data Bar 规则现在内嵌 NPOI 兼容的
data_bar子记录(在template_params后追加 28 字节),使 Apache POI / NPOI 能直接从 CF12 解出条形颜色、min/max 阈值和百分比长度边界,不再需要查询遗留的 CFEX 记录(POI 完全不读 CFEX)。字节布局完全匹配 NPOIDataBarFormatting.Serialize():reserved1(2)+reserved2(1)+options(1)+percentMin(1)+percentMax(1)+ ExtendedColor(16) + ThresholdMin/Max。 - HotXLS 条形颜色(BGR
LongWord)以type=RGB写入 ExtendedColor 块;通过SetThemeColor设置主题色的 Data Bar 写为type=THEMED+ themeIndex + tint。MinLength/MaxLength默认 10% / 90%(可通过 spec 对象调整),与 Excel 标准 Data Bar 外观一致。 - Color Scale 与 Icon Set 子类的尾部(v2.48.2 — v2.48.3)以及 CFEX 退役(v2.48.4)尚未完成;本版只完成 Data Bar 这一支 Gap #6 CF12 重写。本 PATCH 建立在 v2.48.0 的 header 重写之上,详见 v2.48.0 条目。
版本 2.48.0
- BIFF8 CF12 ($087A) 记录的 header 字段布局按 NPOI
CFRule12Record.serialize()和 Excel 实际保存的字节重写。之前的布局把ipriority/iTemplate/grbit/parms紧接在cce2之后、把cbdxf当成 2 字节长度字段;Excel 实际上在 formula tokens 之前写的是ext_formatting_length(4)+ 可选SerializeFormattingBlockheader,formula tokens 之后才是formula_scale/ext_opts/priority/template_type+ 长度前缀的template_params块。 - HotXLS 写出的 CF12 现在 header 部分与
poi_ConditionalFormattingSamples.xls第 152 — 215 条记录字节对齐(data_bar / color_gradient / multistate 各子类的尾部布局还要等 v2.48.1 — v2.48.3 加上;与 CF12 配对的 CFEX 本版仍照旧 emit,到 v2.48.4 才退役)。本次重写的动机请参考 v2.47.1 的 CONDFMT12 兄弟修复条目。 - HotXLS 之前在每条 CF12 末尾附加的 2 字节
nID(spec 里根本没有这个字段)已删除 —— 规则身份由父 CONDFMT12 记录承载。v2.34.0 — v2.47.1 写出的 .xls 文件建议通过 v2.48.0 重新打开保存以重写 CF12 记录。
版本 2.47.1
- BIFF8 CONDFMT12 ($0879) 记录的 wire 格式更正以匹配 Excel 保存的文件。之前的实现按早期 spec 草稿把 8 字节关联范围当作 FtrHeader 内的 "reserved",并在
numCF之前插入一个不存在的 4 字节 Reserved 字段;Excel 保存的 .xls 实际上把 FtrHeader 那 8 字节填为规则的关联单元格范围,且没有 Reserved 字段,所以 HotXLS 输出文件错位 4 字节 + 范围槽全 0。参考 dump 来自poi_ConditionalFormattingSamples.xls(Apache POI 测试 fixture)record 152,现在 HotXLS 输出与之逐字节一致。 - 具体修复:
StoreCondFmt12Header现在按rt(2) + grbitFrt(2) + associatedRange(8)写 FtrHeader,然后按numCF(2) + needRecalcAndId(2,位打包) + enclosingRange(8) + cref(2) + sqref 数组写 body。固定字节数从 30 降为 26(移除 Reserved 4)。ParseCondFmt12对应同步按修正后偏移读取。 - v2.34.0 — v2.47.0 写出的 HotXLS .xls 文件应该用 v2.47.1 重新打开保存以修复其 CONDFMT12 记录。在版本升级之间已经被 Excel round-trip 过的文件不受影响 —— Excel 会按自己的正确 layout 重写记录。
版本 2.47.0
- BIFF8 chart sheet 创建现在把 真实数据范围 绑定到 series。传给 6 参数
AddChartSheet重载的Categories与ValuesA1 字符串(例如'Data!$A$2:$A$5')被编译成tArea3DPTG token 写进 series 的BRAI id=0(categories)与BRAI id=1(values)记录。Excel 打开 .xls 现在在 plot area 渲染真实数据点,不再是 v2.42.0 那个空白占位图表。 - Sheet 名解析 + EXTERNSHEET 注册自动完成:解析器在 workbook 中查找命名的 sheet,如果还没有 XTI 项则自动注册一项,再把对应的 0-based
ixti写到 PtgArea3d 主体。重新保存时 chart 记录会经过公式编译器重新序列化,ixti与最终 EXTERNSHEET 顺序保持一致。 - 支持的范围形式:
Sheet1!$A$2:$A$5(绝对)、Sheet1!A2:A5(相对标记被容忍 —— chart series 一律以绝对地址存)、'My Sheet'!$A$1:$B$5(含空格的 sheet 名用单引号包裹)、单 cell 引用如Sheet1!$A$1(退化为 1×1 PtgArea3d)。Series data point 数量(cValx/cValy)现在按 area 维度自动推算,不再固定为零。 - 不支持的引用形式会静默 fallback 到 v2.41.0 风格的
cce=0占位 BRAI,让 chart 仍能被 Excel 打开:跨 workbook 引用([Book2.xls]Sheet1!...)、命名范围(Sheet1!ProfitColumn)、缺失!sheet 前缀的引用、指向 chart sheet 自身的引用。这些被推迟的 case 留作后续 phase。 - 本次完成 Roadmap #10 Phase 2(柱状图端到端)。Series 标签(Phase 2 前半段,v2.42.0)+ Series 范围绑定(本次 release)合并后,
AddChartSheet创建的柱状图能在 Excel 中显示完整图例与真实数据,无需事后处理。
版本 2.46.0
- BIFF8 端的差异 XF(DXF)解码器现在解析 xclrType=1(索引调色板)颜色,按标准 Excel 2003 64 色调色板查找。之前索引颜色 fallthrough 到 RGB 路径,icv 字节被误读为 RGB 一部分,产生无意义颜色(通常深灰);Excel 保存的 .xls 文件中 CF12 DXF 块使用索引颜色(而非 RGB 或 theme)的现在 round-trip 时呈现合理视觉颜色。
- 查找使用 HotXLS 内置的 Excel 2003 默认调色板 —— icv 0..7 是 8 个系统色(黑 / 白 / 红 / 绿 / 蓝 / 黄 / 洋红 / 青),icv 8..15 镜像系统色,icv 16..63 是标准可定制默认值(深色变种、浅色 tint、棕色、橙色、紫色等)。越界 icv fallback 到黑色 ($000000)。
- BIFF8 PALETTE 记录(rt=$0092)的工作簿定制 不 被查阅 —— 定制了用户可改色板槽(8..63)的工作簿,其 CF12 DXF 索引颜色解析为默认值而非定制值。对大多数使用默认调色板的 Excel 文件正确;对自定义调色板文件视觉颜色可能略有偏差,直到后续 release 加入完整 PALETTE 处理。
- xclrType=0(auto)与 xclrType=2(RGB)路径不变 —— auto 仍然变为 RGB 0(黑),RGB 仍然直接解码 xclrValue 4 字节 BGR LongWord。只修复了之前破损的 xclrType=1 路径。
版本 2.45.0
- 条件格式规则现在在 XLSX
<cfRule priority="N"/>与 BIFF8 CF12ipriority字段两端 round-trip priority 属性。之前每条规则在 save 时按集合 index 顺序自动分配 priority,Excel 保存的文件读入时 priority 被忽略;现在用户设置的 priority 在 load-edit-save 循环中两端都能保留。 TCondFormatRule(BIFF8 端)和TXLSXConditionalFormat(XLSX 端)新增Priority属性。默认为 0,保留现有的按 index 自动行为;设置为正整数则 pin 该 priority,覆盖自动分配。- Priority 控制多规则叠加 —— 当多条规则覆盖同一 range(例如 Data Bar + CellIs 高亮 + Icon Set),Excel 按 priority 顺序应用(数字越小越先)。Round-trip priority 意味着 HotXLS 编辑后的工作簿保留用户预期的渲染顺序,而不是按集合迭代顺序重新计算。
- 不动
Priority的调用方行为不变:XLSX 写出端继续按集合顺序发射priority="1"、"2"、"3"…,BIFF8 CF12 写出端继续发射ipriority=1。读取路径在 wire 值存在时填充Priority;忽略该属性的旧代码继续向后兼容。
版本 2.44.0
- 图标集条件格式规则在 XLSX 端支持每 stop 图标覆盖。3 / 4 / 5 stops 图标集中每个 stop 都可以脱离家族默认,从 17 个 Excel 2007 内置图标家族中任选一个图标显示,通过 icon set name + icon id 标识。涉及的 OOXML 元素是
<cfIcon iconSet="OtherSet" iconId="N"/>,每个被覆盖的 stop 在<iconSet>body 内发射一个。 TXLSIconSetSpec新增方法将 stop 切换到覆盖模式:SetIconOverride(stopIndex, OverrideSet, IconId)与ClearIconOverride(stopIndex)。只读属性HasIconOverride[i]、IconOverrideSet[i]、IconOverrideId[i]暴露每 stop 的覆盖状态用于检查与 round-trip。- XLSX 写出端只为调用过
SetIconOverride的 stop 发射<cfIcon>子元素;未覆盖的 stop 保持家族默认(不发射 cfIcon)。读取端按位置解析iconSetbody 内的<cfIcon>元素,应用到对应 stop。 - 已知限制:BIFF8(.xls)CFEX wire 格式没有每 stop 图标覆盖的字段,所以含覆盖的图标集规则保存到 .xls 时所有 stop 渲染为家族默认(BIFF8 读取端不会看到覆盖信息)。workbook 级别的图标家族校验不做强制 —— 传入超出覆盖家族 icon 数量的 iconId 原样保留,但 Excel 渲染时可能 fallback 到默认图标。
版本 2.43.0
- XLSX(.xlsx)条件格式规则现在在 Data Bar 和 Color Scale 的
<color>元素上 round-trip 主题色引用。之前写出端只发射<color rgb="FFRRGGBB"/>,读取端忽略theme/tint属性;现在双端保留主题色调色板索引和可选的 tint,所以"accent-2 浅化 50%"这种样式经过 Excel 打开 / HotXLS 编辑 / Excel 重新打开 round-trip 时不再被冻结为固定 RGB。 TXLSDataBarSpec与TXLSCfValue(ColorScale stops 使用)新增方法将槽切换到主题模式:SetThemeColor(themeId, tint)和ClearThemeColor。只读属性IsThemeColor、ThemeColorId、ThemeColorTint暴露激活模式。Tint 是 [-1.0, +1.0] 范围的 single —— 负值变暗、正值变浅。- XLSX 写出端在
Tint恰好为 0.0 时发射<color theme="N"/>,非零时发射<color theme="N" tint="0.5"/>,与 Excel 自身的"最短形式"输出一致。读取端两种属性组合都解析,无theme/tint属性时兜底到现有rgb=路径。 - 默认行为不变:用已有 RGB-only
AddCondFormatDataBar/AddCondFormatColorScale*入口创建的规则继续发射与之前完全相同的<color rgb="..."/>。主题模式纯属可选 opt-in,需要通过返回 spec 对象上的新SetThemeColorsetter 调用。 - 已知限制:BIFF8(.xls)CFEX 仍然只携带 RGB 颜色;workbook 主题色板解析(theme1.xml 解析)仍超出范围;
iconSet规则不携带<color>元素,所以主题模式扩展对它们没影响。
版本 2.42.0
- BIFF8 图表 sheet 创建 API 新增第 5 个
AddChartSheet重载,接受TXLSChartSeriesInfo数组(每项含Name、Categories、Values)。每个非空的Name会通过 series-nameBRAI(id=2)上的tStrPTG token 写成字面 series 标签。Excel 在图例和 series 选择器里使用这个标签,所以多 series 图表现在会有具体的 series 名称,而不是默认的 "Series1 / Series2" 占位符。 TXLSChartSeriesInfo与TXLSChartType一起从lxHandle重新导出,调用方无需直接 importlxChartBuilder。- 这是 Roadmap #10 Phase 2(column chart 端到端)的前半段。Series 名称路径已经接通;类别和数值数据绑定(把
Categories/Values字符串编译成真实的tArea3D单元格区域引用并填入 BRAI)目前仍是占位 —— 这两个字段在 API 上接受输入,但还没被写进 chart substream。后续 release 会通过公式编译器和 EXTERNSHEET 引用表完成 Phase 2 的下半段。
版本 2.41.0
- HotXLS 新增BIFF8 图表 sheet 的 API 创建路径。
Sheets上新增的AddChartSheet系列重载会向保存的 .xls 文件写入完整的图表 substream —— 之前图表 sheet 只能通过 load-save 不透明地保留。4 个重载覆盖常见入口:仅名称 / 名称 + 图表类型 / + 标题 / + 类别轴标题 + 数值轴标题。返回的IXLSWorksheet出现在Sheets集合中,保存时写出图表 sheet 的 boundsheet 项,Excel 把它当成图表 tab 打开。 - 新增
TXLSChartType枚举选择图表种类:xlsChartTypeColumn、xlsChartTypeBar、xlsChartTypeLine、xlsChartTypePie。该枚举从lxHandle重新导出,调用方无需直接 import chart-builder 单元。 - 生成的图表 substream 覆盖 spec 要求的 BIFF8 框架 —— BOF(dt=$0020)、Chart / PlotGrowth / Frame / Series / SheetProperties / AxesUsed / AxisParent(POS + 类别轴 + 数值轴 + PlotArea + Frame + ChartFormat + 图表类型记录 + ChartFormatLink + Legend)、EOF —— 让 Excel 识别为请求种类的真实图表 tab。已有的图表 sheet 通过
TXLSCustomChartround-trip 行为不变。 - 这是 Roadmap #10(CHART substream —— BIFF8 audit 中最大的项)的首阶段。Phase 1 提供框架与 API 表面,后续阶段在此基础上层叠 Series 数据绑定、坐标轴标题、各图表类型的精细格式。
- 限制:新建的图表 sheet 渲染为请求种类的空默认图表。Series 数据绑定(将图表连接到实际单元格区域)、标题文本填充、各图表类型格式细节(柱间距 / 柱重叠 / 饼图空心比 / 数据标记样式)留待后续 phase。Excel 中保存与重新打开会保留图表 sheet 的存在与种类,但暂未保留用户提供的数据。
版本 2.40.0
Demo/Delphi/XlsCondFormat12/下新增 XlsCondFormat12 Delphi demo 工程,端到端演示 v2.34.0+ 条件格式扩展 API。3 个按钮分别生成CondFormat12.xls(BIFF8 后端)、CondFormat12.xlsx(XLSX 后端)或同时两个,便于对比。每个输出 sheet 都携带相同的 4 种规则种类 —— 数据条、3 色色阶、图标集(3 箭头)、2 色色阶 —— 覆盖 10 行数据,便于在 Excel 中打开并目视核对两端的渲染表现。- BIFF8 路径额外演示 v2.35.0 DXF 样式覆盖:数据条规则附加白色加粗字体色,使深色条上的文字保持可读。
- 新增 DUnitX 测试套
Tests/Delphi/HotXLS.CondFormat12Tests.pas覆盖 CF12 系列的 10 个 round-trip 与 API 表面场景:BIFF8 端 4 种规则的 round-trip、DXF Style 的 RGB 颜色 / theme 颜色 / 字体粗体斜体下划线 flag 的 round-trip、XLSX 端 Data Bar / 3-color scale / Icon Set + ShowOnly round-trip。测试套已挂到HotXLSDelphiTests.dpr与匹配的.dproj,既有 CI 跑自动捡到。 - 为支持测试套,
TCondFormat新增 2 个公开访问器:RuleCount与Rule(I),调用方读入后可以遍历规则列表,不再依赖此前为私有的 FRules 字段。
版本 2.39.0
- 条件格式规则上的差异 XF(DXF)样式覆盖现在除了 RGB 模式之外,还支持主题色编码。三个颜色槽 —— 字体色、填充背景色、填充前景色 —— 每个都可以设置为基于 workbook 主题色索引加 tint 值,所以"accent-2 浅化 50%"这种样式可以 round-trip 而不被冻结成具体 RGB 值。
TXLSDxfStyle新增 3 个方法将槽切换到 theme 模式:SetFontColorTheme(themeId, tint)、SetFillBgColorTheme(themeId, tint)、SetFillFgColorTheme(themeId, tint)。Tint 是 [-1.0, +1.0] 范围的单精度浮点 —— 负值变暗、正值变浅、0.0 保持基础色。对应已有的SetXxxColor(rgb)保持 RGB 模式;两种模式在同一槽上互斥,最后调用的赢。- 通过新增的
XxxColorIsTheme/XxxColorThemeId/XxxColorThemeTint只读属性查询激活模式。HasXxxColor在两种模式下都返回 True;旧的只检查HasXxxColor+ 读XxxColor的调用方继续工作(theme 模式槽显示为颜色 0,是降级而非崩溃)。 - BIFF8 wire 格式按标准 XFProp Colour layout:RGB 写
xclrType=2+ 4 字节 BGR LongWord(已有 v2.35.0 行为);theme 模式写xclrType=3+ 2 字节有符号 tint × 32767 + 4 字节主题索引(新)。DXF blob 解码器对称分派 —— 读入的 Excel 保存文件中 CF12 DXF 块使用 theme color 的现在通过新属性暴露 theme id 和 tint。 - 已知限制:theme 模式 round-trip 仅在 BIFF8(.xls)端支持 —— XLSX(.xlsx)端仍然只发射和读取
<color rgb="..."/>,忽略theme/tint属性(计划后续 release 配合 workbook 主题色板支持一并补齐)。
版本 2.38.0
- XLSX(.xlsx)读取端现在识别 Excel 2007+ 条件格式扩展规则 —— 数据条、色阶(2 stop 与 3 stop,按 cfvo 数自动判定)、图标集 —— 并填充对应的
TXLSXConditionalFormat对象,用户代码可以检查并 round-trip 这些规则。之前 Excel 保存的含这三种规则类型的 .xlsx 工作簿被静默丢弃。 - 读取端解析 OOXML
<cfRule type="dataBar|colorScale|iconSet">外壳以及内部的<dataBar>/<colorScale>/<iconSet>主体,遍历子级<cfvo>取回每个阈值的 type(num / min / max / percent / percentile / formula / autoMin / autoMax)与 val,并通过<color>取回数据条颜色或色阶每 stop 的颜色。 - 图标集规则 round-trip 保留
iconSet系列名(Excel 2007 基线的 17 套)、reverse标志和showValue标志(映射到ShowOnly)。 - 从 OOXML
rgb="AARRGGBB"属性解析的颜色值被转换为与写出 API 一致的 BGRLongWord约定(R 在低字节,与 VCLTColor和 BIFF8LongRGB匹配),所以 load-edit-save round-trip 完全保留视觉颜色。 - 已有的 XLSX
<cfRule type="cellIs">处理逻辑不变;仅当type属性指定新规则种类时才走新分派,其它情况兜底到 cell-value 路径。 - 已知限制:theme 颜色引用(OOXML
<color theme="N" tint="0.5"/>)当前读为 0 而非根据 workbook theme 色板解析;图标集的iconId每 stop 覆盖暂未捕获;<cfRule>的priority属性读取时被忽略(规则按解析顺序保留)。
版本 2.37.0
- BIFF8 CFEX 记录格式现在承载完整的每 stop cfvo 阵列(kind + value 字符串 + color,符合 [MS-XLS] cfvo 语义),不再只是 bar / stop 颜色。数据条规则现在持久化 min / max 阈值的种类与值,色阶持久化每个 stop 的 kind + value + color 组合,图标集持久化每个阈值的 kind + value 以及 reverse / showOnly 标志。
- CFEX 写入新增 version 标志字节(ver=1),让 v2.34.0 旧版 HotXLS 读取器静默回退到 legacy minimal 解释。v2.37.0 读取器同样识别 ver=0 旧版生成的记录,所以混版本安装的双向 round-trip 在旧格式所携带的 kind/color 字段上都能工作。
- 读取端现在检测同一 range 上的 mixed CONDFMT + CONDFMT12 条目 —— 这是 Excel 保存文件中常见的模式:旧单元格值备份与新 Data Bar / Color Scale / Icon Set 规则覆盖完全相同的 sqref。较旧的 CONDFMT 条目通过
TCondFormat新增的IsShadowed属性标记,方便迭代条件格式集合的用户代码跳过重复项。写出端在保存时继续发射两族记录以保持 Excel 2003 ↔ Excel 2007+ 跨版本兼容性。 TCondFormat新增TotalRange属性暴露原本私有的合并 extent 范围;对实现自定义 dedup、range 查询或 shadow 检查模式的用户有用。- 已知限制:shadow 检测以精确边界框匹配(row1/col1/row2/col2 相等)为界。CONDFMT 覆盖略不同 sqref 子集的混合条目不会被 dedup;ColorScale 完整 cfvo round-trip 保留 8 个标准 kind 值(num/min/max/percent/percentile/formula/autoMin/autoMax)但不 round-trip Excel 的主题色 tint 元数据。
版本 2.36.0
- XLSX(.xlsx)输出端现在支持 Excel 2007+ 的三种条件格式扩展规则 — 数据条、色阶(2-stop 和 3-stop)、图标集 —— 让 XLSX 后端与 v2.34.0 BIFF8(.xls)后端保持对等。
TXLSXWorksheet新增 4 个公开方法对齐 XLS 端 API:AddCondFormatDataBar、AddCondFormatColorScale2、AddCondFormatColorScale3、AddCondFormatIconSet。 - 保存的 .xlsx 文件现在按每种规则类型发射相应的 OOXML
<conditionalFormatting>子结构:数据条用<cfRule type="dataBar"><dataBar><cfvo/><cfvo/><color/>;色阶用<cfRule type="colorScale"><colorScale>含 2 或 3 个 cfvo + color stop;图标集用<cfRule type="iconSet"><iconSet iconSet="...">含对应数量的 cfvo。 - 内置图标集名称映射覆盖 XLS 端支持的同样 17 种 Excel 2007 基线集(3Arrows / 3Flags / 3TrafficLights1 / 3Signs / 3Symbols / 3Symbols2 / 4Arrows / 4ArrowsGray / 4RedToBlack / 4Rating / 4TrafficLights / 5Arrows / 5ArrowsGray / 5Rating / 5Quarters),作为标准 OOXML
iconSet属性字符串输出。 - 阈值类型与颜色值采用与 XLS 端 API 相同的枚举与颜色约定 — 同样的
TXLSCfValueKind对应 num / min / max / percent / percentile / formula,同样的 Delphi BGRLongWord颜色格式。已有的 XLSX 单元格值AddConditionalFormat调用行为完全一致(无回归)。 - 已知限制:暂未发射 theme color 编码(OOXML
<color>仅使用rgbARGB 字符串属性);图标集ShowOnly为真时设showValue="0",但每个 stop 的iconId覆盖暂未支持。XLSX 读取端识别 Excel 创建的数据条 / 色阶 / 图标集规则仍延后 —— 本版本只接通写出端。
版本 2.35.1
- BIFF8 读取端现在会把 CF12 规则携带的差异 XF(DXF)字节流回解码到规则的
TXLSDxfStyle属性包,同时保留原始字节于DxfBlob中。读取一个 Excel 保存的、含样式化的数据条 / 色阶 / 图标集规则的工作簿时,可以通过每个Rule.Style上的HasXxx+ 值对直接拿到字体色、填充色、粗体 / 斜体 / 下划线、数字格式 id。 - Round-trip 行为:load-edit-save 循环现在会反映加载后对
Rule.Style的任何修改。如果用户读取一个工作簿、修改Rule.Style.SetFontColor后保存,新颜色会生效;如果用户不动 Style,保存的文件会携带原始相同的覆盖项。 - DXF 中遇到未识别的
xfPropType会被跳过而不是拒绝读取,因此使用了本版本尚未识别的属性类型的更新版 Excel 文件仍能正常加载(原始字节仍保留在DxfBlob中供检查或后续 round-trip 支持)。
版本 2.35.0
- 条件格式规则现在可以携带一份 差异 XF(DXF)样式覆盖,让 CF12 规则在 Excel 中触发时可以改变单元格的字体颜色、填充、字体粗细、斜体、下划线或数字格式而不修改基础 XF。这份覆盖通过每个
TCondFormatRule上的新增TXLSDxfStyle属性暴露,调用现有的AddCondFormatDataBar/AddCondFormatColorScale*/AddCondFormatIconSet创建出规则之后就能访问。 - 本版本支持的样式覆盖项:字体颜色、填充背景色、填充前景色、填充图案、字体粗体、字体斜体、字体下划线样式、内置数字格式 id。每项都有配对的
HasXxx标志 —— 只有通过SetXxx显式设过的属性才会写入 BIFF8 文件。 - BIFF8 写出端在规则的 Style 至少设置过一项覆盖时,在 CF12 记录尾部追加非空的 DXF 块。DXF 块采用公开 XFProp 阵列格式(cxfp + 每属性的 类型 / 大小 / 数据 三元组),规则触发时 Excel 能拾取样式变化。
- BIFF8 读取端把从 Excel 文件读到的原始 DXF 字节保留到规则的
DxfBlob属性,因此 load-edit-save round-trip 不再静默丢失 CF12 规则携带的单元格样式。把原始字节回解码进TXLSDxfStyle属性包计划放到后续 release。 - 未启用 Style 的规则行为完全不变 —— 写出
cbdxf = 0,与 v2.34.0 一致,现有的数据条 / 色阶 / 图标集规则渲染与之前完全相同。 - 已知限制:DXF 的 theme color 编码暂不支持(只 RGB);边框覆盖、渐变停点本版本未纳入;XFProp 值 blob 的字节序遵循公开 [MS-XLS] 说明,可能需要对照 BiffView 做小幅调整以确保 Excel 完整 round-trip。XLSX 端三种新规则类型的对应实现仍延后。
版本 2.34.0
- 工作表新增 Excel 2007+ 扩展条件格式公开 API:
AddCondFormatDataBar(数据条)、AddCondFormatColorScale2/AddCondFormatColorScale3(双色 / 三色色阶)以及AddCondFormatIconSet(图标集)。每个方法接收"A1:A10"形式的 sqref 区域以及对应类型特有的参数(条颜色、渐变停点颜色或图标集类型),返回创建出的规则对象。 - BIFF8(.xls)写出端在原有的 CONDFMT / CF 记录之外,新增发射对应的 CONDFMT12 / CF12 / CFEX 记录族,使通过新 API 创建的数据条、双 / 三色色阶、图标集规则得以持久化到磁盘。
- BIFF8 读取端识别传入的 CONDFMT12 / CF12 / CFEX 记录,并通过相同的内存规则模型暴露——Excel 创建的含扩展规则的 .xls 文件不再在 Open 时被静默丢弃。
- 内置图标集目录覆盖 Excel 2007 基线的 17 种图标集:3 箭头 / 3 旗 / 3 交通灯 / 3 标志 / 3 符号系列、4 箭头 / 4 评级 / 4 交通灯,以及 5 箭头 / 5 评级 / 5 季度系列,可通过
TXLSIconSetType枚举选择。 - 数据条上下界、色阶 / 图标集停点的阈值类型支持 数值、区域最小 / 最大、百分比、百分位 和 公式,与 Excel 的 cfvo 种类一致。
- 原有单元格值类型的条件格式行为不变,只是新增了 API 与新的 BIFF8 记录处理。
- 本版本已知限制:XLSX 端尚未接入这三种新规则类型的输出(已有 XLSX 单元格值规则不受影响);CF12 上的差异 XF 样式块当前发射为空,因此 Excel 渲染数据条与色阶时可能使用默认颜色而不是 API 指定的颜色;CFEX 中每个停点只携带颜色,不携带种类 / 数值组合。这些 gap 计划在 v2.34.x / v2.35.x 后续版本中补齐,同时配套提供 demo 工程与 Excel 渲染验证。
版本 2.33.3
Demo/Delphi/XlsTables/下新增 XlsTables Delphi 演示工程,端到端展示 BIFF8 Tables(ListObject)写出能力。Demo 生成的SalesTable.xls包含一张含 4 列示例销售数据(Region / Product / Quarter / Revenue)的工作表,用Sheet.AddTable('SalesTable', 'A1:D10', headers)把 A1:D10 绑成一个 Table。在 Excel 中打开生成的 .xls,可看到 Table 列下拉、行交替条纹底色,以及"名称框"里的 SalesTable 结构化引用名。- 该 demo 是采用 v2.33.0 新增
AddTableAPI 的最简端到端范例:设置StyleName = 'TableStyleMedium2'和ShowRowStripes = True,填一行表头 + 九行数据,SaveAs一次完成写出。输出文件落在可执行文件旁,并提供"打开输出目录"按钮便于查看。 - 编译基础设施无需调整:现有
build-Win32-Demo.cmd通过for /r Demo *.dpr扫描自动识别XlsTables.dpr,不需要改动任何 build 脚本或 .cbproj/.dproj 配置。
版本 2.33.2
- BIFF8(.xls)
SaveAs现在会在同一 sheet 上的某个 Table 完全覆盖 autofilter 区域时,跳过独立的 sheet 级AUTOFILTERINFO/AUTOFILTER记录($009D / $009E)的发射。Excel 在 Table 对象内部已经内嵌了 autofilter 下拉,再发射一个覆盖相同区域的 sheet 级 autofilter 会触发 Office File Validation 拒绝该文件。这一处理与 XLSX 端 v2.29.4 的同类修复对齐。 - 覆盖检测是保守的:仅当 Table 的首行/末行/首列/末列分别包围 autofilter 区域的边界时,才视为"Table 覆盖 autofilter"。部分重叠(例如 autofilter 跨越 Table 下方额外行)保持原行为,仍然发射 sheet 级 autofilter,保护"在 Table 上方或旁边放置 filter"这类老工作流的兼容性。
- BIFF5 保存路径与不含 Table 的工作表不受影响——抑制检测仅在文件格式为 BIFF8 且工作表至少有一个 Table 时才运行。无公开 API 变更。
版本 2.33.1
- BIFF8(.xls)读取端现在能识别 v2.33.0 在写出端引入的共享特性表记录。打开一个由 Excel(或 HotXLS 自身)保存的、含一个或多个 ListObject/Table 的 .xls 文件时,工作表的
Tables集合会按解析到的 FEAT11($0872)记录填充对应的TXLSTable:从主 Ref8U 重建 Table 区域,恢复 Table id、name 与 displayName(若存在),并从配对的 LIST12($0877)记录里读出 styleName。此前这些记录被静默忽略,round-trip 时整个 Table 状态丢失。 - 共享的 FEATHEADR($0867)opcode 现在按其
Isf字段分发,不再统一交给保护解析器:Isf=2(增强保护)保留原行为;Isf=4(SharedList)被识别为该 sheet 含 Tables 的标记;Isf=3(SmartTags)以及其他值安全忽略。FEATHEADR11($0871)同样作为 Tables 标记静默确认。 - 读取端采用尽力解析、容错为先的策略:若 FEAT11 payload 损坏或来自 Excel 的不同字段布局,会优雅退化为至少恢复正确单元格区域的 Table,即使更靠后的字段(per-column id、结构化引用数据等)无法解析也不阻断读取。Sheet protection 的 round-trip 不变——Isf=2 payload offset 19 处的 options Word 仍按原方式读取。
版本 2.33.0
- BIFF8(.xls)工作表现在支持表对象(Excel ListObject)。在
IXLSWorksheet上调用Worksheet.AddTable(Name, Range, Columns),即可为单元格区域绑定一个命名 Table,例如Sheet.AddTable('SalesTable', 'A1:F9', HeaderList)。.xls 写出路径会发射 BIFF8 共享特性记录家族,标记该 sheet 含 Table:FEATHEADR($0867,Isf=4)、FEATHEADR11($0871)以及每个 Table 配对的 FEAT11($0872)+ LIST12($0877)。此前 XLS 端没有AddTable,工作表上设置的 Table 在SaveAs(xlExcel97)时被静默丢弃。 IXLSWorksheet新增公开 API:只读集合属性Tables: TXLSTables,以及AddTable方法。形态与 XLSX 端的TXLSXTable/TXLSXTables一致,因此应用层添加 Table 的代码可以做到与文件格式无关。TXLSTable提供Id、Name、DisplayName、Range、Columns、StyleName(默认'TableStyleMedium2')、ShowFirstColumn、ShowLastColumn、ShowRowStripes(默认 true)、ShowColumnStripes以及TotalsRowShown等属性。- 新增的 sheet 流记录在工作表 EOF 前、sheet protection 之后写出,且仅在文件格式为 BIFF8(
xlExcel97)时触发。没有 Table 的工作簿写出与此前**完全一致**——不发射 FEATHEADR、record stream 无任何变化、零开销。BIFF5 写出不受影响(Tables 是 BIFF8+ 概念)。 - Table id 在 SaveAs 时按 sheet 顺序自动分配(1..N),如调用方未显式设置;因此
AddTable后可保留Id默认值。默认 style 名'TableStyleMedium2'与 Excel 和 XLSX 端一致,跨格式表外观保持一致。 - v2.33.0 已知限制:尚未发射汇总行公式与结构化引用辅助范围;sheet 级
AUTOFILTERINFO与 Table 区域的冲突抑制留待后续版本;读取侧(把 Excel 写出的含 Table .xls 解析回Tables集合)同样留待后续。本 v1 写出路径产生的 Table 在 Excel 内自身 round-trip 时格式合规。
版本 2.32.1
- 修复了 v2.32.0 FILEPASS 写出端引入的编译错误。该错误使得在 RAD Studio 12+ 严格类型检查下库无法编译:
EncryptAllBlobs辅助函数把分散缓冲区声明为PByte(解析为lxHandle单元里的本地别名),而调用目标lxEncrypter.EncryptBlobData期望的是lxBLOB.PByte。这两个类型在底层都是^Byte,但 Delphi 在 E2010 严格类型检查下把它们视为不同类型。现已把缓冲区变量显式声明为lxBLOB.PByte,v2.32.0 的密码加密写出路径可在所有受支持的 RAD Studio 版本(12.0–37.0)下顺利编译。
版本 2.32.0
- 在
IXLSWorkbook上新增EncryptionPassword属性。调用SaveAs前设置非空密码,即可生成与 Excel 兼容的密码保护 .xls 文件:Excel、LibreOffice Calc 等 BIFF8 读取器打开时会弹出密码对话框,密码错误则拒绝访问。此前写出端会静默忽略密码设置,工作簿始终以明文形式写出。 - 写出路径在工作簿 BOF 之后立即写入 BIFF8 FILEPASS 记录($002F),并使用与读端相同的 RC4 算法(vMajor=1、vMinor=1,即 Excel 的"Office 97/2000 兼容"加密)对随后所有记录的 body 进行加密。16 字节 Salt 与 Verifier 由 Windows
CryptGenRandom生成而非 PascalRandom。每 1024 字节块边界处的派生密钥重置保持不变,大工作簿、SST CONTINUE 链以及多 sheet 流均能正确加密。 - 加密仅适用于 BIFF8(
xlExcel97)保存路径;BIFF5 路径仍以明文写出。EncryptionPassword默认为空字符串,保留原有的明文写出行为,未调用该 setter 的已有应用不受影响。 - 读取端:修复了
ParseFilePass中的隐藏 bug —— FILEPASS 之后的第一条记录 body(通常是 CODEPAGE)原先被错误地当作明文处理。修复后 HotXLS 自身写出的加密文件可经 HotXLS 完整往返,且来自 Excel 的加密文件 CODEPAGE 值不再变成乱码。 - 安全提示:BIFF8 RC4(vMajor=1/vMinor=1)使用 40 位密钥,按 2025 年标准已属可破解强度。本功能仅用于兼容 Excel 经典密码保护 UI,并非用于保护敏感数据机密性。如需实际安全性,请优先选择 XLSX + AES。
版本 2.31.0
- 在
IXLSWorkbook上新增UseSharedFormulas属性。设为True后,BIFF8 另存为时将公式模板相同的单元格自动合并为原生 SHRFMLA 记录($04BC),与 Microsoft Excel 的紧凑写出格式一致。如=A1*B1、=A2*B2……=A99*B99这类列公式将被自动归组,模板公式密集的工作表文件体积可减少 30–60%。 - 归组策略为列向连续模板匹配:仅对同列中连续行且 PTG 字节等效的公式单元格进行归组;数组公式单元格与合并单元格不参与归组。
- 默认值为
False,保持原有的逐单元格 FORMULA 记录写出行为不变。如需启用,在调用SaveAs前显式设置Workbook.UseSharedFormulas := True。 - 读取侧不受影响:HotXLS 始终正确读取 SHRFMLA 记录,经本功能写出的文件可被正常读回。版本号由 2.30.x 升至 2.31.0(MINOR bump),原因是新增了公开属性且 BIFF8 输出格式在启用时发生变化。
版本 2.30.6
- 修复了 C++Builder 示例在 RAD Studio 37.0 clang bcc32 编译器下的第四类编译错误:通过智能指针接口使用
->Borders[idx]->Prop访问边框属性时触发 E5843 错误("成员引用类型不是指针")。已将所有此类用法改为->Borders->Item[idx]->Prop,直接通过接口的索引属性访问。此修复涉及 ApiTour、ExportWithColoring、PurchaseOrder 和 QuickStart 示例,全部九个 C++Builder 示例项目现已完全兼容新 clang 编译器。
版本 2.30.5
- 全部九个 C++Builder 示例项目现已能够在 RAD Studio 37.0 的基于 clang 的 bcc32 编译器下成功编译。修复了三类编译错误:将
lxFormula的属性EOF改名为IsEof,消除其与 C 标准库stdio.h宏EOF的冲突;C++Builder 示例代码中的 XLS API 枚举常量(xlHAlignCenter、xlAround、xlMedium等)已全部加上Lxhandle::命名空间限定符,解决符号歧义;以及将所有 XLSX API 示例中的单元格赋值从OleVariant(...)改为Variant(...),因为TXLSXCell.Value类型为System::Variant,新的 clang 编译器拒绝从受保护基类OleVariant的隐式转换。
版本 2.30.4
- OrderCalc 示例程序(Delphi 采购订单样例)在原有 XLS、HTML、RTF 格式的基础上新增 XLSX 导出选项。在保存对话框中选择"Excel 2007+ 文件 (*.xlsx)"时,使用原生 TXLSXWorkbook API 写出采购订单,直接生成包含字体、填充、边框、对齐、数字格式和 Excel 公式的标准 XLSX 文件。
版本 2.30.3
- SaveXLSWorkbookAsXLSX(TDataToXLS.SaveAs 和 TGridToXLS.SaveAs 在目标文件名以 .xlsx 结尾时使用的转换桥)现在会将底层 XLS 工作簿的单元格背景填充颜色、字体颜色及字体样式属性(名称、大小、粗体、斜体)复制到 XLSX 输出。列宽——包括导出前手动设置的窄装饰列——也会被同步复制。此前仅传输单元格值和数字格式,导致 XLSX 输出无任何样式、所有列宽均为默认值,且刻意缩窄的装饰列会显示为过宽的空列。
版本 2.30.2
- 修正 XLS 读取侧的 round-trip bug:Outline.SummaryRow 方向在 Open 后翻转。WSBOOL 记录的 fRwSumsBelow flag(BIFF8 spec p278 byte 0 bit 6,mask $0040)意为"摘要行出现在明细 *下方*",但解析器原来在 bit set 时把 SummaryRow 设为 xlAbove(bit clear 时设为 xlBelow)—— 与 spec 完全相反。写出侧本来就是对的(xlBelow 时输出 $0040),所以打开含"摘要行在下方"的 Excel 文件再经 HotXLS 重存,outline 方向会被静默翻转为"在上方"。现在 parse 方向与 spec 和 writer 一致,outline 配置可正确 round-trip。fColSumsRight ($0080) 原本就处理正确,未改动。
版本 2.30.1
- XLS (BIFF8) 写入器现在在 workbook globals 段输出 INTERFACEHDR / INTERFACEEND / WRITEACCESS 三个 records,与 Microsoft Excel 原生记录布局对齐。原生 Excel 总在 CODEPAGE/DSF 与 WINDOW1 之间写这三个记录,更严格的 BIFF reader / Office File Validation 路径可能依赖。INTERFACEHDR 携带 code page(1200,UTF-16),INTERFACEEND 是空标记,WRITEACCESS 携带"最后保存者"用户名(当前硬编码为 "HotXLS",未来版本可能提升为 Workbook 属性)。生成的 XLS 文件现在更贴近 Excel 原生字节布局。
版本 2.30.0
- 新增经典 XLS 到 XLSX 的导出桥。TDataToXLS.SaveAs 和 TGridToXLS.SaveAs 现在可直接写出 .xlsx 文件名,同时保持原有 .xls、.html、.rtf 路径不变。
- 新增 XLS/XLSX 工作表视图 API。IXLSWorksheet.View 与 TXLSXWorksheet.View 支持普通视图、分页预览和页面布局视图,并在对应读写路径中保留设置。
- 新增经典工作簿兼容接口:IXLSWorkbook.SetCodePage 与 IXLSWorkbook.VBAProject。含 VBA storage 的工作簿现在可通过 TXLSVBAProject/TXLSVBAModule 查看模块名和源代码。
- TXLSXWorkbook 新增 ParsedVBAProject,可在 vbaProject.bin 有效时提供只读解析视图;原有 raw VbaProject 字节级往返行为保持不变。
- 新增可选 cxGridAddExcel 单元,用于 DevExpress cxGrid 导出场景。该单元不会加入默认 package,避免未安装 DevExpress 的环境构建失败。
- 修正 XLSX chart sheet 图表显示空白的问题:通过 AddChartSheet 添加的独立图表 sheet 在 Excel 中打开时图表区域是空白的(右上角短暂出现 3 个 chart 工具图标,点击后图标消失整个 sheet 变空)。原因是 chart sheet 的 drawing 用了 <xdr:twoCellAnchor> + xfrm cx=0/cy=0,而 chart sheet 没有 cell grid 让 twoCellAnchor 解析坐标,Excel fallback 到 xfrm 的 0×0 大小把图表 rendered 成 0 像素。chart sheet drawing 改用 <xdr:absoluteAnchor> + 9525000×6858000 EMU 默认尺寸(≈10×7.2 英寸),符合 ECMA-376-1 14.2.3.2 规定(chart sheet drawings 必须用 absoluteAnchor)。worksheet 上的 chart anchor 不变。
版本 2.29.4
- 修正 XLSX 打包 bug:当 sheet 级 autoFilter 与同一 sheet 上 Table 的 autoFilter 范围重叠时(如 MemoryDataExport demo 的 XlsxFeatureGallery.xlsx Details sheet,先调 AddTable('SalesTable', 'A1:F9', ...) 又调 SetAutoFilter('A1:F9')),在 Excel 打开时弹"发现 XXX.xlsx 中的部分内容有问题。是否让我们尽量尝试恢复?"修复提示。OOXML 禁止同一 range 同时被两个 filter 机制管理;writer 现在在 sheet 级 autoFilter range 与任何 table range 相同时跳过 sheet 级 <autoFilter> 输出。Table 自带的 autoFilter(即 header row 下拉箭头)仍然正常工作。
- 修正 <dataValidation> 输出的相关 schema 违规:每个 validation 都输出 operator 属性,但 ECMA-376-1 18.3.1.32 规定 operator 只对 whole / decimal / date / time / textLength 五种 type 有意义。AddListValidation 生成的 type="list" 也会带 operator="between" 默认值;OFV 比 Excel 自身更严,遇到这种 schema 违规会拒绝文件。type="list" / "custom" / "none" 不再输出 operator 属性。
- 修正 worksheet 末尾 <legacyDrawing r:id="..."/> 元素在 internal + external hyperlinks 与 comments 共存时指向错误 rels 的问题(XlsxFeatureGallery.xlsx Dashboard sheet 有 1 个 internal + 1 个 external + 1 个 comment)。rId 计算错误地把所有 hyperlinks 都算进去,但 rId 只分配给 external hyperlinks(internal 走 inline location 属性不消耗 rId),导致 legacyDrawing 指向 comments rels target 而不是 vmlDrawing target。ECMA-376-1 18.3.1.51 要求 legacyDrawing 必须指向 vmlDrawing-typed rels。rId 计算改为只数 external hyperlinks。
- 同时清理:通过 AddChartSheet 添加的独立 chart sheet 不再多写一份 xl/worksheets/_rels/sheetN.xml.rels。该多余文件指向不存在的 worksheet part,作为孤立文件出现在 .xlsx zip 容器里;chart sheet 现在只写正确的 xl/chartsheets/_rels/sheetN.xml.rels。
- 更新 MemoryDataExport demo(XlsxFeatureGallery):删除 Details sheet 上冗余的 SetAutoFilter('A1:F9') 调用 —— AddTable 已经为 table range 附加了 autoFilter,重复调用就触发上述 OFV 拒绝。Writer 端的防御性抑制覆盖未更新到 demo 修改的用户代码。
版本 2.29.3
- 修正 XLSX Open + 修改 + SaveAs 流程中空行边框丢失的问题。ApiTour 第 8 行的水平分隔线(通过 Range.SetBorders 在没有数据的行上画的边框)在首次生成的 ApiTour.xlsx 中显示正确,但 demo 的 Modify 步骤重新保存后整行从 ApiTour-XLSX-Modified.xlsx 中消失,Excel 仅在该修改后的文件中显示出 C8 / D8 处竖网格线断裂(原 ApiTour.xlsx 不受影响)。XLSX 解析器在遇到自闭合 `<c>` 标签或没有 v/f/t 子元素的空 `<c>` 时也会触发样式应用,确保只有样式没有值的单元格能在 round-trip 中保留。
版本 2.29.2
- 修正 XLSX Open + 修改 + SaveAs 流程的 round-trip 回归。ParseWorksheetXml 解析 cell 的
时直接把 N 存到 cell.FormatIndex;SaveAs 时 cellXfs 根据工作簿样式池重建(可能加 composite 条目),新布局同样数字索引几乎不再是同样语义;重存后 cell 指向错误的 cellXf 甚至超出新 cellXfs 表,Excel 报"Office 已检测到此文件存在问题,是否让我们尽量尝试恢复?"。ApplyStyle 现在通过 ParseStylesXml 已经填充的 CellXfXxxMap 表把 cellStyle 反查到 FontIndex / FillIndex / BorderIndex / NumberFormatIndex / AlignmentIndex / ProtectionIndex,让 round trip 根据新建的 cellXfs 重新输出。
版本 2.29.1
- 修正 XLSX 渲染回归两处:(1) Range.SetBorders 在一行内按非单调顺序创建单元格时(例如 outline 先创建 A8/C8、inside 再创建 B8),输出顺序变成 A8/C8/B8 而不是 A8/B8/C8,违反 OOXML CT_Row schema 要求的列升序,Excel 弹"Office 已检测到此文件存在问题"并进入受保护的视图。XLSX 写入器现在按列号排序每行的单元格再输出。(2) 同时设置 2+ 个 style 索引的单元格(Font + Fill + Border 等)以前会被优先级链坍缩到单维 cellXf(FontIndex 赢了,Border / Fill 被丢弃),所以表头行同时有 FontIndex + FillIndex + BorderIndex 时渲染没有边框。写入器现在在 SaveAs 期间收集 composite cellXf 池,把多维单元格路由到合成的 cellXf 上,保留所有维度。
版本 2.29.0
- 内部辅助单元 `lxList2` 重命名为 `lxKeyList`;`lxList` 中以 WideString 为键的类 `TXLSKeyList` / `TXLSKeyEntry` / `TXLSKeyArray` 重命名为 `TXLSStringKeyList` / `TXLSStringKeyEntry` / `TXLSStringKeyArray`。这样单元名跟主类 `TXLSObjectKeyList` 对齐,两代 key-list 也自解释(`TXLSStringKey*` 用于老的 WideString 键池、`TXLSObjectKey*` 用于新的 THashtableKey 去重池)。如果用户代码直接引用了旧单元名或旧类名,请同步更新 uses 子句和类型名。
版本 2.28.3
- 修正了 XLSX 单元格输出回归:对其他列无数据的行设置边框时边框会消失。`Range[''A3:C10''].SetBorders(xlsxEdgeOutline,...)` 在第 8 行无数据的工作表上,会出现 C/D 列之间的竖线在该行断开 —— 因为序列化时会跳过所有 Value 未赋值的单元格,即使这些单元格已经设置了 BorderIndex / FontIndex / FillIndex / NumberFormatIndex / AlignmentIndex / ProtectionIndex。修复后只要单元格有任意 style 索引,都会输出 `
` 占位元素。
版本 2.28.2
- 修正了一处 XLSX 工作表 schema 违规:同时使用合并单元格和自动筛选的工作表会被 Excel 拒绝加载。XLSX 写入器现在按 OOXML CT_Worksheet 顺序先输出 <autoFilter> 再输出 <mergeCells>(autoFilter 是 #11,mergeCells 是 #15)。之前此类工作簿会让 Excel 弹出修复对话框并报 `Load error. Line 1, column 0`(sheet1.xml),修复过程还会顺带删除相邻 Details 工作表中的 tableParts 和自动筛选。
版本 2.28.1
- 经典 XLS 门面新增便捷 API。IXLSRange 新增只读 Width / WidthInPixels 宽度辅助属性和 SaveAsCSV(FileName);IXLSWorksheet 与 IXLSWorkbook 新增 SaveAsCSV(FileName / Stream) 重载,用于导出 UsedRange 或活动工作表;IXLSPageSetup 新增 Order、Draft、BlackAndWhite、PrintNotes 和只读 IsFitToPages。SETUP 记录写入/读取现在会保留这些打印标志。
版本 2.28.0
- TXLSXWorkbook 新增 RTF 导出功能。新增 SaveAsRTF 4 重载(FileName / Stream × 默认活动工作表 / 显式 SheetIndex),将指定工作表写为 RTF 1.6 文档的简单表格。列宽从工作表 ColWidth 数据导出(1 个 Excel 字符单位约等于 96 RTF twips),未设自定义宽度的列回退到 StandardWidth(若有),否则使用 809 twips(~8.43 字符)。按单元格 FontIndex 应用粗体(\\b)、斜体(\\i)和字号(\\fsN,单位半磅)。非 ASCII 字符按 RTF 1.6 §2.4.2 编码为带符号 16 位 \\uN? unicode 转义,覆盖完整 BMP 范围。合并单元格不处理 span —— 原点格输出内容,范围内其余格输出空格。默认 SheetIndex 写活动工作表,越界返回 -1。空工作表输出最小合法 RTF 文档。
版本 2.27.0
- TXLSXWorkbook 新增 HTML 导出功能。新增 SaveAsHTML 4 重载(FileName / Stream × 默认活动工作表 / 显式 SheetIndex),将指定工作表写为带 UTF-8 BOM 的 HTML 文档。输出格式为 <table> 置于简洁 HTML 页面内。合并单元格映射为 colspan / rowspan 属性。单元格样式以 inline CSS 输出:字体名称、字号(pt)、粗体(font-weight:bold)、斜体(font-style:italic)、删除线(text-decoration:line-through)及显式字体颜色;xlsxFillSolid 图案的前景色作为 background-color;水平对齐(left / center / right / justify)和 WrapText(white-space:pre-wrap)。日期 Variant 渲染为 'yyyy-mm-dd hh:nn:ss';富文本单元格展平为各段文字拼接。主题色暂不解析(简单 HTML 导出不依赖 theme1.xml),静默跳过。默认 SheetIndex 写活动工作表,越界返回 -1。
版本 2.26.0
- TXLSXFont / TXLSXFill / TXLSXBorderEdge 新增主题色 + 索引色 + 明暗调(tint/shade)支持。每个颜色槽位除原有 RGB Color 之外,新增三个字段:ColorTheme(Integer;-1=未设;0..11=OOXML 主题色槽)、ColorIndex(Integer;-1=未设;0..63=OOXML legacy 调色板槽,与 Workbook.IndexedColor[N] / XlsxDefaultIndexedPalette 联动)、TintAndShade(Double 区间 [-1.0, 1.0];仅在 theme 模式下输出)。TXLSXFill 的 Foreground / Background 各自独立 3 字段。写入优先级:theme > indexed > rgb;原有的 "ColorIsAuto = True" 路径继续整体抑制元素输出。SaveAs / Open 完整 round-trip <color theme="N" tint="..."/> 和 <color indexed="N"/> 在 font / fill / border 三处的属性集。簿记:TXLSXBorders.LookupOrAdd 的 edge 比较加上 3 个新字段,避免主题色边与 RGB 边在池里误合并。
版本 2.25.0
- TXLSXWorkbook 新增外部工作簿链接 round-trip。新类型:TXLSXExternalLink(Target URL + SheetNames 列表)+ TXLSXExternalLinks 集合。TXLSXWorkbook.ExternalLinks 属性暴露集合;Add(Target) 追加并返回新链接供调用方填充。SaveAs 在 xl/workbook.xml 输出工作簿级 <externalReferences> 块,在 xl/_rels/workbook.xml.rels 加 externalLink rel(rid 排在 rid 链尾,原有 rid 不动),并为每个条目写 xl/externalLinks/externalLink{N}.xml part(<externalBook><sheetNames>)+ 同名 .rels 文件(指向远端工作簿 URL,TargetMode="External")+ 对应 ContentType Override。Open 端从 index 1 起扫 externalLink{N}.xml + .rels 对,首个不存在即停止。本版本仅 round-trip Target URL + SheetNames;<sheetDataSet> 内的缓存单元值不保留。
版本 2.24.0
- TXLSXRange 新增 composing 边框助手 SetBorders。新枚举 TXLSXBorderEdgeKind(xlsxEdgeAll / Outline / Inside / InsideHorizontal / InsideVertical / Top / Bottom / Left / Right / DiagonalUp / DiagonalDown)选定要写的边。SetBorders(Kind, Style, Color) / SetBorders(Kind, Style)(缺省色为不透明黑)遍历 range 内每个单元,按位置算出 edge mask(角格写 2 条 outline 边、边格 1 条、内部格走 inside 网格线等),把 Style + Color 应用到 cell 当前 border 的克隆上(所以连续调用 Outline + Inside 是叠加而非覆盖),再走 workbook 级 lookup-or-add 入 Workbook.Borders 池,把得到的 1-based BorderIndex 写回 cell。新 TXLSXBorders.LookupOrAdd 助手对空 border 返 0,避免 pool 因 no-op 入库而膨胀。
版本 2.23.0
- TXLSXWorkbook 新增 CSV 导出系列重载。新入口:SaveAsCSV(FileName) / SaveAsCSV(FileName, SheetIndex, Delimiter) / SaveAsCSV(Stream) / SaveAsCSV(Stream, SheetIndex, Delimiter),把指定工作表的有数据矩形按 UTF-8 + 带 BOM + CRLF 换行写出。无参版本默认导出活动工作表 + 逗号分隔;带 Delimiter 参数的版本可接任意 WideChar(最常见 TAB #9 = TSV)。字段引用遵循 RFC 4180:含分隔符、双引号、CR、LF 的字段整体加双引号包裹,内嵌双引号按双双引号转义。日期值统一渲染为 'yyyy-mm-dd hh:nn:ss';rich-text 单元格扁平化为各 run 文本拼接;外接矩形内部的空单元以空字段输出,行尾的空单元不再补 padding(每行至最后一个有数据列结束)。
版本 2.22.0
- TXLSXWorkbook 新增工作簿级 indexed 色板覆盖支持。新入口:IndexedColor[Index: Integer]: LongWord(读 / 写,有效槽位 0..63,ARGB LongWord)、HasCustomIndexedColor(Index): Boolean(查询某槽是否被用户覆盖)、CustomIndexedColorCount: Integer(已覆盖槽数;0 = 写出时不发射 <colors> 块)、ResetIndexedColors: procedure(清除所有覆盖)。新常量 XlsxDefaultIndexedPalette 对外暴露 OOXML / ECMA-376 legacy 调色板的 0..63 槽默认值。SaveAs 仅在至少有一个槽被覆盖时输出 <colors><indexedColors> + 64 个 <rgbColor> 子元素(未覆盖槽用默认值),未触碰调色板的工作簿重存后输出依然干净。Open 在解析时只入库与默认值不同的槽,保证 round-trip 最小化。越界(<0 或 >63)的槽位赋值会被静默丢弃,不抛异常。
版本 2.21.0
- TXLSXWorksheet 新增 6 项视图显示属性。Zoom: Integer 是 Excel 状态栏的缩放百分比(10..400,默认 100;越界赋值在写入时 clamp)。DisplayGridLines / DisplayZeros: Boolean(默认 True),设为 False 时分别隐藏网格线 / 把 0 值单元渲染为空。DisplayRightToLeft: Boolean(默认 False)把工作表整体翻转为 RTL 布局(阿拉伯 / 希伯来等)。StandardWidth / StandardHeight: Double 设默认列宽(Excel 字符单位)/ 默认行高(点);0 = 未设置时 Excel 应用内建 8.43 / 15 默认。SaveAs 在偏离 Excel 默认时输出 <sheetView showGridLines / showZeros / rightToLeft / zoomScale> 和 <sheetFormatPr defaultColWidth / defaultRowHeight>;Open 反向解析。原有的 freeze pane / tabSelected 处理逻辑不变,现统一走同一个 <sheetView> 发射器。
版本 2.20.7
- TXLSXWorkbook 新增 TStream 重载用于内存级序列化。新入口:SaveAs(Stream: TStream) / SaveAs(Stream: TStream; FileFormat: TXLSXFileFormat) 把整个 .xlsx 包写入 stream(从当前位置开始),Open(Stream: TStream) 反向读取。调用方拥有 stream,负责 Free。常用于 HTTP 响应、blob 存储、内存管线、绕开本地文件系统的单元测试等场景。已有的文件路径 SaveAs / Open 重载行为不变,内部都委托给同一个 internal helper。
版本 2.20.6
- TXLSXDefinedName 新增 Hidden / Visible / Comment 三个属性。Hidden 映射到 OOXML <definedName hidden="1"/> 属性(默认 False / Visible=True;True 时该名称在 Excel 名称管理器界面里隐藏)。Visible 是 Hidden 的反向 Boolean 别名,调用代码更易读。Comment 映射到 <definedName comment="..."/>。SaveAs 在两个属性偏离默认值时输出对应属性;Open 反向解析。已有的 SheetIndex(通过 localSheetId 绑定 Local scope)行为不变。
版本 2.20.5
- TXLSXFont 新增 5 个缺失属性。新增 TXLSXFontVertAlign 枚举(xlsxVertAlignBaseline / Superscript / Subscript),通过单一 VertAlign 属性映射 Excel 的「上标」「下标」字体复选框(UI 中互斥)。新增 OutlineFont 和 Shadow 两个布尔属性,对应 Excel 字体效果。新增 Family 整数属性(OOXML 字体族号:1=Roman / 2=Swiss / 3=Modern / 4=Script / 5=Decorative;0=未设置)和 CharSet 整数属性(GDI 字符集号:0=ANSI / 1=Default / 134=GB2312 / 136=ChineseBig5 等;-1=未设置)。SaveAs 在 <font> 内输出对应的 <vertAlign> / <outline/> / <shadow/> / <family> / <charset> 子元素;Open 反向解析。ColorIndex / ThemeColor / TintAndShade 留待主题色 milestone 一并处理。
版本 2.20.4
- 新增边框对角线方向开关。TXLSXBorder 新增 DiagonalUp: Boolean 和 DiagonalDown: Boolean 两个属性。两个开关共享已有的 Diagonal 边的 Style 和 Color,控制 Excel 渲染哪条对角线(向上 = 左下到右上、向下 = 左上到右下,或同时画两条)。SaveAs 在 <border> 元素上输出 diagonalUp / diagonalDown 属性;Open 反向解析。之前引擎只输出 Diagonal 边但没有方向信息,Excel 不会绘制任何对角线。
版本 2.20.3
- 新增工作簿 Date1904 时间基准开关。TXLSXWorkbook 新增 Date1904: Boolean 属性,在 Windows 1900 时间基准(默认,与 Excel for Windows 一致)和 Mac 1904 时间基准(Excel for Mac 老格式)之间切换。SaveAs 在设为 True 时输出 <workbookPr date1904="1"/>;Open 反向读取。本属性是元数据开关——引擎不对存储的日期序列做转换;调用方应在赋值 TDateTime 单元前先设 Date1904,才能让 round-trip 落在正确历法上。
版本 2.20.2
- 新增自动筛选每列过滤规则支持。新增类型 TXLSXAutoFilterOp 枚举(Equal / NotEqual / GreaterThan / LessThan / GreaterOrEqual / LessOrEqual)、TXLSXAutoFilterColumn 类(ColId + 1 或 2 个 criteria + AND/OR 连接符)、TXLSXAutoFilterColumns 集合。TXLSXWorksheet 新增 AutoFilterColumns 属性和 AddAutoFilterColumn(ColId, Op, Criteria) / AddAutoFilterColumn(ColId, Op1, Criteria1, Op2, Criteria2, AndConnector) / ClearAutoFilterColumns 便捷方法。SaveAs 在 criteria 不为空时把现有的 <autoFilter ref="..."/> 展开成 <filterColumn colId=N><customFilters and=0|1><customFilter operator="..." val="..."/>...</customFilters></filterColumn> 子结构;Open 反向解析。之前引擎只存 sqref,Excel 打开后筛选下拉是空的。
版本 2.20.1
- TXLSXWorksheet 新增手工分页符支持。新增入口:AddRowBreak(BeforeRow) / AddColBreak(BeforeCol) 在指定行 / 列之前插入水平 / 垂直分页符(Excel UI「Before」语义——row N 开始新页)。HasRowBreak / HasColBreak 检查;RemoveRowBreak / RemoveColBreak 单条删除;ClearRowBreaks / ClearColBreaks / ClearAllPageBreaks 清空。RowBreakCount / ColBreakCount + 索引访问的 RowBreaks(Index) / ColBreaks(Index) 暴露已存的 1-based「Before」索引,方便遍历。SaveAs 在 <headerFooter> 与 <drawing> 之间输出 <rowBreaks> / <colBreaks>,子元素 <brk id="N-1" max="..." man="1"/>;Open 反向解析。
版本 2.20.0
- 新增工作表可见性(隐藏 / 极度隐藏)、单选状态、活动工作表的跟踪支持。新增类型 TXLSXSheetVisibility 枚举(xlsxSheetVisible / xlsxSheetHidden / xlsxSheetVeryHidden)。TXLSXWorksheet 新增 Visibility、Visible(Boolean 别名)、IsSelected(只读)三个属性。TXLSXSheets 新增 ActiveIndex、Activate(Index)、Move(FromIndex, ToIndex)。TXLSXWorkbook 新增 ActiveSheet 代理属性。SaveAs 在工作簿的 <sheet> 上输出 state 属性,在 active 不是 0 时输出 <bookViews><workbookView activeTab=N/></bookViews>,在活动表的 <sheetView> 上输出 tabSelected="1";Open 反向解析。第一张新增的 sheet 默认 visible+active,旧调用代码无需改动。
版本 2.19.2
- TXLSXWorksheet 新增 4 个 PageSetup 属性开关,补齐 OOXML <pageSetup> 覆盖:BlackAndWhite(黑白打印)、Draft(草稿模式,跳过图形以加快预览)、PrintNotes(打印批注,按显示位置)、PrintOverThenDown(页面遍历顺序从默认「下→右」切换到「右→下」)。SaveAs 在对应属性被启用时输出 blackAndWhite / draft / cellComments / pageOrder 属性;Open 反向解析。默认全部 False,未改动的工作表不会多出额外属性。
版本 2.19.1
- TXLSXWorksheet 新增页眉 / 页脚的三段式(左 / 中 / 右)便捷属性:LeftHeader / CenterHeader / RightHeader 和 LeftFooter / CenterFooter / RightFooter。每个属性读取或写入已有 HeaderText / FooterText 原始字符串里对应的 &L / &C / &R 段;任意写入一段都会重新组装完整原始字符串,所以现有 round-trip 写入器和读取器不需要改动。
- 新增 sheet 级打印选项开关:CenterHorizontally、CenterVertically、PrintGridlines、PrintHeadings。SaveAs 在 4 项任意一项被启用时输出 <printOptions horizontalCentered/verticalCentered/gridLines/headings/>;Open 反向解析。默认全部 False,未改动的工作表不会多出 <printOptions/> 元素。
- 新增 sheet 级 PrintArea / PrintTitleRows / PrintTitleCols 往返支持。这三项对应 OOXML 工作簿级的内置 _xlnm.Print_Area 和 _xlnm.Print_Titles 定义名,通过 localSheetId 绑定到具体 sheet。PrintArea 接受裸 A1 引用(如 "$A$1:$D$10");PrintTitleRows 和 PrintTitleCols 接受行 / 列方向引用(如 "$1:$3" 或 "$A:$B"),写入时合并为一条 Print_Titles 记录。写入端会给 sheet 名加正确的引号(含空格或特殊字符时单引号包裹);读取端剥离 sheet 前缀并路由回对应 sheet 的字段,不会污染用户的 TXLSXWorkbook.DefinedNames 集合。
版本 2.19.0
- TXLSXWorksheet 新增行 / 列的插入、删除操作,并同步整张 sheet 内所有几何位置。新增入口:InsertRows(BeforeRow, Count)、DeleteRows(StartRow, Count)、InsertCols(BeforeCol, Count)、DeleteCols(StartCol, Count)。Insert 系列把指定位置及之后的行 / 列推开 Count;Delete 系列移除 [Start, Start+Count-1] 这段并把后面的行 / 列回拉 Count。
- 位移会自动应用到所有依赖行 / 列位置的内容:单元格锚点(Cells)、合并区域四角(MergedCells——横跨删除区域的合并块会被裁切到剩余边界,完全位于删除区域内的合并块会被丢弃)、行 / 列 metadata 列表(FRowHeights / FColWidths / outline / hidden / collapsed)、超链接和批注的锚点(位于删除区域内的条目被丢弃)、FreezePane(FFreezeRow / FFreezeCol)、AutoFilterRange、以及每个 ConditionalFormat / DataValidation / Table 上的 Range 字符串(完全位于删除区域内的条目被丢弃)。
- 配套支撑:TXLSXHyperlinks、TXLSXComments、TXLSXConditionalFormats、TXLSXDataValidations、TXLSXTables 新增 Delete(Index) 方法,方便位移逻辑按需删除单条条目而不是清空整个集合。
- 本次未实现:Images 和 Charts 不参与位移(它们的 EMU 像素锚点与单元格栅格解耦,正确位移需要重算 EMU 偏移,留待后续版本);DefinedNames 中的公式串也未做改写。
版本 2.18.2
- 新增列宽 / 行高自动适配(AutoFit)辅助方法。TXLSXWorksheet 新增 AutoFitColumn(ACol) / AutoFitColumns(ColMin, ColMax) 和 AutoFitRow(ARow) / AutoFitRows(RowMin, RowMax);TXLSXRange 新增 AutoFitColumns 和 AutoFitRows,对 range 覆盖的列 / 行转发到 worksheet 层。宽度估算用 Excel 字符单位(Calibri 11pt 为基准;ASCII 字符算 1 单位,CJK 字符算 2 单位),px/char 系数 1.20、单元两侧加 1.0 padding,结果 clamp 到 [8.43, 255.0]。行高默认 15 pt,每多一个换行符增加 12.75 pt。EntireRow / EntireColumn 等覆盖整行/整列的 range 在 AutoFit 时会自动 clamp 到最后一个有内容的行/列,避免遍历到 Excel 网格上限。
版本 2.18.1
- XLSX 引擎新增单元级保护状态(Locked / FormulaHidden)的往返支持。TXLSXCell 新增 Locked: Boolean(默认 True)和 FormulaHidden: Boolean(默认 False)便捷属性,对应 Excel 的单元保护模型。底层用新增的工作簿级 TXLSXProtections 池存储 (Locked, FormulaHidden) 组合,TXLSXCell.ProtectionIndex(1-based)引用池条目;写便捷属性时自动在池里查找或追加对应条目。默认值组合 (Locked=True, FormulaHidden=False) 会被折叠成 ProtectionIndex=0,保持普通单元的池为空。
- TXLSXRange 新增 SetLocked(ALocked) 和 SetFormulaHidden(AHidden) 批量方法,对整片区域解锁/隐藏公式时只做一次池查找/追加并应用到区域内每个单元,避免每个单元各自查找。
- 同步补齐 writer / reader 链路。SaveAs 在 alignment 区段之后为 Protections 池中每条记录追加一个 cellXf,里面嵌入 <protection locked="N" hidden="M"/>;Open 解析 <protection> 回填到 Workbook.Protections,并通过 ParseStylesXml 和 ParseWorksheetXml 新增的 CellXfProtMap 参数把 cellXf 的 protection index 映射到 TXLSXCell.ProtectionIndex,与已有的 font/fill/border/numFmt/alignment 索引一起往返。
版本 2.18.0
- TXLSXWorksheet 新增 TXLSXRange 多单元区域对象,支持批量操作。新增入口:Worksheet.Range['A1:C5']、Worksheet.RCRange[r1,c1,r2,c2]、Worksheet.UsedRange、Worksheet.EntireRow(r)、Worksheet.EntireColumn(c)。返回的 range 对象提供 SetValue / SetFormula / Clear / ClearAll / Merge / Unmerge / Offset / Resize,以及批量样式索引 setter(SetFontIndex / SetFillIndex / SetBorderIndex / SetNumberFormatIndex / SetAlignmentIndex)和 SetNumberFormat(Fmt) 便捷方法——后者会在工作簿数字格式池里查找或新增对应字符串。TXLSXRange 对象由 worksheet 持有,worksheet 销毁时统一释放,调用方无需 Free。
- TXLSXCell 新增 NumberFormat: WideString 便捷属性,与已有 NumberFormatIndex 配对。读取返回工作簿池中的格式字符串;写入时自动在池里查找或追加该字符串并同步更新 NumberFormatIndex。需要 cell 已挂到工作簿上(通过标准的 TXLSXWorkbook.Sheets.Add(...).Cells[r, c] 流程即可)。
- 新增 cell -> sheet -> workbook 反向引用链,每个 TXLSXCell 现在能直接定位到所属工作簿,无需调用方维护额外映射。TXLSXSheets、TXLSXWorksheet、TXLSXCells 都新增了 Owner 字段,通过各自构造函数串接;TXLSXCell 新增只读 Workbook 属性和 internal-flavor SetWorkbook,由 TXLSXCells.GetItem 在 auto-create 时自动注入。
版本 2.17.42
- 修复 XLSX 单元往返在重新打开时丢失的问题。SaveAs 写出的单元在 Open 后 HasCell(row, col) 返回 False,单元的值、公式、字体索引、填充索引、边框索引、数字格式索引全部丢失。根因是 sheet 解析器在 `<c>` 元素处理中多余调用了 `MoveToAttribute('r')`,把 reader 当前节点类型切到 attribute,导致紧随其后的 IsEmptyElement 检查返回 True 并把 inCell 关掉,凡是带 r="" 属性的 `<c>` 元素(也就是所有单元)一律不再解析子节点。移除这个多余的游标移动后,文本、数字、公式、日期单元的往返一并恢复。
- 修复 XLSX 样式索引在重新打开时无法回填到单元的问题。即便字体/填充/边框/数字格式池本身(Workbook.Fonts/Fills/Borders/NumberFormats)已经正确往返,单元上的 FontIndex/FillIndex/BorderIndex/NumberFormatIndex 仍读回 0。cellXf 解析器原本只在 `</xf>` 终结标签里推进索引计数器,但 Excel 普遍输出 self-closing 的 `<xf .../>`(没有内嵌 `<alignment>` 时),计数器永不递增,所有 cellXf 互相覆盖到索引 0。解析器现在会在 self-closing `<xf/>` 时同步推进计数器,单元级 FontIndex/FillIndex/BorderIndex/NumberFormatIndex 恢复往返。
- 修复 XLSX 日期单元的往返问题。把 TDateTime 写入 TXLSXCell.Value 之前会绕道走 SST 字符串池输出 t="s",原因是 Delphi 的 VarIsNumeric() 对 varDate 返回 False;SaveAs 现在直接把日期序列号写到 `<v>` 并套用日期 cellXf,日期单元重新打开后是 varDate Variant 而不是无法逆向转回 TDateTime 的本地化字符串。
版本 2.17.41
- 修复重新打开包含嵌入图片或 VBA 工程(.xlsm)的 .xlsx 文件时抛出 "zlib stream does not support seeking" 的错误。图片重载和 VBA 字节重载这两条路径都把 inflate 后的 entry 流送进 TMemoryStream.CopyFrom(Source, 0),该调用会内部把 Source 倒带到 0 以推算字节数,而 Deflate 解压流是前向单读流不允许倒带。两处改用分块 Read-直到-EOF 的辅助过程,使得带图片或宏的 .xlsx 文件能正常完成 SaveAs/Open 的往返。
版本 2.17.40
- XLSX 引擎新增 ChartSheet(独立图表工作表)支持。TXLSXWorksheet 新增 IsChartSheet 标志位,工作簿级 Workbook.AddChartSheet(Name, ChartType, Title) 便捷方法会创建 sheet、置位标志并预设 Charts[0] 的合理锚点。SaveAs 把 IsChartSheet 的 sheet 输出到 xl/chartsheets/sheetN.xml,配套独立 rels 文件指向共享 drawing 部件,注册 chartsheet content-type,并在 xl/_rels/workbook.xml.rels 中输出 chartsheet 关系类型。普通工作表仍走 xl/worksheets/sheetN.xml 路径。Open 通过关系类型识别 chartsheet,但当前仍按普通 worksheet 加载(图表数据仍通过共享 chart parts 抵达)。
版本 2.17.39
- XLSX 引擎新增 outline 分组折叠状态(collapsed)的行/列往返支持。TXLSXWorksheet 新增 RowCollapsed[Row] 和 ColCollapsed[Col] 布尔属性以及 SetRowCollapsed / SetColCollapsed / ClearRowCollapsed / ClearColCollapsed 辅助方法。SaveAs 在对应的 <row> 和 <col> 上输出 collapsed="1" 属性;Open 解析回填。配合已有的 outlineLevel 和 hidden 属性,XLSX 引擎现在能完整往返折叠的分组层级。
版本 2.17.38
- XLSX 引擎新增隐藏行 / 隐藏列往返支持。TXLSXWorksheet 新增 RowHidden[Row] 和 ColHidden[Col] 布尔属性以及 SetRowHidden / SetColHidden / ClearRowHidden / ClearColHidden 辅助方法。SaveAs 在对应的 <row> 和 <col> 上输出 hidden="1" 属性;Open 解析回填到工作表,隐藏的行/列无需依赖自定义列宽或 outline 等级即可往返。
版本 2.17.37
- XLSX 引擎新增工作表标签颜色往返支持。TXLSXWorksheet 新增 TabColor (ARGB) 和 TabColorIsAuto 属性。SaveAs 在 worksheet 的最前面输出 <sheetPr><tabColor rgb="..."/></sheetPr> 块(仅当 tab 颜色被设置时);Open 解析 <tabColor> 回填到工作表,彩色标签得以往返。未设置颜色的工作簿保持默认状态(TabColorIsAuto = True),不输出额外块。
版本 2.17.36
- XLSX 引擎新增单元格对齐往返支持。新增 TXLSXHorizontalAlignment 与 TXLSXVerticalAlignment 枚举、TXLSXAlignment 类(Horizontal、Vertical、WrapText、ShrinkToFit、Indent、TextRotation)以及工作簿级 TXLSXAlignments 集合(Workbook.Alignments)。TXLSXCell 新增 AlignmentIndex 属性(1-based 指向 Workbook.Alignments)。SaveAs 为每个工作簿对齐条目输出一个带 <alignment/> 子元素的 cellXf;Open 解析 <alignment> 属性回填 Workbook.Alignments 并把 cellXf 反查为 TXLSXCell.AlignmentIndex。ParseWorksheetXml 与 ParseStylesXml 新增 CellXfAlignMap 参数承接跨阶段映射。
版本 2.17.35
- XLSX 引擎新增 AES 加密保护(ECMA-376 Standard Encryption)API 入口。TXLSXWorkbook 暴露 SaveAsEncrypted(FileName, Password) / OpenEncrypted(FileName, Password) / CanReadEncrypted(FileName) 三个方法以及独立的 EXlsxEncryptionNotImplemented 异常类。CanReadEncrypted 通过 Microsoft Compound File Binary 魔数($D0 $CF $11 $E0 $A1 $B1 $1A $E1)识别加密档;OpenEncrypted 对未加密的 .xlsx 文件透明地退回到普通 Open。AES-128/256 + SHA + OLE Compound File 算法管线尚未接入——加密文件的实际读写当前抛出 typed exception,等待后续 release 实现算法。异常类型独立,调用方可以 catch 它并降级到 Worksheet.Protect / Workbook.ProtectWorkbook 做可视锁定。
版本 2.17.34
- 性能优化:把每个工作表 cell rows 的 O(N²) WideString 拼接换成 TXLSWideStringBuilder,大型表(1万 cells 以上)在 SaveAs 时内存和 CPU 都退到线性。新增 WriteWorksheetXmlStreaming 辅助函数和 TXLSXWorkbook.StreamingWrite 开关——开启后 SaveAs 不再同时持有所有 worksheet XML 字符串,每个工作表按序 build + write + 释放。sharedStrings.xml 改为最后写入,确保流式路径下 SST 完整。默认行为不变。
版本 2.17.33
- XLSX 引擎新增单元格区域操作 API。TXLSXWorksheet 暴露 ClearRange(R1, C1, R2, C2)、本表复制 CopyRange(SrcR1, SrcC1, SrcR2, SrcC2, DstR, DstC)、跨表复制 CopyRangeTo(... TargetSheet, DstR, DstC)、以及剪切 MoveRange(SrcR1, SrcC1, SrcR2, SrcC2, DstR, DstC)。每次操作都会复制单元格的 Value、Formula、四个 style index 和富文本副本;MoveRange 跳过与目标区域的重叠部分,使部分重叠移动仍能保留已粘贴的值。TXLSXCells 同时新增 Remove(Row, Col) 辅助方法。
版本 2.17.32
- XLSX 引擎新增超链接内部锚点支持。TXLSXHyperlink 新增 Location 属性(如 "Sheet2!A1")和 IsInternal 辅助;TXLSXHyperlinks 暴露 AddInternal 方法,TXLSXWorksheet 新增三个 AddHyperlinkToCell 重载。SaveAs 用 location="" 内联属性输出内部超链接,不为之生成 worksheet rels 关系;Open 识别带 location 的 <hyperlink> 并通过 AddInternal 回填。外部 URL 超链接仍走 rels 文件,逻辑不变。
版本 2.17.31
- XLSX 引擎新增富文本字符串往返支持。新增 TXLSXRichTextRun 类(每个 run 携带 Name、Size、Bold、Italic、Strikethrough、Underline、Color)和 TXLSXRichText 容器,暴露 AddRun / AddRunText / Clear / PlainText。TXLSXCell 新增 RichText 属性(所有权由 cell 持有);SaveAs 把带富文本的单元格写为多 <r>/<rPr>/<t> 的共享字符串,Open 从 SST 重建 TXLSXRichText,cell.Value 仍保留拼接后的纯文本以兼容不关心格式的调用方。
版本 2.17.30
- XLSX 引擎新增图表往返支持。新增 TXLSXChartType 枚举(column / bar / line / pie)、TXLSXChartSeries(Name、CategoriesRange、ValuesRange)和 TXLSXChart(ChartType、Title、坐标轴标题、From/To 锚点单元格、Series)类,以及工作表级 TXLSXCharts 集合(Worksheet.Charts)。TXLSXWorksheet 暴露 AddChart(Type, Title, FromRow, FromCol, ToRow, ToCol) 便捷方法。SaveAs 输出 xl/charts/chartN.xml(工作簿全局编号)并通过 xl/drawings/drawingN.xml 中的 twoCellAnchor / graphicFrame 锚定到工作表;Open 解析锚点和图表定义回填到集合。图表标题、坐标轴标题、系列名称和数据源区域全部往返。
版本 2.17.29
- 修复 SetColWidth、SetRowHeight、SetRowOutlineLevel、SetColOutlineLevel 抛 EListError "Operation not allowed on sorted list" 的 bug。这四个 TStringList 字段创建时 Sorted=True,但写入用 Values[Name] := X 形式,RAD Studio RTL 在 sorted 列表上拒绝该操作。改为创建为未排序列表;查询仍走 IndexOfName,在典型工作表的列/行数量级下性能足够。
版本 2.17.28
- 修复 TZipArchive.Exists 是 stub 永远返回 false 的 bug。XLSX Open 路径用 zip.Exists(...) 守卫每个部件的读取,导致此前所有声称的往返支持(单元格、样式、批注、绘图、文档属性、命名范围、保护、VBA 等)在读回时静默丢失全部内容。Exists 现在 delegate 到已实现的 Fcd.Entries.Exists 查询,与 OpenFile / CreateFile 调用模式一致。
版本 2.17.27
- XLSX 引擎新增 VBA 项目保留支持。TXLSXWorkbook 暴露 VbaProject 二进制载荷以及 LoadVbaProjectFromFile(FileName)、ClearVbaProject、HasVbaProject 辅助方法。SaveAs 把字节写入 xl/vbaProject.bin,注册 .bin 内容类型,把工作簿主类型切换为 macro-enabled 变种,并向工作簿 rels 文件加入 vbaProject 关系;Open 把 xl/vbaProject.bin 读回到属性。字节不解析也不修改,已有的 .xlsm 项目原样往返。注意:含宏的工作簿必须以 .xlsm 扩展名保存,Excel 才会启用宏。
版本 2.17.26
- XLSX 引擎新增工作簿与工作表保护支持。TXLSXWorksheet 暴露 Protect / Protect(Password) / UnProtect 方法以及 IsProtected、SheetProtectHash 属性;TXLSXWorkbook 新增 ProtectWorkbook(可选密码、LockStructure、LockWindows 三参数版本)和 UnProtectWorkbook 方法,以及 IsWorkbookProtected、WorkbookProtectHash、LockStructure、LockWindows 属性。SaveAs 在受保护工作表上输出 <sheetProtection>、在受保护工作簿上输出 <workbookProtection>;Open 解析两个块回填到 API。密码以 4 位十六进制的传统 hash 形式存储以保持往返(不能反推回明文密码)。
版本 2.17.25
- XLSX 引擎新增文档属性往返支持。TXLSXWorkbook 暴露 Title、Author、Subject、Keywords、Description、Category、LastModifiedBy、Created、Modified、Company、Application、AppVersion 属性。任一属性被设置后,SaveAs 输出 docProps/core.xml 和 docProps/app.xml(并向 [Content_Types].xml 和 _rels/.rels 注册);Open 解析两个文件回填,作者、修改时间戳、应用元数据等存盘再打开后保留。
版本 2.17.24
- XLSX 引擎新增 Excel 表格往返支持。新增 TXLSXTable 类(Id、Name、DisplayName、Range、Columns、StyleName、ShowFirstColumn / ShowLastColumn / ShowRowStripes / ShowColumnStripes)和工作表级 TXLSXTables 集合。TXLSXWorksheet 暴露 Tables 集合以及 AddTable(Name, Range, ColumnNames) 便捷方法。SaveAs 输出 xl/tables/tableN.xml(工作簿全局编号)、向工作表 rels 写入 table 关系、worksheet 加 <tableParts>、注册 table content-type。Open 解析 table 关系和 tableN.xml 回填到工作表,带样式的 Excel 表格存盘再打开后保留。
版本 2.17.23
- XLSX 引擎新增自动筛选往返支持。TXLSXWorksheet 暴露 AutoFilterRange 属性以及 SetAutoFilter(Row1, Col1, Row2, Col2) / SetAutoFilter(Range) / ClearAutoFilter 便捷方法。SaveAs 在合并单元格之后输出 <autoFilter ref="..."/>(仅当范围非空);Open 解析 ref 回填到属性,工作表上的筛选条得以存盘再打开后保留。
版本 2.17.22
- XLSX 引擎新增页面设置往返支持。TXLSXWorksheet 暴露 Margin{Left,Right,Top,Bottom,Header,Footer}、PageLandscape、PaperSize、PageScale、FitToWidth、FitToHeight、HeaderText、FooterText 属性以及 SetPageMargins(L, R, T, B[, H, F]) 便捷重载。SaveAs 在 hyperlinks 和 drawings 之间输出对应的 <pageMargins>、<pageSetup>、<headerFooter> 块;Open 解析回来。未触碰页面设置的工作表保持默认(用 PageSetupTouched 标志控制输出)。
版本 2.17.21
- XLSX 引擎新增冻结窗格往返支持。TXLSXWorksheet 暴露 FreezePane(Col, Row) / UnfreezePane 方法以及只读的 FreezeCol、FreezeRow 属性。SaveAs 在 <sheetData> 之前输出 <sheetViews>/<pane state="frozen"> 块(含 activePane 和 selection);Open 解析 <pane state="frozen"> 回填到冻结位置,冻结顶行、冻结左列、冻结角点的布局都能存盘再打开后保留。
版本 2.17.20
- XLSX 引擎新增行列分组(outline 等级)支持。TXLSXWorksheet 暴露 RowOutlineLevel[Row] 和 ColOutlineLevel[Col] 索引属性,以及 SetRowOutlineLevel / HasRowOutlineLevel / ClearRowOutlineLevels 和对应的列方法。SaveAs 在 <row> 和 <col> 上输出 outlineLevel 属性(列侧与已有的 customWidth 合并到同一条 <col>);Open 解析两个属性回填到工作表,行列分组层级得以往返。
版本 2.17.19
- XLSX 引擎新增条件格式和数据验证往返支持。新增 TXLSXCfOperator 枚举和 TXLSXConditionalFormat 类(Range、Op、Formula1、Formula2)以及工作表级 TXLSXConditionalFormats 集合(Worksheet.ConditionalFormats)。新增 TXLSXDataValidationType、TXLSXDvOperator、TXLSXDataValidation 类(Range、ValidationType、Op、Formula1、Formula2、AllowBlank、ShowInputMessage、ShowErrorMessage)以及 TXLSXDataValidations 集合(Worksheet.DataValidations),提供 AddList(Range, Items) 便捷下拉列表方法。TXLSXWorksheet 暴露 AddConditionalFormat 与 AddDataValidation / AddListValidation 辅助方法。SaveAs 在 sheetData 之后输出 <conditionalFormatting>(cfRule type="cellIs")和 <dataValidations> 块;Open 解析两个块回填到集合。
版本 2.17.18
- XLSX 引擎新增命名范围往返支持。新增 TXLSXDefinedName 类(Name、Formula、SheetIndex)和工作簿级 TXLSXDefinedNames 集合(Workbook.DefinedNames),提供 Add(Name, Formula[, SheetIndex]) 重载和 IndexOfName 查询。SaveAs 在 xl/workbook.xml 中输出 <definedNames> 块;SheetIndex >= 0 的条目带 localSheetId 属性(工作表作用域),SheetIndex = -1 表示工作簿作用域。Open 解析 <definedName> 元素回填到集合,使存盘再打开后命名范围得以保留。
版本 2.17.17
- XLSX 引擎新增图片往返支持。新增 TXLSXImageFormat 枚举(png / jpeg / gif / bmp)、TXLSXImage 类(Row/Col 锚点、WidthEMU/HeightEMU、Format、Data)以及工作表级 TXLSXImages 集合。TXLSXWorksheet 暴露 Images 属性和 AddImage(Row, Col, Data, Format) / AddImageFromFile(Row, Col, FileName) 便捷方法。SaveAs 把图片字节写入 xl/media/imageN.<ext>,生成 xl/drawings/drawingN.xml(每张图片一个 oneCellAnchor)并配套 rels 文件,注册内容类型和工作表/绘图关系,并在 worksheet 中加入 <drawing r:id="..."/>。Open 解析 drawingN.xml + 绘图 rels + 媒体二进制,把图片回填到 Worksheet.Images。
版本 2.17.16
- XLSX 引擎新增自定义数字格式往返支持。新增 TXLSXNumberFormat 类和工作簿级 TXLSXNumberFormats 集合(Workbook.NumberFormats),Add(FormatCode) 会自动去重。TXLSXCell 新增 NumberFormatIndex 属性;SaveAs 在 xl/styles.xml 中输出 <numFmts> 块(自定义 id 从 OOXML 保留基 164 开始),并为每个格式配套生成一个 cellXf;Open 解析自定义 numFmts 后,把 cellXf->numFmtId 映射反查回 NumberFormatIndex。多属性冲突时优先级:FormatIndex > FontIndex > FillIndex > BorderIndex > NumberFormatIndex。
版本 2.17.15
- XLSX 引擎新增单元格边框往返支持。新增 TXLSXBorderStyle 枚举、TXLSXBorderEdge 类(每条边的 Style + Color + ColorIsAuto)、TXLSXBorder 类(Left / Right / Top / Bottom / Diagonal 五条边及 SetAll(Style[, Color]) 便捷方法),以及工作簿级 TXLSXBorders 集合(Workbook.Borders)和 Borders.AddBox(Style[, Color]) 快捷方法。TXLSXCell 新增 BorderIndex 属性;SaveAs 把每个边框输出到 xl/styles.xml 并配套生成一个 cellXf,Open 解析边框回来后把 cellXf->borderId 映射反查到 BorderIndex。同时设置多个时优先级 FormatIndex > FontIndex > FillIndex > BorderIndex。
版本 2.17.14
- XLSX 引擎新增单元格填充往返支持。新增 TXLSXFillPattern 枚举和 TXLSXFill 类描述 patternType / fgColor / bgColor;工作簿级 TXLSXFills 集合通过 Workbook.Fills 暴露,并提供 Fills.AddSolid(color) 便捷方法。TXLSXCell 新增 FillIndex 属性;SaveAs 把每个填充输出到 xl/styles.xml 并配套生成一个 cellXf,Open 解析回来后把 cell 的 s 属性反查到 FillIndex。FontIndex 和 FillIndex 同时设置时 FontIndex 优先。
版本 2.17.13
- 完成 XLSX 字体的 Open 端往返。Open 现在能解析 xl/styles.xml 回填 Workbook.Fonts 集合和 cellXf->fontId 映射;每个单元格的 s 属性会被反查为 TXLSXCell.FontIndex,使存盘再打开后能保留 Name、Size、Bold、Italic、Strikethrough、Underline、Color 等所有字体属性。
版本 2.17.12
- 新增 TXLSXFont 类和 Workbook.Fonts 集合,让 XLSX 单元格可以选用自定义字体。TXLSXCell 新增 FontIndex 属性;SaveAs 在 xl/styles.xml 中输出 fonts 列表,并为每个字体配套一个 cellXf,cell 的 s 属性按 FontIndex 引用对应 cellXf。Open 端 FontIndex 往返将在下个版本补齐。
版本 2.17.11
- XLSX 引擎新增行高往返支持。TXLSXWorksheet 暴露 RowHeight[Row] 属性以及 SetRowHeight、HasRowHeight、ClearRowHeights 辅助方法。SaveAs 在每个有自定义高度的 <row> 元素上输出 ht 和 customHeight="1" 属性(包括只有行高但无任何单元格的行);Open 解析 ht 属性回填到行高表。
版本 2.17.10
- XLSX 引擎新增列宽往返支持。TXLSXWorksheet 暴露 ColWidth[Col] 属性以及 SetColWidth、HasColWidth、ClearColWidths 辅助方法。SaveAs 输出 <cols> 块,每个自定义列宽一条 <col> 条目;Open 回放 <col min/max/width> 条目,未自定义的列保持 Excel 默认宽度。
版本 2.17.9
- XLSX 引擎新增单元格批注往返支持。TXLSXWorksheet 暴露 Comments 集合和 AddComment(Row, Col, Text[, Author]) 重载。SaveAs 输出 xl/commentsN.xml(自动去重作者列表)以及配套的 xl/drawings/vmlDrawingN.vml 让 Excel 能渲染批注气球;Open 解析 commentsN.xml 写回集合。工作表关系文件、内容类型注册、<legacyDrawing> 引用自动维护。
版本 2.17.8
- XLSX 引擎新增超链接往返支持。TXLSXWorksheet 暴露 Hyperlinks 集合和 AddHyperlink(Row, Col, Url[, Display[, Tooltip]]) 重载。SaveAs 在每个工作表中输出 <hyperlinks> 块,并配套写出 xl/worksheets/_rels/sheetN.xml.rels 关系文件存放外部 URL;Open 先读取工作表关系文件解析 <hyperlink r:id="..."/> 条目对应的真实 URL 后回填到集合。
版本 2.17.7
- XLSX 引擎新增合并单元格往返支持。TXLSXWorksheet 暴露 MergedCells 集合和 MergeCells(R1, C1, R2, C2) 便捷方法,与 BIFF façade 调用风格一致。SaveAs 在 sheetData 之后输出 <mergeCells> 块,Open 解析 <mergeCell ref="A1:B2"/> 条目回填到集合中。
版本 2.17.6
- XLSX 引擎现在能往返日期和公式。TDateTime 单元格值序列化为 Excel 序列号,并打上内置日期 cellXf 标记让 Excel 渲染为日期;Open 时引用日期 cellXf 的单元格自动解码回 TDateTime 变体。TXLSXCell 新增 Formula 属性,SaveAs 把公式作为 <f> 子元素输出,Open 解析 <f> 文本写回单元格。
版本 2.17.5
- XLSX 引擎新增 styles.xml 骨架支持。SaveAs 现在输出最小合规的 xl/styles.xml(含默认 fonts / fills / borders / cellStyleXfs / cellXfs 条目),并同步注册到 content-types 与 workbook 关系中。单元格新增 FormatIndex 属性,非零时输出 s="N" 单元格属性;Open 读回 s="N" 到 FormatIndex。具体的样式描述对象(fonts / fills / borders / cellXfs 作为工作簿级集合)将在后续 commit 中加入。
版本 2.17.4
- XLSX 引擎新增共享字符串(SST)支持。SaveAs 构建去重的字符串表并输出 xl/sharedStrings.xml,取代原先内联字符串输出。Open 优先读取 xl/sharedStrings.xml,按 t="s" 单元格引用解析字符串。来自第三方 XLSX 的内联字符串单元格在 Open 时仍然兼容接受。
版本 2.17.3
- TXLSXWorksheet 的单元格存储从 record 数组改为 TXLSXCell 对象与 TXLSXCells 集合。单元格调用方式改为 Worksheet.Cells.Item[Row, Col].Value,与 BIFF façade 的 IXLSCells / IXLSRange 形态一致。同时提供 Worksheet.Cells.HasCell / Cells.Count / Cells.CellByIndex / Cells.Clear。
版本 2.17.2
- 在 TXLSXWorkbook 上引入 TXLSXSheets 集合类,对应 BIFF façade 的 IXLSWorkSheets 集合。调用方式从原来的 Workbook.AddSheet / Workbook.SheetCount / Workbook.Sheet[i] 改为 Workbook.Sheets.Add / Workbook.Sheets.Count / Workbook.Sheets[i] / Workbook.Sheets.IndexByName,与 v2 façade 写法一致。
版本 2.17.1
- 将 TXLSXWorkbook.SaveToFile 重命名为 SaveAs,TXLSXWorkbook.LoadFromFile 重命名为 Open,与现有 IXLSWorkBook 命名风格保持一致。同时新增文件格式参数和密码参数的重载,让 XLSX façade 的调用方式与 BIFF façade 一致。AddSheet 也新增无参版本,自动生成默认工作表名。
版本 2.17.0
- TXLSXWorkbook.SaveAs 现在能产生最小的 OOXML .xlsx 文件,包含单元格值(数值、布尔、内联字符串)。归档含内容类型、根关系、工作簿及其关系、每个工作表一个 XML 部件。
- TXLSXWorkbook.Open 能读回最小 OOXML .xlsx 归档 —— 从 xl/workbook.xml 获取工作表名,从 xl/worksheets/sheetN.xml 获取单元格值。共享字符串、样式、日期、公式暂未支持。
- 新增 OOXML 命名空间、内容类型、关系类型常量以及引用 / 解析 / 转义辅助函数(XlsxColumnLabel、XlsxCellRef、XlsxColumnIndex、XlsxParseCellRef、XlsxParseRangeRef、XlsxEscapeText、XlsxEscapeAttr),供后续 XLSX 功能使用。
版本 2.16.4
- XLSX façade 单元 lxHandleX 现在定义自己的工作簿和工作表类型(TXLSXWorkbook、TXLSXWorksheet),与 BIFF façade 完全独立。保存和加载入口已预留,OOXML 接入将在后续版本中完成。
- 新增 XLSX façade 开发者参考主题,说明 lxHandle 与 lxHandleX 如何共存以及它们共用的辅助单元。
版本 2.16.3
- 新增专属 XLSX façade 单元
lxHandleX,与现有 BIFF façadelxHandle并列存在。两者共享同一套底层基础设施(样式池、XML 工具、ZIP 归档),但暴露独立的类层级:lxHandle负责TXLSWorkBook与经典 XLS/HTML/RTF/CSV 路径,lxHandleX将负责TXLSXWorkbook及所有 XLSX 专属 API。此前误加到lxHandle的三个方法存根(SetCodePage、GetColumnXFIndex、GetRowXFIndex)已被移出,使 BIFF façade 公开 API 与 v2.15.0 完全一致。现有uses lxHandle的代码无需改动。
版本 2.16.2
- 新增 3 个内部数据结构单元,完成 XLSX 引擎基础的最后一块拼图:
lxAvlTree提供 O(log N) AVL 树(TAVLTree/TAVLNode)用于有序查找;lxCols与lxRows是带细粒度去重与索引重写的列信息与行信息容器,供 XLSX 引擎的列宽和行高映射使用。3 个单元在本版本休眠,将在 v2.17.0 XLSX 读写引擎首次启用时激活。
版本 2.16.1
- 新增 6 个内部 XML / ZIP 工具单元,完成 XLSX 引擎的基础设施层:
lxWStream(带文件存在判断和 AnsiString 写入 helper 的宽字符文件流);lxCacheStream(减少底层 I/O 调用的缓冲流封装);lxZlibStream(前向 deflate/inflate 流 API,与 BIFF 加密路径现有的loZlib绑定相互独立);lxXmlReader(SAX 风格高速 XML 拉式读取器);lxXmlWriter(支持元素名复用的流式 XML 写入器);lxZipArchive(支持逐条 deflate 流的 ZIP 中央目录读写器)。这 6 个单元与 v2.16.0 的 7 个单元共同构成 XLSX 引擎的完整基础设施。
版本 2.16.0
- 新增 7 个内部样式基础设施单元,作为后续 XLSX 引擎的地基:
lxHashTable(含整型 / 宽字符串 / 对象键变体的通用哈希表);lxKeyList(带快速查找与索引重写的对象键列表);lxStyleColor(Office 主题色与调色板槽管理器);lxStyleFont、lxStyleFill、lxStyleBorder(字体、填充、边框样式的去重存储池,涵盖全部 12 种 BIFF 线型与 XLSX 样式映射);lxStyleXf(将上述五个池聚合为带数字格式列表的 XF 记录)。7 个单元在本版本均处于休眠状态,不影响现有 XLS 路径。
版本 2.15.1
- 新增
lxRgb颜色辅助单元:RGBtoHLS、HLStoRGB、RGBTint、GetRGBTint在 RGB 与 HLS 色彩空间(0–240 HLS 范围)之间互转,为后续 XLSX 主题色 tint 计算、色阶条件格式和调色板插值提供基础。 - 新增
lxStrBuilder高性能字符串构造器:TXLSStringBuilder(AnsiChar)与TXLSWideStringBuilder(WideChar)采用预分配 + 倍增扩展缓冲,避免 Pascal 字符串拼接每次重新分配的内存开销;AnsiChar 版用于 XLSX XML 序列化,WideChar 版用于 XLSX 解析器的宽字符串组装。
Version 2.15.0
- 将 HtmlHelp 参考文档重组为适合浏览器直接打开的结构,拆分主题、资源、脚本、样式和源资料目录。
- 新增浏览器友好的帮助首页和目录导航页,并统一页头、主题快捷入口和页脚。