能通过 CI 的电子表格更改
对于重要的电子表格,棘手的问题很少是“哪个文件发生了更改?”而是“是否有人替换了这个数字背后的计算公式,现在它依赖于什么,以及在模型共享之前我们是否注意到了?”
Excel 之所以灵活,是因为模型及其逻辑共存。正是这种灵活性将普通版本历史变成了薄弱的审查表面:Git 看到的是二进制文件,而审查者需要看到意图的变化。
支持工作簿的 Git diff 和 公式异常分析 已经解决了问题的部分价值。我想要缺失的合并边界层:一个小型的本地工具,能够描述语义工作簿更改,追踪其可见后果,并执行审查者可读的规则。
该工具是 FormulaFence,一个 MIT 许可的、本地优先的 CLI,支持 .xlsx 和 .xlsm 工作簿。
将控制权置于合并边界
FormulaFence 比较两个工作簿时不执行公式或宏。它检测公式到值的替换、公式更改、工作表可见性和定义名称更改、显式外部引用、损坏的 #REF! 公式、计算设置更改和宏有效负载更改。
对于每个更改的单元格,它遵循静态可见的 A1 样式和普通命名范围依赖关系,并报告具有确定性最短路径样本的下游公式单元格。
formulafence check approved.xlsx candidate.xlsx \
--policy formulafence.yml \
--format sarif --output results.sarif
Enter fullscreen mode Exit fullscreen mode
策略是纯 YAML。它可以保护输出单元格,将例行编辑限制在输入范围内,禁止公式覆盖,并限制下游影响。它不替代判断;它使审查期望可见且可重复。
version: 1
rules:
no_formula_to_value: true
no_new_external_links: true
no_new_broken_references: true
no_new_parser_warnings: true
no_new_unresolved_references: true
no_new_dynamic_references: true
max_downstream_impact: 100
protected_cells:
- Dashboard!B12
Enter fullscreen mode Exit fullscreen mode
当分析存在盲点时关闭失败
FormulaFence 0.3.0 使用静态 A1 目标解析普通工作簿和工作表本地名称,因此这些引用现在参与影响路径。静态分析仍然有局限性:INDIRECT、OFFSET、命名公式、结构化表引用、加载项和其他 Excel 功能可能会隐藏依赖关系。FormulaFence 不会虚构它无法证实的图。
一个实用的保障是覆盖可见性。当工作簿解析器遇到无法完全解释的 OOXML 扩展时,FormulaFence 会记录覆盖说明。可以使用 no_new_parser_warnings 拒绝添加覆盖说明的候选文件。配置文件现在还列出未解析的范围标记和动态引用函数;可以使用 no_new_unresolved_references 或 no_new_dynamic_references 拒绝更改。
测试超出玩具文件
单元测试装置是必要的,但 Office 文件阅读器也需要满足真实工作簿。我使用公共的 Foresight Cap Table and Exit Waterfall Tool 验证了 FormulaFence:18 个工作表、6,623 个非空单元格和 4,228 个公式单元格。
检查发现了一个不受支持的 OOXML 扩展,并将其记录为结构化覆盖说明,而不是将原始依赖警告泄漏到 CI 输出中。它还识别了 36 个使用 INDIRECT 的单元格,使模型的动态引用表面明确。在本地非分布式副本上,将一个退出瀑布公式替换为数字,追踪了 330 个下游公式单元格;初始策略拒绝了公式覆盖和影响限制。
这些结果是兼容性演示,而不是声称源模型是正确的。完整的限制和验证记录在 FormulaFence 仓库中。
它不声称什么
FormulaFence 不计算 Excel 或证明财务模型正确。重要模型仍然需要合格的所有者、在批准的电子表格引擎中重新计算,以及独立审查。
但审查过程至少应该使默默将公式替换为数字变得困难。这就是 FormulaFence 构建来强制执行的狭窄、有用的边界。
当前版本是 GitHub 上的 FormulaFence 0.3.0。此帖子的规范版本位于 sybilgambleyyu.github.io/posts/formulafence.html。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.