HotXLS 文档

计算与转换保真度

计算数组可以在选择、排序、查找、矩阵和重塑函数之间组合,并带有自动的 XLSX 溢出归属、显式 CSE 目标和有界的求值资源

动态数组与显式 CSE 数组

把产生数组的表达式赋给一个 TXLSXCell.Formula 并调用 TXLSXWorkbook.Recalculate;结果会拥有一个以该单元格为锚点的矩形溢出,适用的公式包括 SEQUENCE(3,2)、A1:A3*10、数组常量以及数组型 LET 结果

Sheet.Cells.Item[1, 1].Formula := 'SEQUENCE(3,2)';
Sheet.Cells.Item[1, 4].Formula := 'SUM(A1#)';
Workbook.Recalculate;

重算会让结果增大或缩小,只清理锚点拥有的过时从属单元格,并在范围变化时重建依赖;对新出现的从属单元格的引用和 A1# 溢出运算符都使用当前范围

既有值、公式、富文本、其他数组、合并区域、表格和工作表边界都会阻碍溢出并产生 #SPILL!;空白单元格上的样式仍可使用,清除阻碍后下一次重算会重试锚点

用值或富文本编辑从属单元格会把该单元格从锚点上分离,下一次计算会把这次编辑当作阻碍保留;删除或清空锚点会释放其拥有的从属单元格,而 ConvertFormulasToValues 会把它们的计算值保留为普通单元格

XLSX 保存会记录当前的数组范围和元数据,加载时会在重算之前恢复对既有缓存从属单元格的归属;包含错误的数组公式只要错误属于个别元素,就仍保留其范围

SetArrayFormula 在两个工作簿引擎中都保留为显式的固定区域 CSE 入口;裸区域算术在该区域内逐元素求值,而普通标量公式保持隐式交集

一元 @ 运算符把引用与公式单元格求交集并取计算数组的第一个元素;SINGLE 与 ANCHORARRAY 作为存储别名被接受,分别对应隐式交集和溢出引用

MAP 接受多个输入数组与匹配的 LAMBDA 参数表,传播元素错误,并对嵌套数组结果以 #CALC! 拒绝;FILTER 接受计算数组和行或列掩码,包括错误传播以及未提供回退值时的空结果 #CALC!

动态溢出变更即使在配置了多个计算线程时也串行执行;范围稳定化最多 32 轮,循环迭代计算中的动态数组会被拒绝,而不是被当作标量结果

INDEX 接受引用、数组常量和计算数组;两个选择器都是标量时,正的行、列选择器返回一个值,零选择器返回选中的整行或整列,两个选择器都为零则返回完整数组;带标量选择器的引用源对 ROW、ISREF 等消费者保持引用行为

行、列选择器也可以是数组,包括常量、计算向量、区域值和 LET 绑定;行列方向相对时广播成矩形叉积,方向一致时按位置成对选取;单元素维度广播,维度不等时缺失的位置返回独立的 #N/A

任一选择器是数组时,零或省略的选择器选取该轴的第一个成员,而不是展开整行或整列;小数选择器向零截断,负数选择器在截断前返回独立的 #VALUE!,超出源边界的选择器返回独立的 #REF!;被选中的字符串、布尔值和类型化错误保留各自类型

SORT 与 UNIQUE 接受区域、常量和计算数组,包括嵌套的 FILTER、SEQUENCE 与 LET 结果;行/列方向、升序或降序、首次出现顺序以及恰好一次去重,对每种源形式遵循同一契约

工作簿级定义名称可以提供引用、标量或计算数组源;ISREF(INDEX(...)) 区分真实的引用结果与命名的计算值;标量 INDEX 选择器和 SORT 的数值选项截断小数,可选的布尔参数对 TRUE/FALSE 以外的文本拒绝

