using OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
namespace Syc.Basic.Web.WMS
{
public static class ExcelExporter
{
///
/// EPPlus 8.0+ 导出 List 数据为 Excel 内存流(带样式美化)
///
/// 数据模型类型
/// 要导出的数据集合
/// Excel 工作表名称
/// 自定义表头(key:模型属性名,value:Excel 表头文本)
/// Excel 内存流(需手动释放)
public static string ExportToExcelStream(
List dataList,
string sheetName = "数据报表",
string filePath = null,
Dictionary headerMap = null)
{
// 1. 配置 EPPlus 许可证(非商业用途,商业需购买许可证)
//ExcelPackage.License = License.NonCommercial;
// 2. 初始化 Excel 包和工作表
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add(sheetName);
// 3. 处理表头(支持自定义列名,无自定义则用模型属性名)
PropertyInfo[] properties = typeof(T).GetProperties();
int colIndex = 1;
// 写入表头
foreach (var prop in properties)
{
string headerText = headerMap?.ContainsKey(prop.Name) ?? false
? headerMap[prop.Name]
: prop.Name; // 优先用自定义表头,否则用属性名
worksheet.Cells[1, colIndex].Value = headerText;
colIndex++;
}
// 4. 写入数据(逐行逐列绑定)
int rowIndex = 2; // 第1行是表头,从第2行开始写数据
foreach (var data in dataList)
{
colIndex = 1;
foreach (var prop in properties)
{
var value = prop.GetValue(data);
// 特殊类型处理(避免日期/布尔值格式异常)
switch (value)
{
case DateTime date:
worksheet.Cells[rowIndex, colIndex].Value = date.ToString("yyyy-MM-dd HH:mm:ss");
break;
case bool b:
worksheet.Cells[rowIndex, colIndex].Value = b ? "是" : "否";
break;
case decimal d:
worksheet.Cells[rowIndex, colIndex].Value = d;
worksheet.Cells[rowIndex, colIndex].Style.Numberformat.Format = "0.00"; // 金额保留2位小数
break;
default:
worksheet.Cells[rowIndex, colIndex].Value = value ?? string.Empty;
break;
}
colIndex++;
}
rowIndex++;
}
// 5. 样式美化(表头加粗+背景色、自动列宽)
var headerRange = worksheet.Cells[1, 1, 1, properties.Length];
headerRange.Style.Font.Bold = true; // 表头加粗
headerRange.Style.Fill.PatternType = ExcelFillStyle.Solid;
headerRange.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightSkyBlue); // 表头背景色
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); // 自动调整所有列宽
// 6. 保存到内存流并返回
//var stream = new MemoryStream();
package.SaveAs(filePath);
// stream.Position = 0; // 重置流指针(关键:否则下载的文件为空)
return filePath;
}
}
}