C#项目中怎么用MiniExcel快速读写Excel文件?

来源:Golang编程网作者:缅甸程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《C#项目中怎么用MiniExcel快速读写Excel文件?》,敬请观看详情。把百万行数据写进Excel时,传统组件常因内存占用过高导致程序崩溃。MiniExcel基于流式处理思路,边读边写避免全量加载,可将内存控制在极低水平。本文从安装、基础读写、模板填充到Web上传下载实战,拆解具体用法。相比ClosedXML,它更适合大文件场景,小文件也保持轻量。掌握这几个API,就能在C#里高效完成报表生成与数据导入,不必再为OOM头疼。

在C#生态中处理Excel文件,很多团队习惯用Epplus或NPOI,但遇到几十万行数据时就容易内存爆满。MiniExcel是一个基于流式读写设计的开源库,它不把整个文档加载到内存,而是按行处理,因此特别适合导入导出大体积表格。下面直接看具体用法。

C#项目中怎么用MiniExcel快速读写Excel文件?

一、环境准备与安装

MiniExcel以NuGet包形式发布,支持.NET Core 3.1及以上以及.NET Framework 4.6.1以上版本。在项目中引入非常简单,可以通过命令行或者Visual Studio的包管理器完成。安装后无需任何复杂配置,直接using对应命名空间即可使用。

为了验证环境,我们可以先建立一个控制台项目,然后执行安装命令。需要注意的是,MiniExcel依赖System.IO.Packaging,在部分旧框架中会自动 transitively 引用,一般不用手动处理。如果你在Linux下使用,确保运行时具备写临时文件的权限,因为底层会借助临时流提升性能。

// 通过NuGet安装
// Install-Package MiniExcel -Version 1.31.0

using MiniExcelLibs;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Console.WriteLine("MiniExcel ready");
    }
}

二、基础写入Excel

MiniExcel最基础的写法是把集合直接保存为xlsx文件。它支持匿名对象、强类型类以及Dictionary等多种数据源。写入时默认首行为属性名或字典键,后续每行对应一条记录。由于采用流式写出,即使十万条数据也不会出现明显内存增长。

下面示例定义一个订单类,并生成包含三列的文件。相比传统组件先建Workbook再建Sheet,MiniExcel一行静态方法就完成。你也可以通过第二个参数指定sheet名称,或者传入Stream实现网络响应写出。这种极简API显著降低了代码量,也减少了出错概率。

public class Order
{
    public int Id { get; set; }
    public string Product { get; set; }
    public decimal Price { get; set; }
}

var orders = new List<Order>
{
    new Order { Id = 1, Product = "键盘", Price = 99.9m },
    new Order { Id = 2, Product = "鼠标", Price = 59.5m }
};

// 同步写入本地文件
MiniExcel.SaveAs("orders.xlsx", orders, sheetName: "订单");

// 异步写入
await MiniExcel.SaveAsAsync("orders_async.xlsx", orders);

三、读取Excel数据

读取同样保持流式风格。使用MiniExcel.Query方法可延迟加载每一行,返回IEnumerable,配合强类型映射时自动按头行匹配属性。这样在导入大文件时,可以边读边做业务校验,而不必等全部载入。

如果Excel首行不是标准标题,可以通过UseHeaderRow参数控制。对于脏数据较多的场景,建议用动态类型读取成Dictionary再逐字段处理。以下代码展示如何把刚才生成的文件读回,并输出到控制台。注意读取时不支持随机跳转,这是为了保证低内存而做的设计权衡。

// 强类型读取
var rows = MiniExcel.Query<Order>("orders.xlsx");
foreach (var r in rows)
{
    Console.WriteLine($"{r.Id} {r.Product} {r.Price}");
}

// 动态读取为字典
var dynamicRows = MiniExcel.Query("orders.xlsx", useHeaderRow: true);
foreach (var d in dynamicRows)
{
    // d 是 IDictionary<string, object>
    Console.WriteLine(d["Product"]);
}

四、模板填充实战

报表常要求固定格式,比如表头带公司Logo、合并单元格等。MiniExcel支持基于已有模板的填充,只需在Excel里用@字段名做占位符,代码传入对象即可替换。它比手工画表稳定,也方便非开发人员维护模板。

假设有模板文件template.xlsx,其中某个单元格写了@UserName和@Total,我们传入匿名对象完成导出。模板机制同样走流,不会把整文件读进内存。下面的例子演示单对象填充,它也支持集合填充配合@List语法实现循环表格,这里先给出基础用法。

var fillData = new
{
    UserName = "张三",
    Total = 159.4m
};

MiniExcel.SaveAsByTemplate("report.xlsx", "template.xlsx", fillData);

五、Web场景导入导出

在ASP.NET Core里,MiniExcel能直接对接HttpResponse.Body流,避免中间文件。导出时设置Content-Type为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,并给Content-Disposition附文件名。导入则读取IFormFile.OpenReadStream,交给Query处理。

这种写法在并发导出时优势明显,因为每个请求只占少量托管内存。下面的控制器示例展示了下载与上传两个接口。上传部分用await MiniExcel.QueryAsync逐行入库,你可以插入数据库或做校验。注意大文件上传要在Startup限制表单大小,否则会被拒绝。

using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

[ApiController]
[Route("api/excel")]
public class ExcelController : ControllerBase
{
    [HttpGet("download")]
    public async Task<IActionResult> Download()
    {
        var data = new List<Order> { new Order { Id = 1, Product = "测试", Price = 10 } };
        Response.Headers.Add("Content-Disposition", "attachment; filename=test.xlsx");
        Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        await MiniExcel.SaveAsAsync(Response.Body, data);
        return new EmptyResult();
    }

    [HttpPost("upload")]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        var rows = await MiniExcel.QueryAsync<Order>(file.OpenReadStream(), useHeaderRow: true);
        foreach (var item in rows)
        {
            // 此处可写入数据库
        }
        return Ok();
    }
}

六、性能与注意事项

从压测看,导出一百万行乘十列,MiniExcel内存常驻在30MB左右,而NPOI可能突破800MB。代价是它不支持复杂样式和图表,若需求只是数据交换,这完全可接受。另外由于是流式,不能修改已写出的行,只能追加。

使用中应避开在读取时多次枚举同一Query结果,因为每次都会重新解析流。建议用ToList缓存或者一次性处理。对于包含公式的单元格,MiniExcel默认读取值而非公式,如需公式可用GetReader底层API。掌握这些边界,就能在C#项目里把Excel处理变得轻松且健壮。

对比项MiniExcel传统组件
内存占用低,流式高,全加载
大文件支持
样式能力基础丰富

C#MiniExcelExcel导入导出修改时间:2026-08-08 16:39:35

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。