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 範例展示了透過
WriteCellscallback 寫入 range、透過ForEachCell掃描已載入儲存格、透過FindText與ReplaceText更新範本文字、將選取範圍匯出到ApiTour-Range.html,以及 Delphi 端透過OnUserFunction處理自訂公式 callback。
版本 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 參考文件重組為適合瀏覽器直接開啟的結構,拆分主題、資源、指令碼、樣式和源資料目錄。
- 新增瀏覽器友好的幫助首頁和目錄導航頁,並統一頁頭、主題快捷入口和頁尾。