返回作品列表

网友作品 #000090 · 提交于 2026/08/10

Excel自定义函数插件:共享缓存实时联动重算

★★★☆☆程序员水平AI 编程工具国际顶级模型exceldna

作品作者

李伟坚-Excel催化剂&EasyShu作者程序员水平微信号liweijian08可加好友交流
开发工具
AI 编程工具
AI 模型
国际顶级模型
使用 Skill
exceldna
提交你的作品

作品简介

这是作者「wps-udf-live-cache」蓝图成果:一个基于 Excel-DNA 的自定义函数插件,同时兼容 Excel 与 WPS 双宿主。它解决的经典问题是“先拉全量、再定时拉增量、多个公式共享同一份缓存”:由一个信号函数(LIVE_CACHE_SIGNAL)负责轮询数据源并推送修订信号,其余汇总公式把该信号作为依赖参数,借助 Excel 依赖链自动触发重算。

数据源支持内建 Demo 模拟与真实 HTTP 接口两种模式,改配置即可切换,并支持运行时热重载;同一插件可按频道隔离多路数据(如订单、库存、客户),各自拥有独立缓存与轮询周期。

核心亮点

  • 信号驱动精确重算:不是定时刷新全部公式,而是缓存真的变化时才重算依赖它的公式,大工作簿性能更稳
  • 全量+增量同步:首次全量拉取建缓存,之后按主键与时间戳做 upsert/delete,增量更旧自动忽略、支持删除标记
  • 共享缓存省请求:同频道所有函数共享一份内存表,由统一轮询任务管理,下游读取零额外网络开销
  • 多频道隔离:订单、库存、客户等不同数据源各自独立缓存、独立轮询周期与 HTTP 端点
  • 零代码切换数据源:Demo 模拟与真实 HTTP 接口通过 JSON 配置切换,支持 CFG_RELOAD 热重载
  • 工作簿状态持久化:通过 CustomXMLParts 把缓存快照写入工作簿,重开可查看,便于审计追溯
  • 函数配套齐全:信号、状态查看、分组汇总(SUM/QTY/TABLE)、查询句柄、配置读取等函数一应俱全

技术与工具

  • 运行时与框架:.NET 6 + Excel-DNA 1.9,x86/x64 双 xll 自动适配 Excel/WPS 宿主
  • 响应式信号:System.Reactive(Rx.NET)的 BehaviorSubject 推送修订信号,配合 ExcelAsyncUtil.Observe
  • 并发与缓存:DataTable + ReaderWriterLockSlim 读写分离,ConcurrentDictionary 管理多频道
  • 配置体系:Microsoft.Extensions.Configuration 双层 JSON(默认层 + 用户层覆盖)
  • 状态持久化:CustomXMLParts 内嵌工作簿,ExcelDna.IntelliSense 提供函数与参数提示
  • 开发方式:AI 编程类工具搭配国际顶级模型完成

适用场景

  • 实时数据看板:订单等业务数据从后端接口实时流入 Excel,按区域、产品线自动汇总刷新
  • 生产监控大屏:从 MES 拉取产线数据,按车间、工序展示产量与良率,异常自动标记
  • 财务对账监控:对接银行流水按账户、金额区间汇总,异常交易触发重算提醒
  • 库存预警:轮询 ERP 库存,低于安全库存的物料自动高亮
  • 多系统联动:通过频道隔离在同一工作簿联动订单、仓储、物流等多源数据
原始提交内容(点开查看,可复制全文去问 AI)

wps-udf-live-cache 项目说明

Excel-DNA 自定义函数插件 | 全量快照 + 增量轮询 + 共享缓存 + 下游联动重算


一、项目概述

wps-udf-live-cache 是一个基于 Excel-DNA 的 Excel/WPS 自定义函数插件,核心能力是解决一类经典问题:“先拉全量数据,再定时拉增量变更,多个 Excel 公式共享同一份内存缓存,只有缓存真的变化时依赖它的公式才重算。”