Sheet.Cells.Item[1, 6].Formula := 'SORT(UNIQUE(FILTER(A1:B5,A1:A5>1)),1,-1)';
Sheet.Cells.Item[1, 9].Formula := 'INDEX(SORT(UNIQUE(A1:B5)),0,2)';
Sheet.Cells.Item[1, 12].Formula := 'INDEX(SEQUENCE(2,3,10,2),2,3)';
Workbook.Recalculate;
Sheet.Cells.Item[1, 1].Formula := 'INDEX(SEQUENCE(3,3),{1;3},{1,3})';
Workbook.Recalculate;

这个选择器示例会把 {1,3;7,9} 溢出为 2×2 的结果;INDEX(SEQUENCE(3,3),{1;3},{1;3}) 则返回成对的列 {1;9};数组选择器即使源是引用也产生值,而标量引用选择器保留引用身份

这些表达式既可以在 XLSX 中溢出并缩放,也可以在显式 CSE 目标内求值;数组源的错误保持类型化,恰好一次去重的空结果返回 #CALC!;选择器输出消耗计算步数预算,源、选择器与结果矩阵的合计负载会对照数组内存预算检查

INDEX 对计算源接受显式的第四个 area_num 参数取值 1,行、列与区域选择器可以在受支持的同表引用并集上一起广播;真实的多区域引用经由本地定义名称与 LET 保留身份,而标量 CHOOSE 保留选中的引用,包括另一张表上的选择;选择器数组结果是值而不是嵌套引用数组;零、缺失、强制转换与错误规则参见 INDEX 区域选择与引用身份

独立计算时,TXLSCalculator.OnGetSpillRange 接受 TXLSGetSpillRange 回调来解析锚点当前的闭区间边界;基于工作簿的求值器会自动安装这个回调

TXLSGetSpillRange = function(SheetIndex, AnchorRow, AnchorCol: Integer;
  var LastRow, LastCol: Integer): Integer of object;

lxNormalizeStorageFormula 为 OOXML 规范化编写期的公式语法,lxTryStorageFormulaOperators 翻译溢出与隐式交集运算符,lxApplyXlfnPrefix 加上必需的未来函数前缀;受保护的文本和数组行分隔符保持原样,赋值公式时内存中仍保留调用方的文本

保存不会改变内存中已编写的表达式;重新打开新编写的 XLSX 公式会得到规范的存储语法(逗号参数、无前导 =),与原生 Excel 导入一致;未被改动的导入公式 XML 仍走原有的保留路径

查找、矩阵与重塑组合

TRANSPOSE 接受引用、常量和计算数组,并保留文本、布尔值和个别错误;空白的源单元格变成数字零

MMULT、MDETERM 与 MINVERSE 接受计算矩阵和 MMULT(MUNIT(2),SEQUENCE(2,2)) 这类嵌套表达式;矩阵条目必须是数字,文本、布尔值和空白会被拒绝而不是被强制转换,源错误保留其错误码

CHOOSECOLS 与 CHOOSEROWS 接受标量或一维选择器向量,按参数顺序拼接选择器,保留重复项,负索引从末尾计数;小数选择器向零截断,零与越界选择器拒绝,二维选择器矩阵不受支持

XLOOKUP、XMATCH 与 MATCH 接受计算得到的查找向量和数组型查找请求;键必须占据一行或一列,XLOOKUP 的返回数组必须与该查找轴对齐

标量 XLOOKUP 可以返回整行或整列的匹配内容,包括类型化错误;数组型查找请求保留自身形状,并对每个匹配切片或回退数组取第一个分量

精确查找扫描会跳过键向量中的错误条目;布尔、数字和文本键彼此区分,普通标量引用路径保持既有的流式处理与重算缓存行为;二分查找模式仍要求键已正确排序

VSTACK、HSTACK、TAKE、DROP、TOROW、TOCOL、WRAPROWS、WRAPCOLS 与 EXPAND 接受计算输入和类型化填充;没有行或列的结果返回 #CALC!,折行则要求一维输入

矩阵运算、查找扫描、选择器遍历、复制与填充消耗计算步数预算;同时持有的输入、工作与输出矩阵负载在分配前会对照配置的数组内存上限检查

