发布于2026-07-01 阅读(0)
扫一扫,手机访问
不得不说,在报表这件事上,Excel几乎是个绕不过去的坎儿。以前很多人处理Excel文件,第一反应就是Microsoft.Office.Interop——那套方案你得先装Office,而且进程管理稍有不慎就容易出幺蛾子,算是历史遗留的“老办法”了。今天聊的MiniExcel就清爽很多,库文件不到1MB,核心思路是不依赖Office环境,直接操作.xlsx文件底层的ZIP压缩包,读写都在.NET Core或.NET Framework上跑得挺溜。

接下来,我们从最基础的读写开始,再到写入优化、样式设置,一步步把常见的操作场景串起来。
安装方式就是一行命令的事:
dotnet add package MiniExcel
读取Excel文件,MiniExcel提供了几种很直观的方式。可以直接把整个sheet读成List,也可以指定sheet名称,还可以读成DataTable方便后面做筛选。
using MiniExcelLibs;
// ===== 读 Excel =====
public void ReadExcel()
{
// 读取整个 sheet
var rows = MiniExcel.Query("report.xlsx").ToList();
// 读取指定 sheet
var rows2 = MiniExcel.Query("report.xlsx", sheetName: "Sheet2").ToList();
// 读取为 DataTable(便于筛选)
var dt = MiniExcel.QueryAsDataTable("report.xlsx");
foreach (DataRow row in dt.Rows)
{
Console.WriteLine($"{row["DeviceId"]} - {row["Value"]}");
}
}
写Excel也一样简洁,直接把List丢进去就行,连表头都会自动映射。
// ===== 写 Excel =====
public void WriteSimpleExcel()
{
var devices = new[]
{
new { DeviceId = "INJ001", Temperature = 85.5, Pressure = 1.2 },
new { DeviceId = "INJ002", Temperature = 82.3, Pressure = 1.1 }
};
// 最简单写法:List 直接写
MiniExcel.Sa veAs("output.xlsx", devices);
// 指定 sheet 名
MiniExcel.Sa veAs("output.xlsx", devices, sheetName: "生产数据");
}
这里有个常见的坑——MiniExcel默认会把所有数据一股脑加载到内存里。数据量小的时候没什么感觉,但一旦到了几十万行,内存就有点吃不消了。
解决办法也不复杂:分批写入。每次处理5000条,第一批负责创建文件并写入表头,后面批次通过AppendExcel追加数据即可。
public void WriteLargeFile(string filePath, IEnumerablerows) { var batchSize = 5000; var batch = new List (); using (var stream = File.Create(filePath)) { bool firstBatch = true; foreach (var row in rows) { batch.Add(row); if (batch.Count >= batchSize) { if (firstBatch) { // 第一批:创建文件 + 写入表头 stream.Seek(0, SeekOrigin.Begin); MiniExcel.Sa veAs(stream, batch, printHeader: true); firstBatch = false; } else { // 后续批次:追加到已有 sheet(通过 sheetName) MiniExcel.AppendExcel(stream, batch, sheetName: "Data"); } batch.Clear(); } } // 处理剩余数据 if (batch.Count > 0) { if (firstBatch) MiniExcel.Sa veAs(stream, batch, printHeader: true); else MiniExcel.AppendExcel(stream, batch, sheetName: "Data"); } } }
很多业务场景下,报表的格式是固定的,只是每次往里面填数据。MiniExcel支持基于模板生成报表——你先把模板Excel准备好,包括标题、列头、合并单元格等格式信息,然后通过Sa veAsByTemplate把数据注入进去。
// 报表模板(template.xlsx)包含:
// - A1: 标题(已合并单元格)
// - A3: 列头(DeviceId, Timestamp, Temperature...)
// - A4 以下:数据区(空着,等我们填充)
public void GenerateFromTemplate()
{
string templatePath = "template.xlsx";
string outputPath = "report_20240421.xlsx";
// 1. 复制模板
File.Copy(templatePath, outputPath, overwrite: true);
// 2. 读取模板内容(不覆盖格式)
var template = MiniExcel.QueryAsDataTable(outputPath);
// 3. 准备数据
var data = GetProductionData(); // List
// 4. 写入数据(从 A4 开始)
MiniExcel.Sa veAsByTemplate(outputPath, new
{
Title = "2024年4月21日 生产报表",
GenerateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm"),
Data = data // 这个 key 会对应模板中的 Data 区域
});
}
样式的控制上,MiniExcel提供了一些基础能力,比如设置列宽、列名、数字格式。如果需要更深入的样式控制(比如行高、背景色、字体),那就得借助底层操作了。
public void WriteWithStyle()
{
var rows = new List>
{
new Dictionary { ["DeviceId"] = "INJ001", ["Value"] = 85.5 },
new Dictionary { ["DeviceId"] = "INJ002", ["Value"] = 82.3 }
};
// 设置列配置
var columns = new Dictionary
{
["DeviceId"] = new MiniExcelColumnAttribute { Name = "设备编号", Width = 15 },
["Value"] = new MiniExcelColumnAttribute { Name = "测量值", Width = 12, Format = "0.00" }
};
// 写入并设置列宽
MiniExcel.Sa veAs("styled.xlsx", rows, configurations: columns);
}
如果确实需要更精细的样式控制,技术判断是:直接用MiniExcel做简单的样式配置,遇到复杂场景时果断引入ClosedXML或EPPlus来配合使用。
// 自定义样式(需要底层操作)
public void WriteWithCustomStyle(string filePath)
{
var config = new MiniExcelConfiguration
{
SheetName = "Report"
};
using var stream = File.Create(filePath);
stream.Seek(0, SeekOrigin.Begin);
// MiniExcel 支持通过 .xlsx 的 shared strings 和 styles.xml
// 完整样式控制建议用 ClosedXML 或 EPPlus
}
合并单元格在真实业务数据中很常见,但读取起来有点麻烦。MiniExcel默认会把合并单元格的值复制到每一行,如果你想精准识别哪些区域是合并的,需要手动解析单元格的MergeCount信息。
public void ReadMergedCells()
{
var cells = MiniExcel.GetCells("merged.xlsx").ToList();
var mergedRanges = cells
.Where(c => c.MergeCount > 0)
.Select(c => new
{
c.Value,
StartRow = c.Row,
EndRow = c.Row + c.MergeCount - 1,
StartCol = c.Column,
EndCol = c.Column + 1 // 简化:默认横向合并
})
.ToList();
foreach (var m in mergedRanges)
{
Console.WriteLine($"合并区域: {m.Value} ({m.StartRow}-{m.EndRow})");
}
}
总的来说,MiniExcel在轻量级、无Office依赖的Excel处理场景里,确实是值得考虑的选择。如果数据量不大、不需要复杂样式,用它就够了;如果需要更精致的报表设计,那配合ClosedXML或EPPlus做样式的深层控制,才是更成熟的实践路径。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8