该蓝图引入了 “信号驱动重算” 架构——一个 Formula 负责轮询数据源并推送修订信号,其他公式把信号作为依赖参数传入,由 Excel 的依赖链自动触发重算。数据源支持内建 Demo 模拟模式和 HTTP 真实接口两种模式,可无缝切换。

一句话定位: 让 Excel 拥有实时数据联动能力,无需手动刷新、无需 VBA、无需定时宏。


二、技术栈

层级 技术选型 说明
运行时 .NET 6(RollForward=LatestPatch) 兼容 .NET 6+ Desktop Runtime
插件框架 Excel-DNA 1.9(本地 Patched 版) 支持 Excel 和 WPS 双宿主
架构 x86 / x64 双 xll 自动适配宿主进程位数
响应式编程 System.Reactive(Rx.NET) BehaviorSubject 实现信号推送
缓存存储 DataTable + ReaderWriterLockSlim 线程安全的内存表,主键索引
HTTP 客户端 HttpClient(单例共享) 全量/增量接口调用
配置管理 Microsoft.Extensions.Configuration appsettings.json + appsettings.user.json 双层配置
工作簿持久化 CustomXMLParts 将缓存状态嵌入工作簿文件
函数注册 Excel-DNA Explicit Registration 显式注册,避免命名冲突
智能感知 ExcelDna.IntelliSense 函数名、参数提示

三、核心架构

3.1 信号驱动重算模型


                     Excel 工作表                         
                                                         
  A1 = LIVE_CACHE_SIGNAL("orders", 5)    信号源        
                                                        
        B1 = LIVE_CACHE_SUM(A1, "orders", "North")  
        B2 = LIVE_CACHE_QTY(A1, "orders", "South")  
        B3 = LIVE_CACHE_TABLE(A1, "orders", "", 10) 
                                                         
  A1 只负责推送修订信号,不参与业务计算。                  
  下游函数把 signal 作为依赖参数,缓存变化时自动重算。      

3.2 数据流架构

全量接口  首次加载  替换内存 DataTable
                              
                               修订号 +1
                              
增量接口  定时轮询   按主键 upsert/delete
                              
                               修订号 +1
                              
                               BehaviorSubject.OnNext() 推送信号
                                       
                                        Excel 依赖链自动重算下游公式

3.3 双模式设计

模式 数据源 适用阶段
Demo 内建模拟数据生成器 开发调试、功能验证、离线演示
Http 真实 HTTP API 生产环境、对接后端业务系统

通过修改 appsettings.json 或 appsettings.user.json 中的 Mode 字段即可切换,无需改代码。

3.4 频道隔离

同一插件实例支持多个逻辑频道,不同频道拥有独立的缓存、轮询周期和 HTTP 端点:

频道 "orders"   订单数据缓存,5 秒轮询
频道 "inventory"  库存数据缓存,10 秒轮询
频道 "customers"  客户数据缓存,30 秒轮询

四、核心功能

4.1 缓存信号函数

函数 功能 说明
LIVE_CACHE_SIGNAL 启动/复用共享缓存轮询,推送修订信号 核心入口,下游公式依赖此信号
LIVE_CACHE_SIGNAL_PC 按调用单元格隔离的信号版本 演示 Observe 主题的 caller 标识能力
LIVE_CACHE_STATUS 查看缓存状态 修订号、行数、最近同步时间、错误信息

4.2 缓存读取函数

函数 功能 说明
LIVE_CACHE_SUM 按分组汇总金额 支持 groupFilter 筛选
LIVE_CACHE_QTY 按分组汇总数量 演示 ExcelParameterConversion 自动类型转换
LIVE_CACHE_TABLE 返回分组汇总表格 按金额降序排列,支持 topN 限制

4.3 查询句柄函数([ExcelHandle] 模式)

函数 功能 说明
LIVE_CACHE_QUERY 创建可复用查询句柄 封装 channel + groupFilter
LIVE_CACHE_QUERY_SUM 基于句柄的金额汇总 多个公式共享同一查询定义
LIVE_CACHE_QUERY_TABLE 基于句柄的表格返回 句柄 + signal 联合依赖

