// ============================================================================= // B28 中文版 — RTD 实时数据服务器(MyRtdServer.cs) // B28 Chinese — RTD real-time-data server (MyRtdServer.cs) // ============================================================================= // // 关键点 / Key points: // 1. 必须继承 ExcelDna.Integration.Rtd.ExcelRtdServer // MUST inherit ExcelDna.Integration.Rtd.ExcelRtdServer // 2. 必须重写的方法(缺一不可): // Must override (all mandatory): // - protected override bool ServerStart() 无参! ExcelRtdServer.ServerStart 是无参虚方法 // - protected override object ConnectData(Topic topic, IList topicInfo, ref bool newValues) // - protected override void DisconnectData(Topic topic) // - GetActiveTopics() 是 protected 实例方法(不是 override),用于"推送时遍历所有订阅者" // GetActiveTopics() is a PROTECTED instance method (not override) — use it when pushing updates // 3. ServerStart / ConnectData 是 protected override,但**签名不固定**:不同 Excel-DNA 版本可能 // 加 ServerStartEventArgs 参数;以你安装版本的官方文档为准。 // ServerStart / ConnectData signatures are NOT frozen across versions; check the docs of your version. // ============================================================================= using ExcelDna.Integration; using ExcelDna.Integration.Rtd; // RTD 相关类型 / RTD types (ExcelRtdServer, Topic) using System.Timers; using System.Collections.Generic; namespace MyExcelAddIn { /// /// 实时数据服务器:每秒生成一个新随机数推送给所有订阅者。 /// Real-time data server: pushes a new random value to all subscribers every second. /// public class MyRtdServer : ExcelRtdServer { private Timer _timer; // .NET 自带的计时器 / .NET built-in timer private double _lastValue = 0; // 当前最新值 / latest value // ------------------------------------------------------------------------- // 服务启动:Excel-DNA 把这个 RTD 加载进来时调用(无参版本) // Server start: invoked by Excel-DNA when this RTD is loaded (parameter-less) // 返回 true 表示成功 / return true to indicate success // ------------------------------------------------------------------------- protected override bool ServerStart() { _timer = new Timer(1000); // 每 1000 毫秒(1 秒)触发一次 / trigger every 1000 ms _timer.Elapsed += (s, e) => { // 模拟数据:每秒生成 0~100 的随机数 // Mock data: random number in [0, 100) every second _lastValue = new System.Random().NextDouble() * 100; // 把所有已订阅的主题都更新成最新值 // Push the latest value to all active topics foreach (Topic topic in GetActiveTopics()) { topic.UpdateValue(_lastValue); // 告诉 Excel:这个值变了 / Excel: please refresh } }; _timer.Start(); return true; // 返回 true 表示启动成功 / return true to indicate success } // ------------------------------------------------------------------------- // 服务终止:Excel 卸载或关闭时调用,做清理 // Server terminate: invoked when Excel unloads; do cleanup // ------------------------------------------------------------------------- protected override void ServerTerminate() { _timer?.Stop(); _timer?.Dispose(); _timer = null; } // ------------------------------------------------------------------------- // Excel 第一次订阅某个主题时调用,返回初始值 // Excel calls this when a topic is first subscribed; return the initial value. // ------------------------------------------------------------------------- protected override object ConnectData(Topic topic, IList topicInfo, ref bool newValues) { // newValues = true 表示"返回了新值",让 Excel 主动刷一次;false 表示"没新值" // newValues = true means "new value, please refresh"; false means "no change". newValues = true; return _lastValue; } // ------------------------------------------------------------------------- // Excel 不再订阅某个主题时调用,做清理(这里一般无需特殊处理) // Excel calls this when a topic is unsubscribed; usually a no-op. // ------------------------------------------------------------------------- protected override void DisconnectData(Topic topic) { // 留空即可 / no-op is fine } } }