Sheet.Cells.Item[1, 1].Formula := 'XLOOKUP({1;3},SEQUENCE(3),SEQUENCE(3,2))';
Sheet.Cells.Item[1, 4].Formula := 'CHOOSECOLS(SEQUENCE(2,3),{-1;1})';
Sheet.Cells.Item[1, 7].Formula := 'TRANSPOSE(UNIQUE({"A";"B";"A"}))';
Workbook.Recalculate;

类型化的新式计算错误

#SPILL! 与 #CALC! 在计算、显示、缓存检查和 XLSX 重新打开的整个过程中都保持类型化单元格错误;XLSX 输出携带它们的富值元数据,同时保留标准缓存错误回退,供不认识该扩展的读取器使用

公式文本结果(包括 CSE 与动态数组从属单元格)使用字面字符串缓存,让 Excel 能在重算前显示它们;普通值单元格继续使用共享字符串

新式富错误输出包含 Excel 解读这些缓存所需的工作簿版本与 Rich Data 计算特性声明;写出的 calcId 至少为 191029,更高的请求值保持不变,工作簿内存中的 CalcId 属性也不受影响

导入的单元格与值元数据、无关的富值结构和不透明的桶在追加新错误桶时保留原始身份;替换错误单元格会在保存时清理过时的类型化错误元数据

TXLSXRichErrorCodes 是解码富错误桶所用的整数数组类型;应用代码从单元格的 Variant 值读取类型化错误

BIFF8 无法忠实地表示这些新式错误和溢出运算符;Classic 序列化器会拒绝不支持的新式表示,而不是随意指派一个不相干的旧式错误码

转换预检

TXLSXWorkbook.GetConversionReport 返回一个由调用方持有的 TXLSConversionReport,不重算也不修改工作簿;类型声明在 lxDiagnostics 中

Report := Workbook.GetConversionReport(xlsConversionOpenDocument);
try
  for I := 0 to Report.Count - 1 do
    InspectIssue(Report.Items[I]);
finally
  Report.Free;
end;
TargetxlsConversionOpenXmlWorkbook, xlsConversionOpenXmlTemplate, xlsConversionMacroEnabledTemplate, xlsConversionOpenDocument, xlsConversionExcel97Workbook, or xlsConversionExcelBinaryWorkbook
FidelityTXLSConversionFidelity: xlsConversionPreserved, xlsConversionDegraded, xlsConversionDropped, or xlsConversionUnsupported
IssueTXLSConversionIssue 公开 Feature、Fidelity、SheetIndex、SheetName、Location 与 Message;HasLoss 涵盖降级、丢弃与不支持三类条目

报告会清点已知的格式损失,例如 VBA、保护、工作簿视图、连接、查询表、批注、外部链接、XML 映射、表格结构、筛选条件、绘图、类型化错误缓存、不受支持的校验或公式语法、数组归属以及不透明的扩展部件;它描述的是已实现的转换路径,并不为每个功能在每个外部应用中的表现背书

ODS 保留普通表格单元格、缓存的公式结果、受支持的批注文本与作者、无密码的工作表保护以及可表示的筛选器,同时丢失 Excel 表格对象、更丰富的图表几何或不支持的规则语义;当目标格式无法承载某个不透明的 OOXML 保留负载时,报告中会记为丢弃

XLSX 门面把 BIFF8 输出报告为不支持;受支持的 BIFF 工作流请使用 Classic 工作簿 API;版本 2.384.93 新增了有界的 XLSB 值与样式后端,无论受检还是不受检保存,都会拒绝未表示的公式、特性对象、元数据和计算设置

受检保存

Status := Workbook.SaveAsChecked(Stream,
  xlsxOpenDocumentSpreadsheet, False);

文件与流重载都会在写入前运行已知损失预检;AllowLossy=False 会以转换诊断拒绝降级或丢弃的特性,而 AllowLossy=True 显式接受这些损失,但仍拒绝不支持的转换

预检被拒绝时目标字节与流位置保持不变;成功的请求走既有的保存事务,并返回与 SaveAs 相同的保存状态约定

