傳統 XLS 與 XLSX 公開相同的無副作用合約,用於在呼叫端變更儲存格之前分類公式輸入
共用原則
TXLSFormulaEmptyStringMode =
(xlfesmClearCell, xlfesmPreserveString);
TXLSFormulaUnknownSymbolMode =
(xlfusmReject, xlfusmPreserve);
TXLSFormulaEntryPolicy = record
EmptyStringMode: TXLSFormulaEmptyStringMode;
UnknownFunctionMode: TXLSFormulaUnknownSymbolMode;
UnknownNameMode: TXLSFormulaUnknownSymbolMode;
end;
property FormulaEntryPolicy: TXLSFormulaEntryPolicy;
傳統 IXLSWorkbook 與 TXLSWorkbook 連同 TXLSXWorkbook一併公開此屬性; XLSDefaultFormulaEntryPolicy 會清空空白輸入,並拒絕未知函式與未知的已定義名稱
活頁簿屬性以傳值方式複製,並在指派時以不可分割的方式驗證,因此不支援的列舉值會引發 EArgumentOutOfRangeException ,而不會改變先前的原則
驗證結果
function ValidateFormulaEntry(Row, Col: Integer;
const Formula: WideString): TXLSFormulaEntryValidationResult;
TXLSFormulaEntryValidationResult = record
Issue: TXLSFormulaEntryIssue;
Action: TXLSFormulaEntryAction;
Symbol: WideString;
end;
Issue 區分無錯誤、未知函式、未知名稱、語法錯誤、目標格式限制,以及無效的目標座標
Action 選擇清空儲存格、儲存字串、儲存公式或拒絕;當辨識出未知函式或名稱時, Symbol 會識別它
空白文字與公式
完全空白的輸入會依據 xlfeaClearCell 傳回 xlfeaStoreString 或 EmptyStringMode
傳回空字串的公式(例如 ="")仍然是公式,並在目標格式能夠表示它時傳回 xlfeaStoreFormula when the target format can represent it
公式文字可以包含或省略開頭的一個等號
現在透過正常的傳統 XLS 或 XLSX 儲存格 Value 屬性指派完全空白的字串,會直接套用此模式:預設行為會移除任何既有的值或公式,而 xlfesmPreserveString 則以長度為零的常數字串取代儲存格內容
Null 與 Unassigned 一律清空儲存格,而諸如 ="" 的真實公式仍然是公式,並帶有獨立儲存或計算出的空字串結果
XLSX 的字串與 Variant 列或欄寫入器套用相同規則,且不會具體化被清空的空洞;只要其餘值在該儲存方式中可表示,就保持打包儲存
原生 XLS、XLSX 與 ODS 讀取器,以及 XLS 轉 XLSX 或 XLSX 轉 XLS 轉換器,都將儲存的值視為可信輸入,因此即使目標活頁簿保留預設的使用者輸入原則,檔案層級的常數空字串仍會保留下來
未知符號與目標格式
已註冊的活頁簿層級或處理程序層級使用者函式,以及已指派的 OnUserFunction 或 OnUserFunctionEx 回呼,在驗證期間視為已知,且不會呼叫處理常式;未註冊的呼叫會在 Symbol
嚴格模式對未知函式或名稱傳回 xlfeaReject ;透過正常的儲存格 Formula 屬性指派,會在變更值、公式快取或相依性之前予以拒絕
保留模式會保留診斷資訊,並透過正常的儲存格 API 儲存公式;傳統 XLS 透過 BIFF 增益集使用者函式語彙基元序列化未知呼叫,並在儲存、重新開啟與 XLS/XLSX 轉換的過程中保留未知名稱文字
傳統 XLS 還會透過 BIFF 寫入器編譯已知公式,並在運算式無法表示時傳回 xlfeiTargetFormatUnsupported ;XLSX 則接受其公式模型支援的已知現代公式函式
XLSX 驗證可辨識 LAMBDA、語彙的 LET 可呼叫項目、參照 lambda 的已定義名稱、報表預留位置、已註冊的外部活頁簿連結,以及有效的限定或未限定結構化參照(包括巢狀形式與目前列形式)
相容模式還可以保留未解析的外部結構化參照以供後續處理,而嚴格模式仍會拒絕未解析的資料表名稱
計算與批次稽核
經過 lambda 與使用者函式分派後仍未處理的被保留未知函式,或被保留的未知名稱,會評估為代碼 $1D的 Variant 錯誤,亦即 Excel 的 #NAME? 錯誤;同樣的具型別錯誤會傳播至相依公式與內容相關評估
已知但未實作的內建函式仍與未知呼叫有所區別;註冊、取代、移除或清除活頁簿層級或處理程序層級使用者函式,以及變更已定義名稱的公式,都會使過期的相依性與計算狀態失效
function AuditFormulaSymbols: TXLSFormulaSymbolIssues; overload;
function AuditFormulaSymbols(
out AStats: TXLSFormulaSymbolAuditStats):
TXLSFormulaSymbolIssues; overload;
TXLSFormulaSymbolIssueKind = (xlfsiUnknownFunction, xlfsiUnknownName,
xlfsiSyntaxError);
TXLSFormulaSymbolLocationKind = (xlfslCell, xlfslDefinedName);
TXLSFormulaSymbolIssue = record
Kind: TXLSFormulaSymbolIssueKind;
LocationKind: TXLSFormulaSymbolLocationKind;
Sheet: Integer;
Row: Integer;
Col: Integer;
DefinedNameIndex: Integer;
DefinedName: WideString;
Formula: WideString;
Symbol: WideString;
end;
TXLSWorkbook 與 TXLSXWorkbook 提供相同的批次稽核多載;每個問題都會識別未知函式、未知名稱或語法錯誤,並同時提供工作表儲存格位置(LocationKind = xlfslCell)或已定義名稱位置(LocationKind = xlfslDefinedName)、來源公式,以及未解析的符號
稽核周遊的是解析後的公式樹或儲存的 BIFF 語彙基元,而不是掃描文字,因此字串內類似函式的文字不會被回報;XLSX 編譯使用作業本地快取,其金鑰由解析後的公式文字、工作表、地區設定、已定義名稱的世代、使用者函式登錄的世代,以及回呼的可用性組成
EntryCount 報告已稽核的公式, UniqueFormulaCount 報告獨立編譯或檢查的公式, CacheHitCount 報告由作業快取服務的重複項目
不修改工作表
驗證不會建立或編輯儲存格,不會變更快取的值,不會更新相依性圖形,不會將活頁簿標記為已修改,也不會呼叫已註冊的使用者函式處理常式
直接驗證始終保持不修改;正常的公式指派會在內部套用相同決策,並且只有在驗證與目標格式準備成功後才會認可
Delphi 範例
Policy := Workbook.FormulaEntryPolicy;
Policy.UnknownFunctionMode := xlfusmReject;
Policy.UnknownNameMode := xlfusmReject;
Workbook.FormulaEntryPolicy := Policy;
Validation := Sheet.ValidateFormulaEntry(4, 2, FormulaText);
if Validation.Action = xlfeaStoreFormula then
Sheet.Cells[4, 2].Formula := FormulaText;
Issues := Workbook.AuditFormulaSymbols(Stats);
for I := 0 to High(Issues) do
if Issues[I].Kind = xlfsiUnknownFunction then
LogUnknownSymbol(Issues[I].Symbol);另請參閱