Unity非游戏应用使用NPOI生成XLSX时出现vstream枚举缺失错误
嘿,我之前在Unity项目里用NPOI处理Excel的时候也踩过这个坑!你遇到的InvalidOperationException: Type NPOI.OpenXmlFormats.ItemChoiceType is missing enumeration value 'vstream'错误,本质是NPOI的OpenXML格式枚举定义不全,或者Unity的AOT链接器把未被直接引用的枚举成员给裁剪掉了。给你几个亲测有效的解决办法:
1. 优先升级NPOI到最新稳定版本
旧版本的NPOI(比如2.x之前的版本)可能没有包含vstream这个新增的OpenXML元素枚举值,直接去NuGet下载最新的NPOI和NPOI.OOXML包,替换掉Unity项目Plugins文件夹里的旧dll文件。
替换后记得检查Unity的.NET配置:
- 打开
Player Settings→Other Settings→Configuration - 将
Scripting Runtime Version设为.NET 4.x Equivalent - 将
Api Compatibility Level设为.NET Framework(NPOI对这个模式支持更完善)
2. 给IL2CPP打包添加链接器保留规则(如果用IL2CPP)
如果你的项目是用IL2CPP打包的,Unity的链接器会自动裁剪掉代码中没有直接引用的枚举成员,而vstream可能刚好是NPOI内部用到但你的代码没直接碰的枚举值。这时候需要添加一个link.xml文件到Assets/Plugins目录,强制保留这个枚举的所有成员:
<linker> <assembly fullname="NPOI.OpenXmlFormats"> <type fullname="NPOI.OpenXmlFormats.ItemChoiceType" preserve="all"/> </assembly> </linker>
3. 手动补全枚举值(不推荐,仅当无法升级时尝试)
如果因为项目限制不能升级NPOI,你可以尝试通过反射的方式动态添加枚举值,不过这个方法比较hack:
using System; using System.Reflection; // 在创建XSSFWorkbook之前执行这段代码 var enumType = typeof(NPOI.OpenXmlFormats.ItemChoiceType); var field = enumType.GetField("vstream", BindingFlags.Public | BindingFlags.Static); if (field == null) { // 获取枚举的基础类型 var underlyingType = Enum.GetUnderlyingType(enumType); // 假设vstream的枚举值是当前最大的值+1,或者查NPOI源码找正确值 object newValue = Convert.ChangeType(Enum.GetValues(enumType).Length, underlyingType); // 动态添加枚举字段 typeof(Enum).GetMethod("AddEnumValue", BindingFlags.NonPublic | BindingFlags.Static) ?.Invoke(null, new object[] { enumType, "vstream", newValue }); }
注意:这个方法依赖NPOI的内部实现,可能在不同版本失效,还是优先升级更稳妥。
4. 替代方案:换用EPPlus生成XLSX
如果NPOI的问题实在绕不开,可以试试EPPlus库——它也是一个强大的Excel处理库,对Unity的兼容性可能更好。不过要注意EPPlus 5.x及以后是商业许可证,如果你的项目是开源或非商业用途,可以用4.x版本(MIT许可证),代码生成XLSX的逻辑和NPOI类似,上手成本很低。
内容的提问来源于stack exchange,提问作者Salbrox

