基于C# ExcelDNA的XLL如何捕获Workbook关闭事件?
用ExcelDNA捕获Excel工作簿BeforeClose事件(无需转为XLSM)
核心思路是通过Excel Interop获取当前Excel应用实例,订阅应用级别的WorkbookBeforeClose事件,就能在任意XLSX工作簿关闭前触发自定义逻辑,不需要修改工作簿格式。
实现步骤
1. 引用依赖包
确保项目通过NuGet安装ExcelDna.AddIn和Microsoft.Office.Interop.Excel包,引用必要的命名空间:
using ExcelDna.Integration; using Microsoft.Office.Interop.Excel; using System;
2. 编写AddIn类处理事件
创建实现IExcelAddIn接口的类,在插件启动时订阅事件,关闭时取消订阅以避免内存泄漏:
[ExcelAddIn(AddInName = "WorkbookCloseHandler", Description = "捕获工作簿关闭事件的XLL插件")] public class WorkbookCloseHandlerAddIn : IExcelAddIn { private Application _excelApp; private WorkbookEvents_BeforeCloseEventHandler _beforeCloseDelegate; public void AutoOpen() { // 获取当前Excel应用实例 _excelApp = (Application)ExcelDnaUtil.Application; // 保存委托引用,防止被GC回收导致事件失效 _beforeCloseDelegate = new WorkbookEvents_BeforeCloseEventHandler(OnWorkbookBeforeClose); // 订阅工作簿关闭前事件 _excelApp.WorkbookBeforeClose += _beforeCloseDelegate; } public void AutoClose() { // 取消订阅,释放资源 if (_excelApp != null && _beforeCloseDelegate != null) { _excelApp.WorkbookBeforeClose -= _beforeCloseDelegate; } } private void OnWorkbookBeforeClose(Workbook targetWorkbook, ref bool cancelClose) { // 获取工作簿文件名(或完整路径) string workbookName = targetWorkbook.Name; string fullPath = targetWorkbook.FullName; // 在这里执行自定义操作,例如: // 备份文件、清理临时数据、记录操作日志等 _excelApp.StatusBar = $"正在处理关闭的工作簿:{workbookName}"; // 若需阻止工作簿关闭,设置cancelClose = true; // cancelClose = true; } }
关键注意事项
- 保留委托引用:必须将事件委托赋值给类级变量(
_beforeCloseDelegate),否则.NET垃圾回收器会回收委托,导致事件订阅失效。 - 内存泄漏防范:在
AutoClose方法中取消事件订阅,避免Excel进程退出时残留资源。 - Excel线程模型:Excel运行在单线程公寓(STA)环境中,事件处理逻辑应尽量简短,避免耗时操作。如需异步处理,可使用ExcelDNA提供的
AsyncUtil工具类。 - 事件触发时机:
WorkbookBeforeClose在用户尝试关闭工作簿时触发,此时工作簿仍处于打开状态,可正常访问其内容和属性。
内容的提问来源于stack exchange,提问作者RobBaker
相关产品推荐
相关产品推荐