4.4 配置管理函数

函数 功能 说明
CFG_GET 读取配置值 演示 .NET 6+ 配置体系入口
CFG_RELOAD 热重载配置 无需重启插件即可切换 Demo/Http 模式

4.5 工作簿状态函数

函数 功能 说明
WORKBOOK_STATE_JSON 读取工作簿中保存的插件状态 演示 CustomXMLParts 持久化

4.6 Ribbon 命令

命令 功能
保存默认频道缓存状态到工作簿 将当前缓存状态写入工作簿的 CustomXMLParts
清空当前工作簿状态 清除工作簿中的插件状态数据

五、核心源码结构

src/TestWpsUdfLiveCache/
 AddIn.cs                    # 插件生命周期、日志、运行时装配
 AdvancedFeatures.cs         # 核心业务逻辑(全部 UDF 函数 + 缓存服务 + 配置 + 状态持久化)
 ExcelWorkbookDataOps.cs     # Excel COM 互操作封装
 HostInteractionGuard.cs     # 宿主忙碌检测与保护
 WpsBlankWorkbookCleaner.cs  # WPS 空白工作簿清理
 Properties/AssemblyInfo.cs  # 程序集信息
 appsettings.json            # 默认配置(版本控制提交)
 appsettings.user.json       # 用户私有配置(不提交版本控制)
 TestWpsUdfLiveCache-AddIn.dna    # x86 配置
 TestWpsUdfLiveCache-AddIn64.dna  # x64 配置

关键内部类:

类 职责
DemoLiveDataCacheService 单例缓存服务,管理多频道轮询、DataTable 读写、信号发布
LiveDataChannelState 单个频道的完整状态:DataTable、轮询循环、修订号、信号主题
DemoLiveDataOptions 配置模型,映射 appsettings.json 的 DemoLiveData 节
AppSettingsProvider 配置加载器,appsettings.json + appsettings.user.json 双层覆盖
WorkbookStateStore 通过 CustomXMLParts 实现缓存状态的工作簿级持久化
TimedFunctionHandler 函数执行时间统计([TimedFunction] 特性)

六、使用场景

6.1 实时数据看板

  • 订单数据从后端接口实时流入 Excel
  • 按区域、按产品线自动汇总
  • 数据变化时看板自动刷新,无需手动 F5

6.2 生产监控大屏

  • 从 MES 系统拉取产线实时数据
  • 按车间、按工序分组展示产量和良率
  • 异常数据自动标记,管理人员第一时间发现

6.3 财务对账监控

  • 对接银行接口,实时拉取交易流水
  • 按账户、按金额区间分组汇总
  • 发现异常交易时自动触发重算提醒

6.4 库存预警

  • 从 ERP 系统轮询库存数据
  • 按仓库、按物料类别分组展示
  • 低于安全库存的物料自动高亮

6.5 多数据源联动

通过不同频道隔离不同数据源,在同一工作簿中实现多系统数据的实时联动:

频道 "orders"   对接订单系统
频道 "inventory"  对接仓储系统
频道 "delivery"  对接物流系统

七、推荐公式布局

# A1:信号源(5 秒轮询)
=TESTWPSUDFLIVECACHE_LIVE_CACHE_SIGNAL("orders", 5)

# A2:缓存状态查看
=TESTWPSUDFLIVECACHE_LIVE_CACHE_STATUS("orders")

# B5:按区域汇总金额
=TESTWPSUDFLIVECACHE_LIVE_CACHE_SUM($A$1, "orders", "North")

# B6:按区域汇总数量
=TESTWPSUDFLIVECACHE_LIVE_CACHE_QTY($A$1, "orders", "South")

# B8:分组汇总表格
=TESTWPSUDFLIVECACHE_LIVE_CACHE_TABLE($A$1, "orders", "", 20)

关键设计原则:

  • A1 只负责提供修订信号,不参与业务计算
  • 下游函数把 signal 作为第一个参数传入($A$1),建立依赖链
  • 信号单元格必须使用绝对引用($A$1),否则下拉填充会断开依赖

