在 Excel 里直接用 =STATS.MEAN()、=STR.REVERSE()、=JSON.PARSE() 等函数。 基于 C# 高性能实现,Python 级精度。net48 版本自带 IntelliSense 参数提示(net8.0 版本因 Excel-DNA 已知问题不提供,见已知限制),VBA 中可通过 Application.Run 直接调用。完整函数清单与数量见 API 参考(数字唯一信源,测试状态见上方 CI 徽章)。
Win10/11 自带 .NET Framework 4.8,直接加载 net48 版本的 .xll:
⚠️ 从 GitHub 下载的.xll需先「解除锁定」:Windows 会将从互联网下载的文件标记为「来自其他计算机」。若 Excel 加载时报「此文件来自其他计算机,可能被阻止以帮助保护该计算机」,请先:右键.xll→ 属性 → 底部「安全」区域勾选「解除锁定」→ 确定,再按下方步骤加载。
- Excel → 文件 → 选项 → 加载项 → 管理:Excel 加载项 → 转到 → 浏览
- 选择
.xll文件,点击确定 - 看到安全提示点"启用"
| 文件 | 包含模块 |
|---|---|
Analytics-AddIn-net48-packed.xll |
STATS · LINALG · REGRESS · SOLVE · PHYCHEM · DOE(需 .NET Framework 4.8,32 位) |
Analytics-AddIn-net48-64-packed.xll |
STATS · LINALG · REGRESS · SOLVE · PHYCHEM · DOE(需 .NET Framework 4.8,64 位) |
Analytics-AddIn-net8.0-packed.xll |
STATS · LINALG · REGRESS · SOLVE · PHYCHEM · DOE(需 .NET 8 运行时,32 位) |
Analytics-AddIn-net8.0-64-packed.xll |
STATS · LINALG · REGRESS · SOLVE · PHYCHEM · DOE(需 .NET 8 运行时,64 位) |
DataToolkit-AddIn-net48-packed.xll |
STR · DT · REGEX · ARR · DICT · JSON/XML · PIVOT · SQL · FS · RANGE(需 .NET Framework 4.8,32 位) |
DataToolkit-AddIn-net48-64-packed.xll |
STR · DT · REGEX · ARR · DICT · JSON/XML · PIVOT · SQL · FS · RANGE(需 .NET Framework 4.8,64 位) |
DataToolkit-AddIn-net8.0-packed.xll |
STR · DT · REGEX · ARR · DICT · JSON/XML · PIVOT · SQL · FS · RANGE(需 .NET 8 运行时,32 位) |
DataToolkit-AddIn-net8.0-64-packed.xll |
STR · DT · REGEX · ARR · DICT · JSON/XML · PIVOT · SQL · FS · RANGE(需 .NET 8 运行时,64 位) |
版本选择:64 位 Excel 选文件名含
64的.xll,32 位 Excel 选不含的。-net48版本无需额外安装运行时(Win10/11 自带),-net8.0版本性能更优但需安装 .NET 8 运行时。两个加载项可同时加载,也可按需只装一个。
- 下载 .NET Desktop Runtime 8.0(约 50 MB),双击安装
- 验证:命令行运行
dotnet --list-runtimes,应出现Microsoft.NETCore.App 8.0.x - 加载 net8.0 版本的
.xll(路径在net8.0-windows/publish/下)
在任意单元格输入 =STATS.MEAN(,Excel 弹出函数自动补全即成功(net48 包)。
net8.0 包:因 Excel-DNA 已知问题无参数提示(见已知限制),输入完整公式
=STATS.MEAN(A1:A10)能算出结果即安装成功。
| 模块 | 做什么 | 试一试 |
|---|---|---|
STATS.* |
均值/方差/分位数/t检验/相关/相关矩阵… 对标 scipy | =STATS.SUMMARY(A1:A100) |
STR.* |
反转/提取/编解码/编辑距离/格式化… | =STR.TEXTJOIN(",", TRUE, A1:A10) |
REGEX.* |
正则匹配/替换/捕获组(Excel 原生没有) | =REGEX.MATCH(A1, "\d+") |
DT.* |
ISO 周/工作日/年龄/复活节/时间戳… | =DT.AGEYEARS(B2, TODAY()) |
ARR.* |
排序/筛选/去重/切片/打乱… | =ARR.UNIQUE(A1:A100) |
JSON.* / XML.* |
解析 JSON、XPath 查询 | =JSON.QUERY(A1, "0.Name") |
DICT.* |
频率统计/交集/并集/键值查找 | =DICT.FREQUENCY(A1:A100) |
LINALG.* |
行列式/求逆/特征值/SVD/QR/LU… | =LINALG.SOLVE(A1:C3, D1:D3) |
REGRESS.* |
OLS/WLS/岭回归/ANOVA/因子重要性 | =REGRESS.OLS(A1:A100, B1:C100) |
SOLVE.* |
工艺参数反解:给定输出目标反推可调参数(多目标/边界/可达性/速率模型时间外推) | =SOLVE.INVERSE(A1:C11) |
PHYCHEM.* |
分子量/温度/压力/体积/质量换算 | =PHYCHEM.C_TO_F(100) |
DOE.* |
实验设计矩阵(全因子设计,对齐 Minitab/JMP) | =DOE.PLAN(2,2,0,2,"full",FALSE) |
SQL.* |
对 Excel 区域写 SQL 查询 | =SQL.QUERY(A1:D100, "SELECT Col1, AVG(Col3) FROM data GROUP BY Col1") |
PIVOT.* |
透视表/逆透视/分组聚合/交叉连接 | =PIVOT.GROUPBY(A1:C100, {1}, 3, "avg") |
RANGE.* |
导出 HTML/JSON/Markdown/CSV | =RANGE.TOMD(A1:D10, TRUE) |
FS.* |
读写文件/列目录/复制删除 | =FS.READ("C:\data.txt") |
加载 .xll 后,所有函数可通过 Application.Run 直接调用,无需引用或声明。详见 API 参考 → VBA 调用。
所有函数支持数组输入。Excel 365 中自动溢出(spill),旧版按 Ctrl+Shift+Enter。
=STATS.MEAN(A1:A100) ' 标量结果
=STATS.ABS(A1:A10) ' 逐元素,返回数组
=LINALG.MATMUL(A1:C3, E1:G3) ' 矩阵乘法,返回二维数组
多参数函数自动广播(broadcast)。标量参数广播到数组尺寸,等长数组逐元素配对。尺寸不匹配返回 #VALUE!。
=STR.STARTSWITH(A1:A10, B1) ' 标量 B1 广播到整个数组
=STATS.COVAR(A1:A10, B1:B10) ' 等长数组逐元素配对
=STATS.SUMMARY(A1:A100) ' 一键输出 count/mean/stdev/min/Q1/median/Q3/max/IQR
=DT.AGEYEARS(DATE(1990,5,15), TODAY()) ' 计算年龄
=REGEX.MATCHALL(A1, "\d+") ' 提取所有数字
=JSON.QUERY(A1, "results[0].name") ' 从 JSON 中取字段
=SQL.QUERY(A1:D500, "SELECT Dept, AVG(Salary) FROM data GROUP BY Dept")
=FS.READ("C:\Users\Public\Documents\data.txt")
函数返回两类错误值:#VALUE!(输入/执行错误,用户可修正)和 #NUM!(计算结果无定义,数据本身不满足数学条件)。
- Excel 错误值(
#N/A、#DIV/0!等)在 MapOver 层透传,在统计函数中被跳过 - 空白单元格:MapOver 函数中透传为空;统计函数中按哨兵 NaN 处理(区域含空 →
#NUM!,不跳过——与 ExcelAVERAGE跳过空值不同,见已知限制) - 非数值单元格经类型转换后返回哨兵值(
0/false/""),不视为错误 - 所有输入被过滤时返回
#VALUE!或NaN
完整错误清单见 API 参考 → 错误参考(唯一信源)。
⚠️ 重要:FS.*函数默认无路径限制(SandboxRoot为null),可访问任意文件系统路径。 若分发给不受信任的用户,请务必在AddIn.cs的AutoOpen()中启用沙箱:
FileSystemCore.Initialize(new SandboxConfig(@"C:\Users\Public\Documents"));配置为不可变 record,启动时一次性设定,消除运行时竞态。越界访问返回 #VALUE!。沙箱支持 NTFS 重解析点(junctions/symlinks)逐段检查。
数据 INSERT 使用参数化查询,列名经字母数字消毒。用户提供的 SQL 语句本身不可参数化——请在可信输入上使用。
所有 REGEX.* 函数内置 5 秒超时,防止 ReDoS 攻击导致 Excel 挂起。
- 双 .NET 版本全量测试,覆盖正常路径和退化输入(零值/空值/单元素/全等值)
- Python 交叉验证:Stats/Regression 与 numpy/scipy 逐项对照,精度 1e-10;DataToolkit 集成管道测试覆盖跨模块组合
- 手册验证:228/240 个 UDF 有硬编码期望值的手册示例,由 Python 独立复算逐项对照(防自校验);
verify-manual.py按双通道分报:manual-only 235 / cross-validated 197(合计 432 项检查;基线 2026-09-15,实际计数以脚本输出为准),其中真正与 C# 实现对照的 UDF 为 124/240(51.7%)(其余 12 个无独立示例的 *_ASYNC/共享 Core 变体由 UDF 层测试覆盖)
- net48 加载项:加载后在公式栏输入函数名时显示参数名浮动提示。
- net8.0 加载项:无参数提示。这是 Excel-DNA 已知 bug(Issue #343)——.NET 8 下
ExcelSynchronizationContext.Post内部空引用。UDF 函数计算、公式列表完全不受影响。
变通方案:选中含函数名的单元格后按
Ctrl+Shift+A插入参数名占位符;或使用 Excel 的fx按钮查看函数参数对话框。
极少数情况下 Excel 会报 Unexpected error trying to run SyncMacro for queued macro execution(AccessViolationException / TargetInvocationException)——这是 Excel-DNA 框架的已知问题(Excel-DNA Issue #390,open 状态),与 Excel 语言版本(非英语环境更易触发)、Office Click-to-Run 版本及计算时序相关,与本加载项的函数逻辑无关。本地 120 秒压力测试(含 *_ASYNC 异步 UDF 持续重算)未复现。
如频繁出现可尝试:① 卸载后重新加载加载项;② 避免在复杂工作簿中反复使用 *_ASYNC 函数;③ 临时禁用 net48 IntelliSense(注释 AddIn.AutoOpen 中的 IntelliSenseServer.Install() 后重新打包)。本加载项仅通过 Excel-DNA 官方机制使用异步队列(net48 IntelliSense 安装 + 异步 UDF 结果回传),未排队任何业务宏。
STATS.*/REGRESS.* 等统计函数对空白单元格按哨兵 NaN 传播(区域含空 → #NUM!),与 Excel 原生 AVERAGE/SUM 的"跳过空值"不同。需要跳过时请先用 FILTER/IF 或 ARR.FILTER 清洗数据。
两个加载项(Analytics + DataToolkit)已加载时,建议逐一卸载(先取消勾选一个,确定后再取消另一个)。
- Excel → 文件 → 选项 → 加载项 → Excel 加载项 → 转到
- 取消勾选加载项,确定
- 彻底删除:移除
.xll文件;如需卸载 .NET 8 Runtime,在 Windows 设置 → 应用 中操作
UDF 层 (public static, [ExcelFunction]) ← 入口:仅分发与适配
↓ MapOver / MapOverMulti / V() 分发
Core 层 (internal static, 纯逻辑) ← 零 Excel 依赖
↓ 依赖
Foundation (共享工具) ← InputNormalizer, MapOver, OutputWrapper
- ✅ UDF 不包含业务逻辑;Core 不引用
ExcelDna.Integration - ❌ 禁止跨层直接调用或反向依赖
- 双 TFM:net48(免安装,Win10/11 自动可用)+ net8.0(性能更优)
- 哨兵契约 L1-L5:不可转换值返回零值哨兵,不抛异常
- MapOver 抽象:消除 ~3000 行重复样板代码
dotnet restore
dotnet build -c Release
dotnet test产物:src/*/bin/Release/{net8.0-windows|net48}/publish/
| 文档 | 角色 | 内容 |
|---|---|---|
| README.en.md | 英文入口 | English entry for international users |
| API 参考 | 数字唯一信源 | 函数完整签名、参数说明、错误表 |
| 用户手册 | 学习教程 | 每个函数详细示例 + 结果解读指南 |
| context.md | 术语表 | 所有术语唯一定义 |
| AGENTS.md | 项目宪法 | 架构分层、红线规则、开发流程 |
| skill: excel-dna-project | 编码规范 | MapOver 选型、预防规则、测试模式 |
| skill: excel-dna-addins | 打包分发 | UDF 声明、黄金法则、.xll 打包 |
本项目遵循 Harmonization 治理规范 模板体系:
| 文件 | 面向 | 职责 |
|---|---|---|
AGENTS.md |
AI 编程助手 | 项目宪法——架构、红线、编码准则、防幻觉铁律 |
readme.md |
人类用户 | 功能指南——安装、模块速览、使用模式(本文件) |
docs/ |
AI + 人类 | 规范文档——API 参考、用户手册、术语表、治理规范 |
skills/ |
AI 编码 | 技能定义——语言陷阱、编码模式、重构守则 |
核心原则:SSOT(信息只在一处定义)、Skill-first(修改代码前加载技能)、四条核心准则。