OpenXml、NPOI、EPPlus、Spire.Office组件对EXCEL ole对象附件的支持

OpenXml、NPOI、EPPlus、Spire.Office 对EXCEL插入附件的读取支持情况(比如插入ZIP文件)

这些主流Excel操作库对插入附件(如ZIP文件)的支持情况如下:

📊 支持情况对比

库名称 版本 附件读取支持 实现方式 备注
OpenXml 2.20+ ✅ 完全支持 直接操作OLE对象 最底层,最灵活
NPOI 2.7+ ✅ 支持 通过OLE对象访问 需要额外处理
EPPlus 5.8+ ⚠️ 有限支持 通过OLE对象 商业版支持更好
Spire.Office 13.8+ ✅ 支持 内置方法 商业库,功能完整

🔧 各库具体实现

1. OpenXml SDK - 最底层支持

cs 复制代码
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

public void ExtractAttachments(string filePath, string outputDir)
{
    using (var spreadsheet = SpreadsheetDocument.Open(filePath, false))
    {
        var workbookPart = spreadsheet.WorkbookPart;
        
        // 获取所有OLE对象
        foreach (var oleObject in workbookPart.OleObjectsPart?.OleObjects.Elements<OleObject>())
        {
            var objectId = oleObject.Id.Value;
            var embeddedObjectPart = (EmbeddedObjectPart)workbookPart.GetPartById(objectId);
            
            // 保存附件
            using (var stream = embeddedObjectPart.GetStream())
            {
                var fileName = $"attachment_{objectId}.bin";
                File.WriteAllBytes(Path.Combine(outputDir, fileName), ReadStream(stream));
            }
        }
    }
}

private byte[] ReadStream(Stream stream)
{
    using (var memoryStream = new MemoryStream())
    {
        stream.CopyTo(memoryStream);
        return memoryStream.ToArray();
    }
}

2. NPOI - 需要额外处理

cs 复制代码
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;

public void ExtractAttachmentsNPOI(string filePath, string outputDir)
{
    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        var workbook = new XSSFWorkbook(fs);
        var xssfWorkbook = (XSSFWorkbook)workbook;
        
        // 获取所有嵌入对象
        var package = xssfWorkbook.GetPackage();
        foreach (var partName in package.GetPartsByName("/xl/embeddings/.*"))
        {
            var part = package.GetPart(partName);
            using (var stream = part.GetInputStream())
            {
                var fileName = Path.GetFileName(partName.Name);
                File.WriteAllBytes(Path.Combine(outputDir, fileName), ReadStream(stream));
            }
        }
    }
}

3. EPPlus - 商业版支持更好

cs 复制代码
using OfficeOpenXml;

public void ExtractAttachmentsEPPlus(string filePath, string outputDir)
{
    ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
    
    using (var package = new ExcelPackage(new FileInfo(filePath)))
    {
        // EPPlus 5.8+ 商业版支持
        var workbook = package.Workbook;
        
        // 通过自定义方式访问OLE对象
        foreach (var worksheet in workbook.Worksheets)
        {
            var drawings = worksheet.Drawings;
            foreach (var drawing in drawings)
            {
                if (drawing is ExcelOleObjectDrawing oleObject)
                {
                    // 商业版功能
                    var content = oleObject.Content;
                    if (content != null)
                    {
                        File.WriteAllBytes(Path.Combine(outputDir, $"ole_{oleObject.Name}.bin"), content);
                    }
                }
            }
        }
    }
}

4. Spire.Office - 最便捷

cs 复制代码
using Spire.Xls;

public void ExtractAttachmentsSpire(string filePath, string outputDir)
{
    Workbook workbook = new Workbook();
    workbook.LoadFromFile(filePath);
    
    // 直接获取所有OLE对象
    foreach (Worksheet sheet in workbook.Worksheets)
    {
        foreach (Spire.Xls.OleObject oleObject in sheet.OleObjects)
        {
            // 获取附件数据
            byte[] data = oleObject.Data;
            string extension = GetFileExtension(oleObject.ObjectType);
            
            File.WriteAllBytes(Path.Combine(outputDir, 
                $"attachment_{sheet.Name}_{oleObject.Location.Row}_{oleObject.Location.Column}{extension}"), 
                data);
        }
    }
}

private string GetFileExtension(OleObjectType objectType)
{
    switch (objectType)
    {
        case OleObjectType.Package: return ".zip";
        case OleObjectType.AcrobatDocument: return ".pdf";
        case OleObjectType.WordDocument: return ".doc";
        default: return ".bin";
    }
}

📋 功能对比详情

OpenXml SDK

  • 优点: 最底层控制,支持所有附件类型

  • 缺点: 代码复杂,需要深入了解OOXML结构

  • 适用: 需要完全控制的高级场景

NPOI

  • 优点: 开源免费,支持基本附件操作

  • 缺点: API不够直观,需要手动处理Package

  • 适用: Java/.NET跨平台项目

EPPlus

  • 优点: API友好,性能优秀

  • 缺点: 免费版附件功能有限,商业版较贵

  • 适用: 简单Excel操作,商业项目

Spire.Office

  • 优点: 功能完整,API简单易用

  • 缺点: 商业收费,免费版有限制

  • 适用: 企业级应用,需要快速开发

🎯 推荐选择

  1. 完全免费 → NPOI

  2. 企业项目 → Spire.Office

  3. 底层控制 → OpenXml SDK

  4. 已有EPPlus → 升级到商业版

⚠️ 注意事项

  • 附件可能存储在/xl/embeddings//xl/oleObjects/路径

  • ZIP文件通常作为OLE Package对象插入

  • 需要处理不同的内容类型(MIME types)

  • 注意内存使用,大附件需要流式处理

根据你的具体需求和技术栈选择合适的库。

相关推荐
胡gh1 小时前
页面卡成PPT?重排重绘惹的祸!依旧性能优化
前端·javascript·面试
言兴2 小时前
# 深度解析 ECharts:从零到一构建企业级数据可视化看板
前端·javascript·面试
山有木兮木有枝_2 小时前
TailWind CSS
前端·css·postcss
烛阴2 小时前
TypeScript 的“读心术”:让类型在代码中“流动”起来
前端·javascript·typescript
唐青枫2 小时前
ValueTask 实战指南:解锁 .NET 异步编程的性能秘密
c#·.net
杨荧2 小时前
基于Python的农作物病虫害防治网站 Python+Django+Vue.js
大数据·前端·vue.js·爬虫·python
Moment3 小时前
毕业一年了,分享一下我的四个开源项目!😊😊😊
前端·后端·开源
程序视点4 小时前
Escrcpy 3.0投屏控制软件使用教程:无线/有线连接+虚拟显示功能详解
前端·后端
silent_missile4 小时前
element-plus穿梭框transfer的调整
前端·javascript·vue.js