八、HTTP 接入指南

8.1 从 Demo 切换到 Http

  1. 先用 Demo 模式跑通缓存联动,验证公式布局正确
  2. 修改 appsettings.user.json(建议不改 appsettings.json,用 user 层覆盖):
{
  "DemoLiveData": {
    "Mode": "Http",
    "FullSnapshotUrl": "https://api.example.com/orders/full",
    "DeltaSnapshotUrl": "https://api.example.com/orders/delta",
    "AuthHeaderName": "Authorization",
    "AuthHeaderValue": "Bearer <token>"
  }
}
  1. 在 Excel 中执行 =CFG_RELOAD() 热重载配置
  2. 观察 LIVE_CACHE_STATUS 确认数据已从 HTTP 接口加载

8.2 接口响应规范

全量接口:

{
  "data": {
    "rows": [
      {
        "id": "ORD-001",
        "group": "North",
        "amount": 128.5,
        "quantity": 4,
        "updatedAtUtc": "2026-07-04T08:00:00Z"
      }
    ]
  }
}

增量接口:

{
  "data": {
    "rows": [
      {
        "id": "ORD-001",
        "group": "North",
        "amount": 132.0,
        "quantity": 5,
        "updatedAtUtc": "2026-07-04T08:05:00Z"
      },
      {
        "id": "ORD-099",
        "group": "West",
        "amount": 52.3,
        "quantity": 1,
        "updatedAtUtc": "2026-07-04T08:05:10Z"
      }
    ]
  }
}

8.3 关键配置字段

字段 说明
FullRowsJsonPath 全量响应中数据数组的 JSON 路径(如 data.rows)
DeltaRowsJsonPath 增量响应中数据数组的 JSON 路径
PrimaryKeyFieldName 主键字段名,决定缓存按哪一列做 upsert/delete
UpdatedAtFieldName 更新时间字段,增量数据比现有记录更旧时会被忽略
DeltaSinceParameterName 增量接口的时间戳查询参数名(如 sinceUtc)
DeltaLookbackMinutes 首次增量请求的回溯分钟数
DeleteFlagFieldName 删除标记字段,命中后从缓存中移除该行
ChannelParameterName 频道参数名,用于在 URL 中区分不同频道
AuthHeaderName/Value HTTP 鉴权头(Bearer Token 等)

8.4 POST 请求支持

如果接口要求 POST 方法发送 JSON Body:

{
  "DemoLiveData": {
    "DeltaSnapshotMethod": "POST",
    "DeltaRequestBodyTemplate": "{\"channel\":\"{channel}\",\"sinceUtc\":\"{sinceUtc}\"}"
  }
}

占位符 {channel} 和 {sinceUtc} 会在请求时自动替换为实际值。


九、功能特色

9.1 信号驱动重算——精确联动

  • 不是“定时刷新全部公式”,而是“缓存变化时只重算依赖它的公式”
  • 使用 BehaviorSubject 作为信号源,下游通过 Excel 的依赖链自动触发
  • 减少不必要的计算,提升大工作簿性能

9.2 共享缓存——避免重复请求

  • 同一频道的所有公式共享同一份内存 DataTable
  • 不是每个单元格各自发 HTTP 请求,而是由一个轮询任务统一管理
  • 多个下游函数从同一份缓存读取,零额外网络开销

9.3 全量 + 增量同步——高效数据更新

  • 首次加载:全量拉取整表数据
  • 后续轮询:只拉最近几分钟的增量变更
  • 按主键 upsert:存在则更新,不存在则插入
  • 按时间戳去重:增量数据比现有记录更旧时自动忽略
  • 支持删除语义:通过 DeleteFlagFieldName 标记删除

9.4 线程安全设计

  • ReaderWriterLockSlim 保证读写分离
  • 汇总函数使用读锁,允许多个公式并发读取
  • 数据更新使用写锁,保证原子性
  • BehaviorSubject 是线程安全的,信号发布无竞态

