1,Excel-DNA 第一種方法,簡單
2,自定義添加,VIsual studio 需要管理員權限啟動。
寫Server代碼
1) 新建C# 類庫項目,添加如下類:
using System; using System.Threading; using System.Collections.Generic; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; namespace StackOverflow { public class Countdown { public int CurrentValue { get; set; } } [Guid("EBD9B4A9-3E17-45F0-A1C9-E134043923D3")] [ProgId("StackOverflow.RtdServer.ProgId")] public class RtdServer : IRtdServer { private readonly Dictionary<int, Countdown> _topics = new Dictionary<int, Countdown>(); private Timer _timer; public int ServerStart(IRTDUpdateEvent rtdUpdateEvent) { _timer = new Timer(delegate { rtdUpdateEvent.UpdateNotify(); }, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); return 1; } public object ConnectData(int topicId, ref Array strings, ref bool getNewValues) { var start = Convert.ToInt32(strings.GetValue(0).ToString()); getNewValues = true; _topics[topicId] = new Countdown { CurrentValue = start }; return start; } public Array RefreshData(ref int topicCount) { var data = new object[2, _topics.Count]; var index = 0; foreach (var entry in _topics) { --entry.Value.CurrentValue; data[0, index] = entry.Key; data[1, index] = entry.Value.CurrentValue; ++index; } topicCount = _topics.Count; return data; } public void DisconnectData(int topicId) { _topics.Remove(topicId); } public int Heartbeat() { return 1; } public void ServerTerminate() { _timer.Dispose(); } [ComRegisterFunctionAttribute] public static void RegisterFunction(Type t) { Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(@"CLSID\{" + t.GUID.ToString().ToUpper() + @"}\Programmable"); var key = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(@"CLSID\{" + t.GUID.ToString().ToUpper() + @"}\InprocServer32", true); if (key != null) key.SetValue("", System.Environment.SystemDirectory + @"\mscoree.dll", Microsoft.Win32.RegistryValueKind.String); } [ComUnregisterFunctionAttribute] public static void UnregisterFunction(Type t) { Microsoft.Win32.Registry.ClassesRoot.DeleteSubKey(@"CLSID\{" + t.GUID.ToString().ToUpper() + @"}\Programmable"); } } }
2) 右鍵項目->選擇屬性->新添加項目->選擇安裝類(Installer Class).F7切換到代碼編輯器加入如下代碼:
using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; namespace StackOverflow { [RunInstaller(true)] public partial class RtdServerInstaller : System.Configuration.Install.Installer { public RtdServerInstaller() { InitializeComponent(); } [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] public override void Commit(IDictionary savedState) { base.Commit(savedState); var registrationServices = new RegistrationServices(); if (registrationServices.RegisterAssembly(GetType().Assembly, AssemblyRegistrationFlags.SetCodeBase)) Trace.TraceInformation("Types registered successfully"); else Trace.TraceError("Unable to register types"); } [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)] public override void Install(IDictionary stateSaver) { base.Install(stateSaver); var registrationServices = new RegistrationServices(); if (registrationServices.RegisterAssembly(GetType().Assembly, AssemblyRegistrationFlags.SetCodeBase)) Trace.TraceInformation("Types registered successfully"); else Trace.TraceError("Unable to register types"); } public override void Uninstall(IDictionary savedState) { var registrationServices = new RegistrationServices(); if (registrationServices.UnregisterAssembly(GetType().Assembly)) Trace.TraceInformation("Types unregistered successfully"); else Trace.TraceError("Unable to unregister types"); base.Uninstall(savedState); } } }
3) 右鍵項目->選擇屬性:
進入程序(Application)選項卡 >程序集( Assembly Information)... >勾選最下面的COM可以參照
進入編譯(build)選項卡->選擇Release模式->最下面輸出的地方勾選COM登錄 ( Register for COM Interop)
4) 添加Nuget包: Microsoft.Office.Interop.Excel
5) Release 模式編譯測序
6) 打卡Excel,選擇文件->選項 > Add-Ins > Excel Add-Ins > Automation and select "StackOverflow.RtdServer"
7) 在Cell里面輸入 "=RTD("StackOverflow.RtdServer.ProgId",,200)" .