SaveSemanticSnapshot 與 ComputeSemanticHash 方法
串流輸出帶版本號的活頁簿語意規範表示,或計算恰恰這些位元組的 SHA-256
語法
procedure SaveSemanticSnapshot(AStream: TStream); overload; procedure SaveSemanticSnapshot(AStream: TStream; AProfile: TXLSSemanticSnapshotProfile; AOptions: TXLSSemanticSnapshotOptions); overload; function ComputeSemanticHash: WideString; overload; function ComputeSemanticHash( AProfile: TXLSSemanticSnapshotProfile; AOptions: TXLSSemanticSnapshotOptions): WideString; overload;
這些方法由 IXLSWorkbook 中的傳統 TXLSWorkbook 與 lxHandle,以及 TXLSXWorkbook 中的 lxHandleX
設定檔與選項型別宣告於 lxSemanticSnapshot ,並可透過兩個活頁簿單元看到
設定檔
| 值 | 意義 |
|---|---|
xlsspContent | 規範的活頁簿內容,適用於一般的語意同一性檢查 |
xlsspSecurityComplete | 內容加上受支援的不透明安全性與保留狀態,這些狀態被刻意排除在一般內容同一性之外 |
選項
| 值 | 包含的狀態 |
|---|---|
xlssoIncludeViewerState | 選取、作用中檢視狀態,以及其他受支援的檢視器導向狀態 |
xlssoIncludeVolatileMetadata | 受支援的時間戳記、產生者中繼資料,以及其他刻意多變的欄位 |
xlssoIncludeFormulaCachedResults | 儲存的公式結果與受支援的外部連結快取,不進行重新計算或外部 I/O |
The option set has type TXLSSemanticSnapshotOptions = set of TXLSSemanticSnapshotOption無參數的多載使用 xlsspContent 與空的選項集合
串流與同一性規則
SaveSemanticSnapshot寫入目標資料流的目前位置,不會定位、擁有或釋放該資料流- 下游寫入失敗可能在目標中留下前置部分,因此需要不可分割發行的呼叫端應先寫入暫時目標,再取代最終目標
ComputeSemanticHash傳回 64 個小寫十六進位字元,並以增量方式計算雜湊,而不需配置完整的快照緩衝區- 此快照是 HotXLS 語意協定,不是 XLS、XLSX、ODS、CSV 或 PDF 文件
- 僅在協定版本、設定檔與選項集合都一致時才比較快照或雜湊
- 此作業不會儲存、重新計算、重新整理連結、存取外部資源,也不會修改活頁簿快取
現代儲存格功能
TXLSSemanticCellStyle.CellControlKind 的型別為 TXLSSemanticCellControlKind ,含 xlssControlNone、 xlssControlUnknown與 xlssControlCheckbox; CellControlDefaultState 的型別為 TXLSSemanticCheckboxDefaultState ,含 xlssCheckboxUnchecked、 xlssCheckboxChecked與 xlssCheckboxBlank
XLSX 樣式讀取會解析直接與繼承的控制項而不建立儲存格;標準樣式序列化遇到 xlssControlUnknown 會拒絕,而不是把未知屬性 bag 當成普通儲存格
快照與雜湊包含正規化後的有效控制項矩形,合併相鄰的相等區域而不把整欄展開成儲存格;無關的非預設樣式覆蓋保留其既有的不受支援正規化界限
TXLSXWorkbook.ReadSemanticFeatures(xlsxSemanticCellImages, Sheet, AMaxBytes, AMaxItems) 回傳以儲存格位址為鍵值的分離項目,包含確切編碼的 PNG 或 JPEG 位元組、內容型別、替代文字與裝飾性中繼資料;配額涵蓋標準位元組與圖片項目,過大的承載會在複製前被拒絕
選取 lcoDrawings 時,活頁簿比較包含這些圖片定義,而 lcoCellStyles 與 lcoBlankStyleRegions 則包含有效的核取方塊格式;只有相符的後備錯誤並不會讓不同的圖片視為相等
未知的 rich-value 圖片圖會在選定的功能比較或快照走訪期間引發 EXLSSemanticSnapshot;這些操作保留活頁簿讀取租約,且不計算被檢查的儲存格
並行與錯誤
兩個方法在整個周遊期間都持有活頁簿讀取租約
並行的公開修改會在變更活頁簿狀態之前以 EXLSWorkbookWriteGuardUnavailable失敗,而偵測到的世代變更或不受支援的歧義語意結構會引發 EXLSSemanticSnapshot
Delphi 範例
var
Snapshot: TFileStream;
Hash: WideString;
begin
Snapshot:= TFileStream.Create('workbook.semantic', fmCreate);
try
Workbook.SaveSemanticSnapshot(Snapshot,
xlsspSecurityComplete,
[xlssoIncludeFormulaCachedResults]);
finally
Snapshot.Free;
end;
Hash:= Workbook.ComputeSemanticHash;C++Builder 範例
TFileStream *snapshot = new TFileStream(
L"workbook.semantic", fmCreate);
try
{
workbook->SaveSemanticSnapshot(snapshot);
}
__finally
{
delete snapshot;
}
WideString hash = workbook->ComputeSemanticHash();快照模型參考
快照引擎不綁定活頁簿物件:以下所有內容都宣告在 lxSemanticSnapshot中,活頁簿方法只是同一批全域進入點的薄包裝
擴充介面
實作 IXLSSemanticWorkbookSource 即可對任何來源輸出快照或計算雜湊,並可選擇性實作 IXLSSemanticFormulaResolver ,讓輸出的公式帶有已解析的外部參照與已定義名稱資訊
IXLSSemanticWorkbookSource = interface
procedure WriteCommon(AWriter: TXLSSemanticCanonicalWriter);
end;
IXLSSemanticFormulaResolver = interface
function ResolveFormulaReference(AExternID: Integer;
out AInfo: TXLSSemanticFormulaReferenceInfo): Boolean;
function ResolveFormulaName(ANameID, AExternID: Integer;
out AInfo: TXLSSemanticFormulaNameInfo): Boolean;
end;
TXLSSemanticFormulaReferenceInfo = record
LinkKind: TXLSSemanticFormulaLinkKind;
BookName: WideString;
FirstSheetName: WideString;
LastSheetName: WideString;
end;
TXLSSemanticFormulaNameInfo = record
NameKind: TXLSSemanticFormulaNameKind;
LinkKind: TXLSSemanticFormulaLinkKind;
Name: WideString;
ScopeSheetName: WideString;
BookName: WideString;
end;在 WriteCommon 裡,writer 是一個不透明控制代碼:不要直接呼叫它的基元方法 —— BeginContainer / EndContainer 框出一個帶標籤的容器, WriteNull、 WriteBoolean、 WriteUInt32、 WriteUInt64、 WriteInt32、 WriteInt64、 WriteBinary64、 WriteWideString與 WriteBytes 各編碼一個 canonical 基元, Finish 封住串流、 Finished 回報完成 —— 請把它交回給下面的輸出輔助方法,讓每個生產者輸出完全一致的位元組
進入點全域函式
procedure XLSSaveSemanticSnapshot(AStream: TStream; const ASource: IXLSSemanticWorkbookSource; AProfile: TXLSSemanticSnapshotProfile; AOptions: TXLSSemanticSnapshotOptions); function XLSComputeSemanticHash( const ASource: IXLSSemanticWorkbookSource; AProfile: TXLSSemanticSnapshotProfile; AOptions: TXLSSemanticSnapshotOptions): WideString; procedure XLSInitializeSemanticCellStyle(out AStyle: TXLSSemanticCellStyle); function XLSBuiltinSemanticNumberFormat(AId: Word): WideString;
XLSInitializeSemanticCellStyle 會以 canonical 預設值填滿樣式記錄,之後再個別修改欄位; XLSBuiltinSemanticNumberFormat 把內建數字格式 id(低於 164)對應到它的格式字串,消費端解讀輸出的樣式與解碼串流時會需要它
模型詞彙
| Group | Types |
|---|---|
| Sheet | TXLSSemanticSheetKind (worksheet、macro、chart、VBA、unknown)、 TXLSSemanticSheetVisibility (visible、hidden、very hidden)、 TXLSSemanticDefinedNameScope (活頁簿或工作表)、 TXLSSemanticRange / TXLSSemanticRanges (合併、條件式格式與資料表使用的矩形範圍) |
| Cell | TXLSSemanticCellKind (blank、number、datetime、text、boolean、error、formula) |
| Style | TXLSSemanticCellStyle (完整 canonical 儲存格樣式)、帶 TXLSSemanticColor (none、automatic、system、ARGB、theme、indexed)與色調的 TXLSSemanticColorKind 、 TXLSSemanticBorderEdge / TXLSSemanticBorderStyle、 TXLSSemanticFillPattern、 TXLSSemanticGradientKind / TXLSSemanticGradientStop / TXLSSemanticGradientStops、 TXLSSemanticUnderline、 TXLSSemanticFontVerticalAlign |
| Formula | TXLSSemanticFormulaEncoding (剖析樹或不透明文字)、 TXLSSemanticFormulaArrayKind (none、CSE、dynamic)、 TXLSSemanticFormulaNodeKind、 TXLSSemanticFormulaRangeKind、 TXLSSemanticFormulaLinkKind (同工作表、內部、外部、增益集、DDE、OLE、其他)、 TXLSSemanticFormulaNameKind |
| Drawing and charts | TXLSSemanticDrawingKind (image、textbox、chart、group、form control)、 TXLSSemanticDrawingAnchorMode (移動並調整大小、僅移動、絕對)、 TXLSSemanticImageFormat、 TXLSSemanticChartFamily |
輸出輔助方法
這些全域函式會把一個模型片段寫進傳給 WriteCommon的 writer: XLSWriteSemanticLiteralCell、 XLSWriteSemanticCellStyle、 XLSWriteSemanticColor、 XLSWriteSemanticRanges、 XLSWriteSemanticMerge、 XLSWriteSemanticAxisEntry、 XLSWriteSemanticFormulaTree、 XLSWriteSemanticFormulaDefinition,以及 XLSWriteSemanticFormulaCell (公式儲存格會帶陣列界限與選擇性的快取結果)。 XLSWriteSemanticWorkbookCommon 會開啟活頁簿容器並呼叫 WriteCommon,自訂來源通常會先呼叫它