普通 SaveAs 仍按既有行为可用;需要显式损失决策的应用应先检查报告,再使用受检保存

模板格式

xlsxOpenXMLTemplate 选择无宏的 XLTX,xlsxOpenXMLMacroEnabledTemplate 选择 XLTM 并保留既有 VBA 工程;格式是显式选择的,不会从文件扩展名或导入的模板推断

无宏 XLTX 即使启用了有损受检保存也会拒绝带 VBA 的工作簿;XLTM 包可以在没有 VBA 工程的情况下写出,HotXLS 不会创建 VBA 代码

ODS 校验公式

自定义布尔校验使用 of:is-true-formula(...);受支持的标量边界、列表源、限定 A1 引用、字符串与参数分隔符会翻译为 OpenFormula,并在导入时以校验基准单元格地址为基准重新定位

不受支持的结构化、外部或三维校验表达式会连同其单元格引用一起被省略,避免留下悬空的校验定义;转换预检会报告这些被省略的规则

ODS 批注、保护与筛选

普通单元格批注以 OpenDocument 批注的形式导出,带文本与作者,包括空批注、制表符、空格和换行;落在原本不存在的单元格和远距离坐标上的批注使用稀疏的重复行/列段,不会创建工作表单元格

合并区域锚点单元格上的批注保留其地址;被覆盖单元格上或工作表网格之外的批注会报告为丢弃;富文本批注会被压平为显示文本,转换报告会指出 run 样式、自定义框尺寸与始终可见呈现的损失

OpenDocument 的保护标志与受支持的锁定/解锁单元格样式会被保留;无损工作表子集不使用密码或可编辑区域例外,仅允许选中锁定与未锁定单元格

Sheet.Protect;
Sheet.SheetProtectionOptions :=
  [xlsxSpoSelectLockedCells, xlsxSpoSelectUnlockedCells];
Sheet.Range['B2:B100'].Locked := False;

该子集之外的 Excel 密码哈希、新式密码设置、可编辑区域与操作权限会报告为降级,同时保留保护标志;Excel 宽泛的默认权限集同样需要显式的损失决策

OpenDocument 导入保留保护标志与单元格锁定样式;原生密码哈希不会转换为 Excel 哈希,未表示的导入权限元数据在后续转换报告中仍是一项具名损失

AutoFilter 导出支持六个标量比较运算符、每列最多两个以 AND 或 OR 连接的标量条件,以及列之间的一个 AND;受支持的纯值选择列表和空白选择没有双值数量限制,仍保留为原生筛选元数据

数值标量条件使用不变文化的有限值;文本选择保留字面字符,包括选择列表内的通配符,而自定义筛选中的通配符表达式、含糊的布尔条件、日期分组、动态日期、颜色与图标筛选没有等价的受支持转换

不受支持的筛选表达式会作为完整表达式被省略,而不是弱化部分条件;筛选区域保留,转换报告会指出被省略的条件

ODS 流式保存会把完成的包先暂存到注册的临时文件,再写到目标原始位置;既有的前缀字节与绝对 ZIP 偏移被保留,包括超出原文件末尾的位置;提交前取消或进度回调抛出异常会保留目标字节、大小与位置并释放临时文件;最终的写入通知不可取消

OpenDocument 导入支持同样的标量合取以及同列的文本析取或值集;跨列 OR、正则表达式、区分大小写的比较和不受支持的原生筛选运算符仍是显式记录的导入损失

TXLSXOdsImportLoss 与 TXLSXOdsImportLosses 描述私有工作表来源类别;转换报告使用 ImportedOdsProtectionPassword、ImportedOdsProtectionOptions、ImportedOdsFilterCriteria 与 ImportedOdsCommentFormatting;它们在工作表复制后保留,并且对 OpenDocument 与 Open XML 转换目标都会出现

筛选转换保留元数据与既有的行可见性,不应用筛选也不重算单元格;各原生应用自行负责其筛选与编辑行为

相关工作流