应彻底放弃 Microsoft.Office.Interop.Excel,改用 EPPlus(.NET 5+)或 NPOI(兼容 .NET Framework);EPPlus 通过 package.Workbook.Worksheets 获取可见表名,全量需遍历 WorkbookPart.Workbook.Sheets;NPOI 统一用 workbook.GetSheetName(i) 但不支持隐藏表。
用 Microsoft.Office.Interop.Excel 读取 Sheet 名会卡死或报错
直接用 com 互操作打开 excel 文件再遍历 worksheets,在无 excel 桌面环境(如服务器、ci 环境)必然失败,常见错误是 system.runtime.interopservices.comexception: 检索 com 类工厂中 clsid 为 {00024500-0000-0000-c000-000000000046} 的组件时失败。即使本地能跑,也会因 excel 进程残留导致后续调用卡住。
实操建议:
- 彻底放弃
Microsoft.Office.Interop.Excel,它不是为后台服务设计的 - 改用纯托管库,比如
EPPlus(.NET 5+ 推荐)或NPOI(兼容 .NET Framework) - 若必须用 Interop(例如要执行宏),需确保目标机器装了 Excel、启用 DCOM 配置、且每次调用后显式调用
app.Quit()+Marshal.ReleaseComObject()清理——但依然不推荐
EPPlus 读取所有 Sheet 名的正确写法
EPPlus 不依赖 Office 安装,速度快,内存友好,但注意:它只支持 .xlsx / .xlsm / .xltx,不支持老式 .xls(那是 NPOI 的活)。
实操建议:
- 安装包:
Install-Package EPPlus(.NET 6+ 需额外加EPPlus.Core或确认版本 ≥ 6.0) - 必须先设置许可证(免费版有水印且限制功能),开发阶段可临时加:
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; - 用
ExcelPackage打开文件后,Workbook.Worksheets是个索引集合,遍历即可:using (var package = new ExcelPackage(new FileInfo("data.xlsx"))) { var sheetNames = package.Workbook.Worksheets.Select(ws => ws.Name).ToList(); } - 注意:
Worksheets只包含可见 Sheet;隐藏/非常隐藏的 Sheet 默认不会出现在这个集合里(见下一条)
如何拿到隐藏(Hidden / VeryHidden)的 Sheet 名
EPPlus 默认跳过隐藏状态的 Sheet,但它们实际仍存在于文件结构中。想完整枚举,得换路径:读取底层 Workbook.Part 中的 worksheets 关系项。
实操建议:
- 隐藏分两级:
xlSheetHidden(右键“隐藏”)和xlSheetVeryHidden(VBA 设为xlSheetVeryHidden),后者连“取消隐藏”菜单都看不到 - 用
package.Workbook.Worksheets只能得到xlSheetVisible的 Sheet;要全量,得这样:var allSheets = package.Workbook.WorkbookPart.Workbook.Sheets .Cast<Sheet>() .Select(s => s.Name.Value) .ToList(); - 这个列表里的每个
Sheet对象还带State属性(SheetStateValues.Visible/Hidden/VeryHidden),可用来过滤或标记 - 别试图用
Worksheets[名称]访问隐藏 Sheet——会抛NullReferenceException,得先用WorkbookPart.GetWorksheetById()拿到 part 再加载
NPOI 兼容 .xls 时的 Sheet 名获取差异
如果必须处理 97–2003 格式的 .xls,NPOI 是唯一靠谱选择,但它对两种格式的 API 不统一:HSSF(.xls)和 XSSF(.xlsx)用不同类暴露 Sheet 列表。
实操建议:
- 判断格式再分支处理,别硬套一个类型:
var fs = new FileStream("data.xls", FileMode.Open); IWorkbook workbook = WorkbookFactory.Create(fs); // 此时 workbook 是 HSSFWorkbook 或 XSSFWorkbook 实例 - 统一用
workbook.NumberOfSheets和workbook.GetSheetName(i)遍历,这个接口在两个实现里都存在 -
NPOI默认也不返回隐藏 Sheet,但没提供像 EPPlus 那样方便的底层访问方式;若真需要,得反射进HSSFSheet或解析 OLE 复合文档——代价高,通常建议提前清理源文件 - 注意编码:老
.xls文件若含中文 Sheet 名,且未指定编码,NPOI可能乱码;可在WorkbookFactory.Create()前设Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)


















