EPPlus进阶实战:从数据导出到报表美化的C#自动化指南

夏末的回忆

1. EPPlus库简介与基础准备

EPPlus是一个强大的开源库,专门用于在C#中操作Excel文件。它支持Excel 2007/2010/2013/2016的文件格式(.xlsx),提供了丰富的API来处理工作表、单元格、公式、图表等。相比传统的Microsoft.Office.Interop.Excel,EPPlus不需要安装Office软件,性能更好,特别适合在服务器端生成报表。

要开始使用EPPlus,首先需要通过NuGet安装它。在Visual Studio中,打开NuGet包管理器控制台,输入以下命令:

csharp复制Install-Package EPPlus

安装完成后,记得在代码文件顶部添加引用:

csharp复制using OfficeOpenXml;
using OfficeOpenXml.Style;

EPPlus有商业版和开源版两种授权方式。对于大多数个人和小型项目,开源版已经足够使用。在代码开始时设置授权上下文:

csharp复制ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

基础准备工作还包括了解ExcelPackage和ExcelWorksheet这两个核心类。ExcelPackage代表整个Excel文件,而ExcelWorksheet则对应文件中的单个工作表。创建它们的基本代码如下:

csharp复制using (var package = new ExcelPackage())
{
    var worksheet = package.Workbook.Worksheets.Add("Sheet1");
    // 在这里添加你的数据处理代码
    package.SaveAs(new FileInfo(@"C:\output.xlsx"));
}

2. 数据导出基础操作

将数据导出到Excel是EPPlus最基本的功能。假设我们有一个DataTable或者List集合,需要将其内容导出到Excel中。下面是一个完整的示例:

csharp复制public void ExportToExcel<T>(List<T> data, string filePath)
{
    using (var package = new ExcelPackage())
    {
        var worksheet = package.Workbook.Worksheets.Add("Data");
        
        // 写入表头
        var properties = typeof(T).GetProperties();
        for (int i = 0; i < properties.Length; i++)
        {
            worksheet.Cells[1, i + 1].Value = properties[i].Name;
            worksheet.Cells[1, i + 1].Style.Font.Bold = true;
        }
        
        // 写入数据
        for (int i = 0; i < data.Count; i++)
        {
            for (int j = 0; j < properties.Length; j++)
            {
                worksheet.Cells[i + 2, j + 1].Value = properties[j].GetValue(data[i]);
            }
        }
        
        package.SaveAs(new FileInfo(filePath));
    }
}

对于DataGrid控件的导出,方法类似但需要考虑列头和绑定数据:

csharp复制public void ExportDataGridToExcel(DataGrid dataGrid, string filePath)
{
    using (var package = new ExcelPackage())
    {
        var worksheet = package.Workbook.Worksheets.Add("Sheet1");
        
        // 写入列头
        for (int i = 0; i < dataGrid.Columns.Count; i++)
        {
            worksheet.Cells[1, i + 1].Value = dataGrid.Columns[i].Header;
            worksheet.Cells[1, i + 1].Style.Font.Bold = true;
        }
        
        // 写入数据
        for (int i = 0; i < dataGrid.Items.Count; i++)
        {
            for (int j = 0; j < dataGrid.Columns.Count; j++)
            {
                var cellValue = dataGrid.Columns[j].GetCellContent(dataGrid.Items[i]);
                if (cellValue is TextBlock textBlock)
                {
                    worksheet.Cells[i + 2, j + 1].Value = textBlock.Text;
                }
            }
        }
        
        package.SaveAs(new FileInfo(filePath));
    }
}

3. 高级单元格样式设置

要让导出的Excel看起来更专业,单元格样式设置至关重要。EPPlus提供了丰富的样式API,可以精确控制每个单元格的外观。

首先,设置字体样式:

csharp复制worksheet.Cells["A1:D1"].Style.Font.Bold = true;  // 加粗
worksheet.Cells["A1:D1"].Style.Font.Size = 12;    // 字号
worksheet.Cells["A1:D1"].Style.Font.Color.SetColor(Color.DarkBlue);  // 字体颜色

然后是单元格填充色和边框:

csharp复制// 设置填充色
worksheet.Cells["A1:D1"].Style.Fill.PatternType = ExcelFillStyle.Solid;
worksheet.Cells["A1:D1"].Style.Fill.BackgroundColor.SetColor(Color.LightGray);

// 设置边框
worksheet.Cells["A1:D10"].Style.Border.Top.Style = ExcelBorderStyle.Thin;
worksheet.Cells["A1:D10"].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
worksheet.Cells["A1:D10"].Style.Border.Left.Style = ExcelBorderStyle.Thin;
worksheet.Cells["A1:D10"].Style.Border.Right.Style = ExcelBorderStyle.Thin;

行高和列宽的设置也很重要:

csharp复制// 设置行高
worksheet.Row(1).Height = 25;  // 第一行高度为25

// 设置列宽
worksheet.Column(1).Width = 15;  // 第一列宽度为15
worksheet.Column(2).AutoFit();   // 第二列自动调整宽度

对于条件格式,EPPlus也能轻松实现:

csharp复制// 添加数据条
var range = worksheet.Cells["B2:B10"];
var dataBar = range.ConditionalFormatting.AddDatabar(Color.Blue);
dataBar.ShowValue = true;

// 添加色阶
var colorScale = worksheet.Cells["C2:C10"].ConditionalFormatting.AddThreeColorScale();
colorScale.LowValue.Color = Color.Red;
colorScale.MiddleValue.Color = Color.Yellow;
colorScale.HighValue.Color = Color.Green;

4. 动态插入图片与图表

在报表中插入图片可以让数据展示更加直观。EPPlus支持从文件或内存流中插入图片:

csharp复制public void InsertImage(ExcelWorksheet worksheet, string imagePath, int row, int col)
{
    using (var image = new Bitmap(imagePath))
    {
        var picture = worksheet.Drawings.AddPicture(Guid.NewGuid().ToString(), image);
        picture.SetPosition(row - 1, 0, col - 1, 0);
        picture.SetSize(200, 150);  // 设置图片大小
    }
}

// 从字节数组插入图片
public void InsertImageFromBytes(ExcelWorksheet worksheet, byte[] imageBytes, int row, int col)
{
    using (var stream = new MemoryStream(imageBytes))
    {
        var image = Image.FromStream(stream);
        var picture = worksheet.Drawings.AddPicture(Guid.NewGuid().ToString(), image);
        picture.SetPosition(row - 1, 0, col - 1, 0);
        picture.SetSize(200, 150);
    }
}

创建图表也很简单,EPPlus支持多种图表类型:

csharp复制var chart = worksheet.Drawings.AddChart("chart1", eChartType.ColumnClustered);
chart.SetPosition(5, 0, 5, 0);
chart.SetSize(600, 400);

// 添加数据系列
var series = chart.Series.Add(worksheet.Cells["B2:B10"], worksheet.Cells["A2:A10"]);
series.Header = "销售额";

// 设置图表标题
chart.Title.Text = "月度销售报表";
chart.Title.Font.Size = 14;
chart.Title.Font.Bold = true;

5. 创建专业商业报表

要创建真正专业的商业报表,需要结合前面介绍的各种技术。下面是一个完整的商业报表生成示例:

