真·VB.NET彻底释放Interop.Excel对象

使用 Microsoft.Office.Interop.Excel 虽然有速度慢的缺点;但是作为自带引用,兼容性最好,而且是COM对象模型也很熟悉(Excel里直接录个宏,很方便把VBA代码转成VB.NET)。所以处理几百上千条的小数据时还是很方便的。

Microsoft.Office.Interop.Excel 用得不多的最大问题其实就是拿简单例子可以正确释放Excel,做了大量操作后却发现在任务管理器中依然有多余Excel进程存在。

问题原因当然是COM对象映射到Interop交互对象之后,.NET下的交互对象释放次序不符合COM对象预期,导致不能正确释放。比如

vbnet 复制代码
Dim xlApp New Excel.Application() With {.Visible = False}
Dim xlWorkbooks As Excel.Workbooks = xlApp.Workbooks
Dim xlWorkbook As Excel.Workbook = xlWorkbooks.Open("...")

Dim value As Object = xlWorkbook.Sheets(1).Cells(1,1).Value

xlWorkbook.Close()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook)
xlWorkbook = Nothing
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbooks)
xlWorkbooks = Nothing
xlApp.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
xlApp = Nothing
System.GC.Collect()

中间取value这行代码看起来很正常,没有保留任何交互对象。其实在整个对象访问路径上隐式使用了以下交互对象,要靠GC来释放(通常是延后的------------即调用Close()时交互对象未释放、工作簿关闭不了,之后的Quit()Excel不会退出),

vbnet 复制代码
xlWorkbook.Sheets 'Excel.Sheets
xlWorkbook.Sheets(1) 'Excel.Worksheet
xlWorkbook.Sheets(1).Cells 'Excel.Range
xlWorkbook.Sheets(1).Cells(1,1) 'Excel.Range

要做到正确释放,要把这些交互对象全部在Close()前释放。为了方便使用,把 Excel.ApplicationExcel.Workbook 封装在类中,用 IDisposable 接口确保释放。用类似下面的属性封装访问

vbnet 复制代码
    Public Property CellValue(sheetIndex As Object, rowNo As Integer, colNo As Integer) As Object
        Get
            Dim xlSheets As Excel.Sheets = m_xlWorkbook.Sheets
            Dim xlSheet As Excel.Worksheet = xlSheets.Item(sheetIndex)
            Dim xlCells As Excel.Range = xlSheet.Cells
            Dim xlCell As Excel.Range = xlCells.Item(rowNo, colNo)
            Dim value As Object = xlCell.Value
            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCell)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
            System.GC.Collect(0)
            Return value
        End Get
        Set(value As Object)
            ' 同理所有交互对象保留变量、释放
        End Set
    End Property

上面的属性是通过行号、列号访问单元value;如果需要通过A1格式访问单元又要定义属性;如果需要访问单元text也要单独定义属性。
总之全部封装好后,读写完Excel文件后就能正确释放,不再有多余Excel进程残留。

相关推荐
三天不学习1 小时前
YOLO + .NET 10 快速入门:从零搭建实时目标检测应用
yolo·目标检测·.net
开开心心就好2 小时前
小白友好的程序联网封锁实用工具
windows·eureka·计算机外设·rabbitmq·word·excel·csdn开发云
SunnyDays101118 小时前
Python操作Excel批注:从基础添加到高级自定义的完整指南
开发语言·python·excel
Eiceblue20 小时前
Python 操作 Excel:数据分组、分类汇总与取消分组全解
开发语言·python·excel
城数派21 小时前
2026年500米分辨率DEM地形数据(全球/全国/分省/分市)
数据库·arcgis·信息可视化·数据分析·excel
0x000721 小时前
译 Anders Hejlsberg 谈 C# 与 .NET
开发语言·c#·.net
SunnyDays10111 天前
Python 操作 Excel 超链接:添加网页、文件、工作表和图片链接
python·excel
AI行业学习1 天前
.NET Framework 3.5 SP1 完整离线包(2029.5.29)
开发语言·windows·.net
AI行业学习1 天前
.NET Framework 3.5 官方离线包下载+完整安装教程【2026.5.29】
windows·.net·notepad++
我是唐青枫1 天前
C#.NET YARP 服务发现实战:接入 Consul 和 Kubernetes 动态发现后端服务
c#·服务发现·.net