9.5 零代码切换 Demo/Http

  • 配置驱动,修改 JSON 即可切换数据源
  • Demo 模式内置模拟数据生成器,无需外部依赖即可演示
  • 支持运行时热重载配置(CFG_RELOAD)

9.6 配置双层覆盖

  • appsettings.json:默认配置,可提交版本控制
  • appsettings.user.json:用户私有配置,不提交版本控制
  • 后者覆盖前者,灵活管理不同环境的配置差异

9.7 工作簿状态持久化

  • 通过 Excel 的 CustomXMLParts 将缓存状态写入工作簿文件
  • 关闭工作簿后重新打开,可查看上次缓存的快照状态
  • 适合审计追溯和离线分析

9.8 函数执行计时

  • [TimedFunction] 特性自动记录函数执行耗时
  • 写入 addin.log,便于性能分析和问题排查

十、面向组合:与 TreeCollections 蓝图的联动

wps-udf-live-cache 和 wps-udf-tree-collections 可以组合使用,构成完整的 BI 分析方案:

wps-udf-live-cache          wps-udf-tree-collections
       
实时数据轮询                 维度树构建
共享内存缓存                 层级查询
信号驱动重算                 作用域汇总
                             事实聚合
                                 
        
                  
                  
        全功能实时 BI 分析插件

例如:从后端接口实时拉取各子公司的收入数据,结合组织架构树做层级汇总,数据变化时报表自动刷新。


十一、与其他蓝图的对比

蓝图 核心能力 适用场景
wps-udf-only 纯自定义函数,无共享缓存 普通查询函数,不需要联动重算
wps-udf-live-cache 共享缓存 + 信号重算 + 轮询 实时数据看板、多函数共享缓存
wps-udf-tree-collections 父子维度树 + BI 层级汇总 组织架构、科目树、成本中心分析
wps-ribbon-ctp-webview Ribbon 界面 + 任务窗格 需要交互式 UI 的插件

十二、技术要点总结

  1. 信号驱动重算:BehaviorSubject + ExcelAsyncUtil.Observe 实现精确的缓存变化通知
  2. 单例缓存服务:Lazy<T> 确保全局唯一实例,ConcurrentDictionary 管理多频道隔离
  3. 全量 + 增量:先 ReplaceAllRows 再 ApplyDeltaRows,按主键 + 时间戳做 upsert
  4. 线程安全:ReaderWriterLockSlim 读写分离,DataTable 主键索引
  5. 配置热重载:Microsoft.Extensions.Configuration + 双层 JSON 文件
  6. 参数转换:ExcelParameterConversion 将文本自动转换为强类型筛选器
  7. 执行计时:FunctionExecutionHandler 自定义特性,透明记录函数耗时
  8. 工作簿持久化:CustomXMLParts 实现状态数据内嵌在工作簿文件中
  9. HTTP 灵活配置:支持 GET/POST、JSON Path 解析、URL 参数模板、占位符替换
  10. 双宿主兼容:ExcelDnaUtil.IsET 自动检测 Excel/WPS,统一代码路径

十三、系统要求

  • 操作系统:Windows 7 SP1 及以上
  • .NET 运行时:.NET 6 Desktop Runtime(x86 或 x64)
  • Office 版本:Microsoft Excel 2010+ 或 WPS 2019+
  • 位数:x86 或 x64,与 Office/WPS 位数一致
  • 网络:Http 模式需要能访问目标 API 端点

十四、最小验证步骤

  1. 安装插件后打开 Excel/WPS
  2. 在 A1 输入:=TESTWPSUDFLIVECACHE_LIVE_CACHE_SIGNAL("orders", 5)
  3. 在 A2 输入:=TESTWPSUDFLIVECACHE_LIVE_CACHE_STATUS("orders")
  4. 在 B1 输入:=TESTWPSUDFLIVECACHE_LIVE_CACHE_SUM($A$1, "orders", "North")
  5. 观察 A2 显示缓存状态,B1 显示汇总金额
  6. 等待几秒后,观察修订号递增,汇总金额自动变化
  7. 验证通过后,切入 Http 模式对接真实接口