csharp复制public void GenerateBusinessReport(List<SalesData> salesData, string logoPath, string outputPath)
{
    using (var package = new ExcelPackage())
    {
        var worksheet = package.Workbook.Worksheets.Add("销售报表");
        
        // 添加公司Logo
        InsertImage(worksheet, logoPath, 1, 1);
        
        // 报表标题
        worksheet.Cells["C2"].Value = "2023年度销售报告";
        worksheet.Cells["C2"].Style.Font.Size = 16;
        worksheet.Cells["C2"].Style.Font.Bold = true;
        worksheet.Cells["C2"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
        
        // 合并单元格
        worksheet.Cells["C2:F2"].Merge = true;
        
        // 表头
        string[] headers = { "月份", "销售额", "同比增长", "完成率" };
        for (int i = 0; i < headers.Length; i++)
        {
            worksheet.Cells[4, i + 2].Value = headers[i];
            worksheet.Cells[4, i + 2].Style.Font.Bold = true;
            worksheet.Cells[4, i + 2].Style.Fill.PatternType = ExcelFillStyle.Solid;
            worksheet.Cells[4, i + 2].Style.Fill.BackgroundColor.SetColor(Color.LightGray);
        }
        
        // 数据
        for (int i = 0; i < salesData.Count; i++)
        {
            worksheet.Cells[i + 5, 2].Value = salesData[i].Month;
            worksheet.Cells[i + 5, 3].Value = salesData[i].Amount;
            worksheet.Cells[i + 5, 4].Value = salesData[i].GrowthRate;
            worksheet.Cells[i + 5, 5].Value = salesData[i].CompletionRate;
            
            // 设置百分比格式
            worksheet.Cells[i + 5, 4].Style.Numberformat.Format = "0.00%";
            worksheet.Cells[i + 5, 5].Style.Numberformat.Format = "0.00%";
        }
        
        // 添加图表
        var chart = worksheet.Drawings.AddChart("salesChart", eChartType.ColumnClustered);
        chart.SetPosition(5, 0, 7, 0);
        chart.SetSize(800, 400);
        
        var series1 = chart.Series.Add(worksheet.Cells["C5:C16"], worksheet.Cells["B5:B16"]);
        series1.Header = "销售额";
        
        // 设置表格边框
        var dataRange = worksheet.Cells["B4:E16"];
        dataRange.Style.Border.Top.Style = ExcelBorderStyle.Thin;
        dataRange.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
        dataRange.Style.Border.Left.Style = ExcelBorderStyle.Thin;
        dataRange.Style.Border.Right.Style = ExcelBorderStyle.Thin;
        
        // 自动调整列宽
        worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
        
        // 保存文件
        package.SaveAs(new FileInfo(outputPath));
    }
}

6. 性能优化与实用技巧

处理大量数据时,性能优化很重要。以下是一些实用技巧:

  1. 批量写入数据:使用LoadFromCollection或LoadFromDataTable方法比逐个单元格写入快得多:
csharp复制// 快速写入List数据
worksheet.Cells["A2"].LoadFromCollection(dataList, false);

// 快速写入DataTable
worksheet.Cells["A2"].LoadFromDataTable(dataTable, false);
  1. 禁用计算和绘图:在写入大量数据时,临时禁用这些功能可以提高性能:
csharp复制package.Workbook.CalcMode = ExcelCalcMode.Manual;
// 处理数据...
package.Workbook.CalcMode = ExcelCalcMode.Automatic;
  1. 使用命名范围:可以使公式更易读和维护:
csharp复制var namedRange = worksheet.Names.Add("SalesData", worksheet.Cells["B2:E100"]);
  1. 模板技术:对于固定格式的报表,可以先创建模板文件,然后只填充数据:
csharp复制using (var templateStream = new FileStream("template.xlsx", FileMode.Open))
{
    using (var package = new ExcelPackage(templateStream))
    {
        var worksheet = package.Workbook.Worksheets["Sheet1"];
        // 填充数据...
        package.SaveAs(new FileInfo("output.xlsx"));
    }
}
  1. 内存管理:处理大量图片时要注意内存释放:
csharp复制using (var image = new Bitmap(imagePath))
{
    // 插入图片...
}  // 这里会自动释放图像资源
  1. 错误处理:添加适当的异常处理:
csharp复制try
{
    // Excel操作代码...
}
catch (InvalidOperationException ex)
{
    // 处理特定异常
}
catch (Exception ex)
{
    // 处理一般异常
}

在实际项目中,我发现合理使用这些技巧可以显著提高报表生成速度,特别是在处理数千行数据和多个工作表时。

内容推荐

Cadence HDL原理图设计避坑指南:从栅格设置到工程重命名全流程
本文详细解析Cadence HDL原理图设计中的常见问题与解决方案,涵盖栅格设置、元件库转换、工程重命名等关键操作。通过实战技巧和脚本示例,帮助硬件工程师提升设计效率,避免常见陷阱,优化工作流程。
【K8S】从请求到容器:Service、Kube-Proxy与Pod的流量寻址之旅
本文深入解析Kubernetes中Service、kube-proxy与Pod的流量寻址机制,通过生动类比揭示从请求到容器的完整路径。重点探讨Service的负载均衡原理、kube-proxy的iptables/ipvs模式演进,以及生产环境中的性能优化技巧,帮助开发者掌握K8S核心网络架构。
基于Python与NETCONF实现华为CE系列交换机自动化配置实战
本文详细介绍了如何基于Python与NETCONF协议实现华为CE系列交换机的自动化配置。从环境搭建、基础配置到Python脚本开发,提供了完整的实战指南,特别针对华为设备的NETCONF实现进行了优化,帮助网络工程师提升配置效率。
别再搞混了!ROS Melodic/Noetic中joint_state_publisher和robot_state_publisher的保姆级配置指南
本文深入解析ROS Melodic/Noetic中joint_state_publisher和robot_state_publisher的核心功能与配置方法,提供保姆级launch文件编写指南。通过对比表、参数详解和典型问题排查方案,帮助开发者正确配置这两个关键节点,解决TF树生成和Rviz模型显示等常见问题,提升机器人开发效率。
uni-app中superwei-combox组件的实战应用与数据交互
本文详细介绍了uni-app中superwei-combox组件的实战应用与数据交互技巧。通过双向绑定、智能搜索等核心功能,该组件有效解决了传统下拉选择框的体验问题。文章涵盖基础使用、数据绑定、事件处理、API集成等场景,并提供了性能优化和移动端适配的实用方案,帮助开发者快速实现高效的下拉搜索选择功能。
给5GC网元起外号:AMF是‘前台’,UPF是‘快递员’,这样理解5G核心网就简单了
本文通过生活场景类比,生动解析5G核心网(5GC)中AMF、SMF、UPF等关键网元的功能。AMF如同酒店前台处理接入认证,SMF像项目经理协调会话资源,UPF则承担数据快递员角色,而UDM则是用户数据的保险箱。这种形象化解读帮助读者轻松理解5G核心网工作原理,特别适合非技术人员快速掌握5GC架构。
Pandas数据清洗避坑指南:中位数填充、cut离散化、min-max归一化,一个函数搞定一种脏数据
本文深入解析Pandas数据清洗中的三大核心技巧:中位数填充缺失值、cut离散化处理以及min-max归一化,揭示常见陷阱并提供工业级解决方案。针对数据预处理中的关键问题,如异常值处理、边界条件设定和内存优化,给出了可复用的代码实现和性能优化策略,帮助数据分析师高效处理各类脏数据。
【AD9361 LVDS接口实战解析】并行数据流与时钟同步设计
本文深入解析AD9361芯片的LVDS接口设计,重点探讨并行数据流与时钟同步的关键技术。通过实战经验分享,详细介绍了源同步时序设计、帧同步机制优化以及TDD/FDD模式下的突发控制策略,并提供了信号完整性设计要点和常见问题解决方案,帮助工程师提升射频数据传输质量。
手把手教你为FPGA项目选型和连接CY7C68013A的56个引脚(附原理图检查清单)
本文详细解析了CY7C68013A芯片在FPGA项目中的硬件设计要点,包括56个引脚的分类策略、电源架构设计及信号完整性优化。特别针对USB 2.0高速通信需求,提供了原理图检查清单和故障排查指南,帮助开发者高效完成FPGA与CY7C68013A的连接与调试。
POE供电的‘隐藏’成本与避坑指南:从4芯网线布线到百米传输的实战经验
本文深入探讨POE供电在实际部署中的‘隐藏’成本与解决方案,重点分析4芯与8芯网线的选择对稳定性的影响,并提供百米传输的实测数据。通过分享末端跨接法等实用技巧和7个关键验收维度,帮助工程师避免常见陷阱,确保POE供电系统的长期稳定运行。
SAP QM核心事务码:从检验计划到质量通知的实战指南
本文详细解析SAP QM模块核心事务码的应用实践,从检验计划(QP01)到质量通知(QM01)的全流程操作指南。通过实战案例展示如何利用TCODE提升质量管理效率,包括检验批次管理(QA01)、结果记录(QE01)和缺陷追踪(QF01)等关键功能,帮助企业实现ISO 9001标准的数字化落地。
C# WinForm项目实战:手把手教你搭建本地测试服务器,调试Autoupdater.NET的完整流程
本文详细介绍了如何在C# WinForm项目中搭建本地测试服务器,完整调试Autoupdater.NET的软件升级流程。从环境准备、基础配置到构建本地服务器、制作更新包,再到高级调试技巧和自动化测试方案,手把手教你确保软件升级功能的可靠性。特别适合需要实现安全、稳定软件升级机制的开发者参考。
TI毫米波雷达AWR1642+DCA1000EVM保姆级避坑指南:从软件下载到数据采集的完整流程
本文详细解析了TI毫米波雷达AWR1642与DCA1000EVM数据采集卡的完整配置流程,涵盖硬件连接、软件环境设置、常见错误解决方案及数据采集高级技巧。特别针对FPGA配置、电源噪声抑制等关键问题提供实用指南,帮助开发者高效完成毫米波信号采集与处理,适用于自动驾驶和工业检测等领域。
告别DHCP!用华为/华三路由器5分钟搞定IPv6无状态地址自动配置
本文详细介绍了如何在华为CE系列和华三SR系列路由器上快速部署IPv6无状态地址自动配置(SLAAC),替代传统DHCPv4。通过配置路由器通告(RA)的关键参数,如前缀信息、M/O标志位和路由器生存时间,实现终端设备的即插即用,显著提升大规模网络地址分配效率。
Vue3项目实战:用mitt插件和useAttrs优雅处理Element Plus组件的属性透传
本文详细介绍了在Vue3项目中如何利用mitt插件和useAttrs实现Element Plus组件的优雅属性透传。通过实战案例展示了useAttrs的高级用法和mitt事件总线的跨组件通信能力,解决了传统方案中的代码冗余和维护难题,提升开发效率和组件灵活性。
Spring Boot 3.2 升级实战:深度解析 'factoryBeanObjectType' 类型错误与 MyBatis 生态适配
本文详细解析了Spring Boot 3.2升级过程中遇到的'Invalid value type for attribute 'factoryBeanObjectType''类型错误,特别是在整合MyBatis或MyBatis-Plus时。文章深入探讨了问题的根源、技术原理,并提供了官方推荐解决方案和临时修复方法,帮助开发者顺利完成升级并避免常见陷阱。
PMIC:从“心脏”到“大脑”,看一颗芯片如何重塑设备电源架构
本文深入探讨了PMIC(电源管理集成电路)从传统供电到智能管理的进化历程。通过实际案例展示了PMIC如何像大脑一样精准控制设备电源,实现多电压域协同、功耗智能切换及AI驱动的优化策略,显著提升设备性能和能效。文章还提供了PMIC选型指南和设计避坑经验,为工程师提供实用参考。
从零开始,用SWAT模型搞定农业面源污染模拟(附ArcGIS 10.6+SWAT-CUP完整配置流程)
本文详细介绍了如何使用SWAT模型进行农业面源污染模拟的全流程,包括数据准备、模型搭建、参数率定和结果解析。特别针对ArcGIS 10.6与SWAT-CUP的协同工作流程进行深度解析,帮助读者从零开始掌握SWAT模型的应用技巧,提升农业面源污染模拟的精度和效率。
从SRAM分区到总线仲裁:深入STM32G431内存架构,解决你的程序卡顿与DMA冲突难题
本文深入解析STM32G431内存架构,从SRAM分区到总线仲裁,解决程序卡顿与DMA冲突难题。详细介绍了32KB SRAM的三分区设计、总线矩阵的隐形战场及实战优化策略,帮助开发者提升嵌入式系统性能。特别适合蓝桥杯参赛者和STM32开发者参考。
实战指南:利用 .NET Upgrade Assistant 实现遗留项目现代化迁移
本文详细介绍了如何使用.NET Upgrade Assistant将遗留.NET项目现代化迁移至最新.NET平台。通过实战案例和分步指南,帮助开发者解决升级过程中的常见问题,如NuGet包冲突和Web.config转换,并提供了性能对比测试和企业级升级策略,显著提升项目性能和跨平台支持。
已经到底了哦
精选内容
热门内容
最新内容
【RDkit】SMILES标准化中的手性陷阱:从参数误解到分子生成实战复盘
本文深入探讨了RDKit中SMILES标准化过程中的手性参数陷阱,揭示了`isomericSmiles=False`默认设置对药物研发的潜在风险。通过实战案例和代码示例,详细分析了手性信息丢失导致的连锁反应,并提供了构建手性安全分子处理流程的最佳实践和检查清单,助力化学信息学工作避免常见陷阱。
SPSS小白也能搞定!用PROCESS插件做中介效应检验的保姆级教程(附模型4选择避坑)
本文为SPSS初学者提供了使用PROCESS插件进行中介效应检验的详细教程,特别推荐Model 4作为基础中介分析的首选模型。通过安装指南、模型选择策略、选项配置技巧和结果解读方法,帮助用户轻松掌握中介分析的核心步骤,避免常见错误。
Py之optimum:从入门到精通,解锁HuggingFace模型硬件加速实战指南
本文详细介绍了如何使用Optimum库优化HuggingFace模型在不同硬件上的推理性能。从基础安装到OpenVINO加速、动态量化等高级技巧,帮助开发者显著提升模型运行效率,降低资源消耗。通过实战案例展示,Optimum可实现3-5倍的推理速度提升,是生产环境部署的必备工具。
除了AJE,还有哪些润色服务能过IEEE的关?一份给学术新手的性价比方案对比
本文为学术新手提供IEEE认可的论文润色服务性价比方案对比,详细分析了AJE替代服务的核心标准、主流润色服务横向对比及质量评估指标。重点推荐Scribendi和Wordvice等性价比突出的服务,并分享非AJE润色证明的提交技巧和应急策略,帮助研究者高效通过IEEE审核。
别再死记硬背了!用NumPy的gradient函数搞定图像边缘检测与物理场分析
本文深入探讨了NumPy的gradient函数在图像边缘检测与物理场分析中的高级应用。通过实战案例,展示了如何利用该函数进行多维梯度计算,包括温度场模拟、流体力学分析及图像处理,帮助读者摆脱死记硬背,掌握工程实践中的核心技巧。
从STC89C51到蓝牙SOC:一个老嵌入式工程师的‘芯片观’演变史
本文通过一位嵌入式工程师从STC89C51到蓝牙SOC的开发经历,展现了芯片技术的演进对工程师思维方式的深刻影响。文章详细对比了传统MCU与SOC在开发方式、资源利用和项目周期等方面的差异,并分享了在蓝牙SOC项目中积累的实战经验与行业洞察,为嵌入式开发者提供了宝贵的技术转型指南。
告别数据下载焦虑:用GEE的calendarRange函数,5分钟搞定MODIS GPP的年总/月均合成
本文介绍了如何利用Google Earth Engine(GEE)的`ee.Filter.calendarRange`函数高效处理MODIS GPP数据,实现年总和与月均值的智能聚合。通过对比传统方法与GEE的处理效率,展示了GEE在遥感数据分析中的显著优势,帮助生态学家快速完成时间序列分析,提升研究效率。
别再死磕标注数据了!用MixMatch搞定半监督图像分类,PyTorch实战代码逐行解析
本文深入解析MixMatch半监督学习算法在图像分类中的应用,提供PyTorch实战代码逐行解析。通过数据增强、一致性正则化和熵最小化三大技术,MixMatch显著提升模型性能,减少标注数据需求。文章涵盖核心原理、PyTorch实现细节、调优技巧及医疗影像和电商分类的工业级应用案例,帮助开发者高效利用未标注数据提升分类效果。
从浮栅到电荷陷阱:NAND架构演进如何重塑SSD性能格局
本文深入探讨了NAND闪存从浮栅(FG)到电荷陷阱(CTF)架构的演进,分析了两者在SSD性能、耐久度和数据保持能力上的差异。通过实测数据和场景对比,揭示了不同架构在SLC/MLC和TLC/QLC时代的性能博弈,以及三维堆叠技术下的最新发展趋势,为存储方案选型提供专业指导。
自动驾驶TPM技术漫谈 ———— 路缘石几何建模与感知挑战
本文探讨了自动驾驶TPM技术中路缘石的几何建模与感知挑战。路缘石作为自动驾驶系统的关键参照物,其多样化的几何特征和复杂的感知环境对系统安全提出了严峻考验。文章详细分析了截面类型数字化表达、曲线路缘石数学建模、多传感器融合局限等核心技术难题,并提出了基于粒子滤波的定位增强和动态安全边界计算等解决方案。