
简介面向.NET开发者的NPOI预编译组件包专为需要兼容.NET Framework 2.0与4.0的老项目或指定框架环境准备省去自行编译的繁琐步骤可直接引用DLL完成Excel、Word等Office文件读写、报表生成与数据导入导出。压缩包为rar格式共39个文件包含18个DLL运行库、12个PDB调试符号和9个XML注释文档整体大小11.51MBDLL按framework2.0和4.0分目录存放便于按需选用。目前已有3784人学习下载。资源覆盖NPOI核心模块NPOI.dll、NPOI.OOXML.dll、NPOI.OpenXmlFormats.dll等支持.xls/.xlsx、.doc/.docx常用格式可创建工作簿、设置样式、处理公式与图表并附有基本调用示例能帮助开发者快速上手尤其适合在低版本.NET环境中引入Office操作能力的场景。1. 项目背景为什么还有人在找NPOI的.NET 2.0和4.0版本下载先坦白一下我为什么会对这个标题感兴趣。上个月接了一个老系统的维护需求客户那边是2012年上线的生产管理系统服务器还是Windows Server 2008跑着.NET Framework 2.0的WinForm程序里面用NPOI做了Excel导出报表的功能。客户说导出的Excel文件格式不对让我排查。我打开代码一看好家伙引用的NPOI是1.2.5版本年代感一下就上来了。这个场景其实非常典型。NPOI是一个开源的.NET类库功能是在没有安装Office的情况下读写字Excel、Word、PPT文件底层逻辑移植自Java生态里的Apache POI项目。我自己目前主要用.NET 8做偏现代栈的Web项目但每年总会有几次碰到老项目的场景——工厂里跑了好多年的MES系统、医院里的收费系统、银行内部的报表平台这些系统的服务器环境往往还被钉在旧版.NET Framework上升级成本太高、风险太大只能沿用对应的NPOI版本继续维护。所以就说说这两个版本怎么下载、怎么选、怎么用。这篇文章我把关键经验整理出来正好适合下面几类读者第一接手了老项目需要给.NET 2.0或.NET 4.0项目引入NPOI的开发者第二公司内网开发环境不让随意装软件、只能离线引DLL的人第三纯粹好奇NPOI新旧版本差异、想了解从老版本迁移到新版本有什么坑的。先说一个最容易踩的坑NPOI的版本和.NET框架版本是绑定的不是随便下个最新版就能用的。NPOI 2.0正式版系列比如2.0.6是官方明确支持.NET Framework 2.0、3.5、4.0的收官版本从2.1.0版本开始官方把最低要求提到了.NET Framework 4.0后续的3.x、4.x版本更是全面面向.NET Framework 4.5及以上。所以如果你的服务器环境是.NET 2.0还是.NET 4.0决定了你能装的NPOI版本范围。这个对应关系是硬约束不搞清楚后面全是报错。2. NPOI核心能力解析与版本差异对比2.1 NPOI到底能做什么NPOI最核心的用途就是程序级生成、读取、修改Excel文件官方称之为不依赖Office COM组件的纯托管方案。我打个比方很多老项目里导出Excel是直接用Excel COM组件服务器上必须装一套完整的Microsoft Office这在真实生产环境里极其痛苦——Office授权贵、并发操作容易崩、服务器重启后Excel进程残留经常搞到服务器内存耗尽。NPOI不存在这些问题它更像一个翻译官直接把数据映射成Excel的底层文件格式写出去不需要任何Office程序参与。具体来说它支持三种重要的文件格式操作能力HSSF对应老式的.xls二进制格式Excel 97-2003、XSSF对应.xlsx格式Excel 2007之后、还有SXSSF流式处理适合超大文件导出。另外还提供了HWPF和XWPF来操作Word文档、HSLF和XSLF来操作PPT不过实际项目里用NPOI做Excel的人占绝大多数Word和PPT的处理需求相对少。从底层原理角度看NPOI不是把Excel文件当作一张二维表格简单读取它把所有内容解析成一个完整的对象模型。工作簿Workbook是最顶层的概念里面包含工作表Sheet每张表排列着行Row每行划分出单元格Cell。每个单元格对象保存了值、类型、样式、字体、边框、背景色等信息。这样的设计带来的好处是你能操作的文件细节极其丰富不止是填数据还可以合并单元格、加密文件、设置数据验证、加公式。代价是概念多了之后新手刚开始会有点绕对“Excel文件是一个有层次的对象结构”这个理解需要花点时间建立起来。2.2 2.0版本和4.0版本的差异对比NPOI从2.0到4.0中间隔了很多版本不同版本最大的差别不只是命名空间和API还有编译目标框架。我整理了一个对照表方便你直接判断该选哪个版本对比维度NPOI 2.0.xNPOI 4.x最低运行框架.NET Framework 2.0/3.5.NET Framework 4.5典型命名空间NPOI.HSSF.UserModel、NPOI.XSSF.UserModel基本一致但部分类型移到NPOI.SS.UserModel统一接口.xls支持完整支持完整支持底层代码更优.xlsx支持基础支持支持更完整包括样式、图表、图片等大数据量导出一般容易内存暴涨支持SXSSFWorkbook流式写几万行数据比较轻松API风格老式偏Java风格增加了不少NewWorkbook这类快捷入口NuGet安装需要手动指定版本号Install-Package NPOI默认就是新版如果你是把一个老项目从NPOI 2.0升级到4.x最直接的感受是原来写过的大量HSSFWorkbook workbook new HSSFWorkbook();不需要改太多但有些细节行为不一样了。比如NPOI 2.0时代创建单元格样式你写cell.CellStyle style;在4.x里依然兼容不过4.x对单元格类型判断更严格拿CellType.String来取值时如果实际是数字类型可能会得到空值而不是自动转换。还有一个重要变化NPOI 3.x开始逐步把API统一到NPOI.SS.UserModel这个接口层。过去你操作.xls和.xlsx要分别学HSSF和XSSF两套API新版本里很多代码直接面向IWorkbook、ISheet、IRow、ICell这些接口写传入new HSSFWorkbook()还是new XSSFWorkbook()工作簿对象剩下的代码几乎可以共用。对写通用工具类来说这个改进非常舒服。3. 下载与环境配置实操正确的找包姿势3.1 在线环境下的NuGet安装如果你的开发机可以直接访问外网最省事的方式就是NuGet。这里有个细节我特别想强调不要直接在Visual Studio的NuGet管理器里搜NPOI然后闭着眼睛点安装因为你看到的默认版本可能是最新的4.x如果项目目标框架是.NET 2.0或.NET 4.0会直接报“不兼容”或者“无法还原”。正确做法是打开程序包管理器控制台Package Manager Console先确认当前项目的目标框架然后指定版本号安装。比如.NET Framework 4.0的老项目我建议用2.0.6作为上限安装命令是Install-Package NPOI -Version 2.0.6如果你的项目目标框架确实是.NET 2.0那你需要更谨慎。NPOI官方NuGet包从2.0系列开始最低标准其实是.NET Framework 2.0可运行。但我实测下来有个朋友在.NET 2.0项目里装NPOI 2.0.6跑起来偶尔会报缺少System.Core的引用这是因为Visual Studio老项目默认引用程序集并不完整。这时候手动添加对System.Core.dll的引用就可以解决。对于.NET Framework 4.0或4.5项目我个人的建议是直接上4.1或更高版本。我当前主力环境是4.7.2和.NET 8用NPOI 2.1.6写过不少报表处理工具原因只有一个稳定。新版本虽然增加了特性但是对于报表导出这种基本需求接口成熟、踩坑资料多比什么都重要。如果你的环境是.NET 4.0且不想升级用2.1.x系列其实也有不少人在生产环境里跑得很好。提示NuGet安装完成后注意检查一下packages.config文件老式项目或者Project.assets.jsonPackageReference方式确认安装的是你指定的版本避免因为其他依赖项自动升级导致版本漂移。3.2 离线环境的下载与引用公司内网开发环境往往禁止直接访问NuGet这种情况我用过三种方案第一种在外网机器上先把nupkg包下载下来拷进内网后手动安装。NuGet包下载地址是一个固定结构https://www.nuget.org/api/v2/package/NPOI/2.0.6这个地址会直接下载2.0.6版本的nupkg文件。拿到文件后可以在NuGet包管理器设置里把这个文件放到本地源目录也可以直接把nupkg解压把里面的lib目录下的对应DLL文件复制到项目的libs文件夹里然后右键引用添加这些DLL。第二种直接从GitHub Releases页面下载。NPOI是开源项目GitHub仓库地址是https://github.com/nissl-lab/npoiReleases页面会按版本列出下载包通常发布的是zip压缩包里面有完整DLL和XML帮助文档。老版本需要往下翻2.0.6的包也能找到。这里我要额外说一句GitHub上NPOI的老版本release下载速度可能很慢你耐心等一会儿别误以为挂了。第三种是官方文档里不太提但实际很推荐的方式——使用NPOI.Compiler或者直接在NuGet里搜索NPOI时选择“包括预发行版”选项然后找对应的便携版包这类包体积更大但包含了不同框架的DLL适合在不同环境里切换。离线方式有一个关键点就是项目里引用了多个NPOI相关DLL比如NPOI.dll、NPOI.OOXML.dll、NPOI.OpenXml4Net.dll、NPOI.OpenXmlFormats.dll必须在bin目录下同时存在缺一个运行时会报“找不到文件或程序集”。3.3 服务器端的运行时环境准备NPOI是托管代码库它运行的环境是.NET运行时不是操作系统。所以即便你的项目编译时引用了NPOI 2.0.6目标服务器上也必须安装对应的.NET Framework运行时。.NET Framework 2.0或3.5的服务器环境现在很多Windows Server版本默认不带3.5组件需要在“服务器管理器-功能-添加功能”里勾选“.NET Framework 3.5功能”这一项会同时包含2.0和3.0的CLR。Windows Server 2012之后系统安装盘或Windows Update可以直接获取但如果你的服务器完全离线需要准备microsoft-windows-netfx3-ondemand-package的CAB包用DISM命令离线安装。我经历过一次银行项目对接对方的服务器连Windows Update都禁了最后靠DISM离线包搞定的。.NET Framework 4.0环境安装方式更简单直接装4.0的独立安装包即可。但注意4.0是全版本独立的一套CLR机制和2.0/3.5是共存的装了4.0并不会帮你升级3.5也不会互相影响。我见过有人以为装了4.8就万事大吉结果程序跑到一个没装3.5的机器上直接崩溃这种情况在维护老项目时尤其常见。4. 快速上手老版本环境下的Excel读写实操4.1 读取Excel文件的完整示例兼容NPOI 2.0这里我写一个适用于.NET Framework 2.0/4.0、NPOI 2.0.6的代码示例用来读取一个.xls格式的Excel文件并输出内容。为什么特意用老版本API写因为很多网上搜到的教程都是新版本的老项目里复制新代码会报错。using System; using System.IO; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; class Program { static void Main(string[] args) { string filePath D:\test\data.xls; using (FileStream fs File.OpenRead(filePath)) { // 注意NPOI 2.0里HSSFWorkbook直接传入Stream即可 HSSFWorkbook workbook new HSSFWorkbook(fs); // 取第一个工作表 ISheet sheet workbook.GetSheetAt(0); if (sheet null) { Console.WriteLine(没有找到工作表); return; } // 遍历所有行 for (int rowIndex 0; rowIndex sheet.LastRowNum; rowIndex) { IRow row sheet.GetRow(rowIndex); if (row null) continue; Console.WriteLine( 第 {0} 行 , rowIndex 1); // 遍历这一行的所有单元格 for (int cellIndex 0; cellIndex row.LastCellNum; cellIndex) { ICell cell row.GetCell(cellIndex); if (cell null) continue; string cellValue; switch (cell.CellType) { case CellType.STRING: cellValue cell.StringCellValue; break; case CellType.NUMERIC: // 如果是日期格式的数字单元格需要判断 if (HSSFDateUtil.IsCellDateFormatted(cell)) { cellValue cell.DateCellValue.ToString(yyyy-MM-dd); } else { cellValue cell.NumericCellValue.ToString(); } break; case CellType.BOOLEAN: cellValue cell.BooleanCellValue.ToString(); break; case CellType.FORMULA: cellValue cell.CellFormula; // 拿公式字符串 break; default: cellValue ; break; } Console.WriteLine(第{0}列: {1}, cellIndex 1, cellValue); } } workbook.Close(); } } }这个示例里几个老版本特有的坑值得说明一下第一HSSFDateUtil.IsDateFormatted(cell)用于识别日期单元格。Excel里的日期本质上是数字没做这个判断之前我遇到过把日期显示成一串数字的情况找半天才发现是日期格式化没做。第二row.LastCellNum返回的是“列数1”的语义也就是说如果有5列它返回的是5不是一个索引位置。新手很容易写出cellIndex row.LastCellNum还是的疑惑正确小于号没跑了这个细节在4.x版本里行为不变。第三老版本NPOI对空行的处理比较粗sheet.GetRow(rowIndex)如果这行完全没有数据会返回null所以代码里必须加上if (row null) continue;否则空行会直接触发NullReferenceException中断整个遍历流程。这在实际生产文件里非常常见因为很多Excel导出工具会留空行。4.2 生成Excel文件的完整示例兼容NPOI 2.0读取之外生成Excel是另一个高频场景。很多老项目的报表导出就是简单地把DataTable循环塞进单元格里这里我展示一个稍完整些的代码包含表头样式、列宽调整、合并单元格和单元格边框这些细节直接影响报表的可用性。using System; using System.Data; using System.IO; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; class ExcelExporter { public static void ExportDataTableToExcel(DataTable dt, string filePath) { HSSFWorkbook workbook new HSSFWorkbook(); ISheet sheet workbook.CreateSheet(Sheet1); // 创建表头样式加粗 背景色 边框 ICellStyle headerStyle workbook.CreateCellStyle(); headerStyle.FillForegroundColor NPOI.HSSF.Util.HSSFColor.LightBlue.Index; headerStyle.FillPattern FillPattern.SolidForeground; headerStyle.BorderBottom BorderStyle.Thin; headerStyle.BorderTop BorderStyle.Thin; headerStyle.BorderLeft BorderStyle.Thin; headerStyle.BorderRight BorderStyle.Thin; IFont headerFont workbook.CreateFont(); headerFont.Boldweight (short)FontBoldWeight.Bold; headerStyle.SetFont(headerFont); // 写入表头 IRow headerRow sheet.CreateRow(0); for (int col 0; col dt.Columns.Count; col) { ICell cell headerRow.CreateCell(col); cell.SetCellValue(dt.Columns[col].ColumnName); cell.CellStyle headerStyle; sheet.AutoSizeColumn(col); } // 写入数据行 for (int row 0; row dt.Rows.Count; row) { IRow dataRow sheet.CreateRow(row 1); for (int col 0; col dt.Columns.Count; col) { ICell cell dataRow.CreateCell(col); object value dt.Rows[row][col]; if (value null || value DBNull.Value) { cell.SetCellValue(); } else if (value is int || value is long || value is float || value is double || value is decimal) { cell.SetCellValue(Convert.ToDouble(value)); } else if (value is DateTime) { cell.SetCellValue(((DateTime)value).ToString(yyyy-MM-dd HH:mm:ss)); } else { cell.SetCellValue(value.ToString()); } } } // 合并单元格示例合并第一行第一列到第二列做标题场景 // sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, 1)); using (FileStream fs new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } workbook.Close(); Console.WriteLine(导出成功 filePath); } }这个示例有一些我经验之谈的优化点。sheet.AutoSizeColumn这个API我建议在数据量比较小的时候用几十行数据量大或者完全不设置也可以因为AutoSizeColumn的原理是遍历列里所有单元格内容计算宽度上千行的表调用这个接口导出的耗时可能从秒级涨到几十秒体验很差。更好的做法是手动估算列宽sheet.SetColumnWidth(0, 12 * 256); // 宽度为12个字符 sheet.SetColumnWidth(1, 30 * 256);列宽的单位是字符宽度的256分之一这算是NPOI一个没什么文档但很实用的知识。FillPattern.SolidForeground一定要写否则背景色不生效。我早期写NPOI导出只设置了FillForegroundColor结果Excel里死活没颜色翻阅源码才明白FillPattern默认是NoFill必须显式指定。边框线的设置也是NPOI新手必踩的坑。默认创建的单元格没有任何边框导出后Excel看起来“没有表格线”但这只是视觉样式问题数据本身没有丢失。客户经常因为这个认为你没做表格所以记得给单元格设置边框设置方式见上面的headerStyle.BorderBottom等四行代码。4.3 处理.xlsx格式时API的差异老版本的NPOI 2.0也支持XSSF.xlsx格式但相比HSSF来说API的命名空间变了需要引用NPOI.XSSF.UserModel创建对象的方式变成XSSFWorkbook workbook new XSSFWorkbook();。要注意的是XSSF虽然也能在NPOI 2.0里使用但它依赖额外的程序集NPOI.OOXML.dll。这个程序集在老版本中存在的意义是为了解析OOXML格式的底层包结构底层逻辑其实涉及很多OpenXml约定的类。如果项目里只引用了NPOI.dll创建XSSFWorkbook时会直接抛TypeInitializationException很容易让人一头雾水。如果你主要处理的是新格式.xlsx且项目环境允许.NET Framework 4.0我更推荐直接在2.0.6基础上手动升级到2.1.6这个版本的XSSF支持已经很稳我拿它写过一个导出10万行数据的工具内存占用在一个可以接受的范围。再往上的3.x、4.x对XSSF的支持当然更好但升级的工程量也会变大需要评估。5. 常见问题与排查技巧实录5.1 版本冲突与程序集绑定问题NPOI引入了多个程序集之后最常碰到的问题就是程序集版本不一致。具体表现是编译没问题运行时报错类似未能加载文件或程序集“NPOI, Version2.0.6.0, Cultureneutral, PublicKeyToken0df73ec7942d1a01”或它的某一个依赖项。系统找不到指定的文件。这种问题百分之八九十是bin目录下DLL文件版本跟引用不一致造成的。排查思路是这样先看项目引用的NPOI版本在解决方案管理器的引用项上右键属性里可以看Version然后再去bin目录里看实际生成的NPOI.dll文件版本。如果发现不一致清空bin目录重新编译或者手动把正确版本的DLL复制过去。多环境部署时还会出现一种情况服务器GAC全局程序集缓存里注册了一个旧版本NPOI而应用本地又有新版本。这种情况下可以通过在Web.config或App.config里加绑定定向bindingRedirect来解决网上很多涉及NPOI报错的文章都会提到这个但很多人不知道绑定的写法。这里给一个针对NPOI的配置示例configuration runtime assemblyBinding xmlnsurn:schemas-microsoft-com:asm.v1 dependentAssembly assemblyIdentity nameNPOI publicKeyToken0df73ec7942d1a01 cultureneutral / bindingRedirect oldVersion0.0.0.0-2.1.6.0 newVersion2.1.6.0 / /dependentAssembly /assemblyBinding /runtime /configuration5.2 单元格格式错误Cannot get a STRING value from a NUMERIC cell这个错误基本上每个NPOI新手都会遇到。原因很简单Excel单元格里存的是数字类型但代码里却直接调用了StringCellValue来取值类型不匹配就抛异常。我给一个通用型的方法用于安全地从单元格取值public static string GetCellValueSafe(ICell cell) { if (cell null) return ; switch (cell.CellType) { case CellType.String: return cell.StringCellValue; case CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell)) return cell.DateCellValue.ToString(yyyy-MM-dd HH:mm:ss); // 处理大数字避免科学计数法 double num cell.NumericCellValue; if (num Math.Floor(num)) return ((long)num).ToString(); return num.ToString(); case CellType.Boolean: return cell.BooleanCellValue.ToString(); case CellType.Formula: return GetCellValueSafe(cell.CachedFormulaResultType CellType.Numeric ? cell.GetNumericCellValue() : (ICell)null); default: return ; } }这里我顺手处理了科学计数法的问题。Excel里数字超过特定位数时会显示成1.23457E17这种形式但实际数据可能是一个手机号或身份证号。代码里判断num Math.Floor(num)如果是整数就转成long再ToString能避免科学计数法。不过要提醒一句如果源单元格本身就被Excel存成了文本格式就不要走数字分支直接走字符串分支即可。5.3 大数据量导出时内存溢出老版本的NPOI 2.0在大数据量导出时内存占用是相当没谱的。处理几十万行的数据我用2.0.6直接爆过OutOfMemoryException。原因是HSSFWorkbook会把整个Sheet的所有行对象全部加载进内存再加上样式对象也是每个单元格单独持有的。面对这种场景我的建议是评估当前项目的实际限制。如果你只能在.NET 2.0/4.0外加NPOI 2.0.x的约束下工作那么最好的策略是分块导出——每5万行写一个Sheet或者拆成多个Excel文件写完后释放Workbook对象再创建新的。这种方式程序写起来更麻烦但至少内存可控。如果你的服务器环境能升级到.NET Framework 4.5以上那我强烈建议直接把NPOI升级到2.1.6或更新版本然后改用SXSSFWorkbook它是流式写入的。核心思想是数据不常驻内存写一行就刷新一行到临时文件只有控制窗口大小内的行会留在内存里。API大概这样SXSSFWorkbook workbook new SXSSFWorkbook(100); // 窗口100行这个类在3.x版本后是主力推荐的大数据导出方案。5.4 服务端导出Excel文件打不开的排查项目上线后客户反馈导出的Excel文件双击打不开Excel提示文件已损坏。这个应该是很多人的噩梦。我这里提供一个完整的排查顺序第一先检查是不是文件扩展名和实际文件格式不匹配。NPOI 2.0的HSSFWorkbook写出来后扩展名必须是.xls如果代码里用HSSFWorkbook但文件名写成.xlsxExcel打开肯定会报错。反过来XSSFWorkbook就要求.xlsx扩展名。这个错误几乎人人都会犯包括我自己早期干过这事。第二检查写入文件是否完整关闭。NPOI的workbook.Write(stream)之后一定要保证FileStream被正确Close或者Dispose。如果程序在写入过程中抛出异常而没有关闭流文件可能只有部分字节——注意我这里说的不是流被占用的问题而是数据没写完。用using包裹FileStream是最稳妥的写法。第三检查服务器上的杀毒软件或文件监控软件是否锁定了文件。我曾经在客户环境遇到诡异问题程序明明提示导出成功但Excel文件只有几KB甚至0KB后来排查发现是服务器的企业版杀毒软件对xls文件开启了“安全审查”功能把正在写入的文件锁住了。解决办法是在杀毒白名单里排除导出目录。5.5 老项目从NPOI 2.0升级到4.0的迁移要点如果你维护的老项目有升级空间我给你一个实际的迁移流程参考前置检查确认项目引用的所有第三方组件是否依赖NPOI的某个特定行为。如果一个项目里多处引用了NPOI先直接搜索HSSFWorkbook、XSSFWorkbook、HSSFDateUtil这些关键字统计代码量。代码量在几百行以内的直接升代码量超过几千行的需要考虑是不是值得升因为API细节差异多测试回归成本高。升级步骤我总结为四步用NuGet管理器将NPOI更新到4.x这个步骤会自动处理DLL引用但会留下一些废弃API的编译报错。把HSSFWorkbook、XSSFWorkbook改成统一的WorkbookFactory.Create(...)或者new XSSFWorkbook()这个不是必须的但能让代码在之后维护时更通用。全局替换掉直接操作底层类型的API。NPOI 4.x里很多方法的返回类型变成了接口最典型的就是CreateFont()返回IFont而不是HSSFFont如果你的代码里写了HSSFFont font workbook.CreateFont();会编译报错改成IFont font workbook.CreateFont();即可。检查所有.xls和.xlsx的处理分支确认逻辑没有因为格式判断改变而错乱。还有一个常常被忽略的点NPOI在4.x版本里增强了对Office 2016文件名长度、特殊字符的校验。老版本里你给Sheet命名一个包含[]的字符串能正常输出文件但是Excel 2016以上版本打开会提示修复。升级后NPOI会直接抛异常拦截这种非法命名。如果你的数据源里有这种特殊字符记得加异常过滤。6. 那个老系统的后续处理心得说回文章开头那个项目。我最后没有选择把NPOI从1.2.5升级到2.0.6而是用2.0.6修复了那个字段格式的问题。原因很现实客户的生产系统已经稳定运行快十年代码里大量调用了NPOI 1.x特有的API和内部实现一些方法在2.0里已经被标记为废弃甚至改变行为。在这种情况下最小改动原则远比引入新特性重要。我只花了一个小时修完bug在测试环境跑了十几分钟验证然后打包补丁事情就结束了。这个案例想表达的是在选择NPOI版本时没有“最好”只有“最合适”。老版本不是不能用关键是搞清楚它的能力边界以及预期内的坑在哪。NPOI 2.0版本很老但对于不依赖Office环境、只需要读写Excel的业务系统老项目来说它依然是一个非常可靠的方案。2.0.6作为支持.NET Framework 2.0的最终版本在很长一段时间里会继续为大量老系统服役。如果让我给一个最终的选型参考建议纯.NET 2.0老环境用2.0.6.NET 4.0能用2.1.6就用2.1.6.NET 4.5以上优先用最新4.x如果是新项目直接上.NET 6配合NPOI 2.6.x以上读写大文件选SXSSFWorkbook这是目前最省心的组合。要是实在拿不准先把环境框架列出来再对照这篇文章里的版本约束表做决策基本不会走偏。本文还有配套的精品资源点击获取