C#封装EPPlus库为Excel导出工具
1,添加NUGet包

2,封装工具类
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;namespace GMWPF.utils
{public class ExcelUtil<T>{/// <summary>/// excel打印/// </summary>/// <param name="datas">需要打印的数据集合</param>/// <param name="columnNames">表头列名</param>/// <param name="columnIgnores">实体类中需要忽略的列名</param>/// <param name="filePath">文件保存路径</param>/// <param name="fileName">文件名</param>public static void ExportExcel(List<T> datas,List<string> columnNames, List<string>columnIgnores,string filePath,string fileName){ExcelPackage.LicenseContext = LicenseContext.NonCommercial;using (ExcelPackage package = new ExcelPackage()){// 添加工作表var worksheet = package.Workbook.Worksheets.Add("Sheet1");for (int i = 0; i < columnNames.Count; i++){// 添加列标题worksheet.Cells[1, i+1].Value = columnNames[i];}// 填充数据for (int i = 0; i < datas.Count; i++){for (int j = 0; j < columnNames.Count+1; j++){// 通过反射获取相应属性值PropertyInfo[] propertyInfos = typeof(T).GetProperties();string propertyName = propertyInfos[j].Name;if (!columnIgnores.Contains(propertyName)){// 获取属性值object value = propertyInfos[j].GetValue(datas[i]);worksheet.Cells[i + 2, j].Value = value; // 数据从第二行开始填充}}}// 设置列宽自适应worksheet.Cells.AutoFitColumns();// 保存 Excel 文件FileInfo fileInfo = new FileInfo(filePath+"\\"+fileName);package.SaveAs(fileInfo);}}public static void ExportExcel<T>(List<T> datas, Dictionary<string, string> Column2Property, List<string> columnIgnores, string filePath, string fileName){ExcelPackage.LicenseContext = LicenseContext.NonCommercial;using (ExcelPackage package = new ExcelPackage()){// 添加工作表var worksheet = package.Workbook.Worksheets.Add("Sheet1");// 写入列标题int colIndex = 1;foreach (var col in Column2Property){if (!columnIgnores.Contains(col.Key)){worksheet.Cells[1, colIndex].Value = col.Value; // 列标题colIndex++;}}// 填充数据int rowIndex = 2; // 数据从第二行开始填充foreach (var data in datas){int currentColIndex = 1;foreach (var col in Column2Property){if (!columnIgnores.Contains(col.Key)){// 使用反射获取属性值PropertyInfo propertyInfo = data.GetType().GetProperty(col.Key);if (propertyInfo != null){object value = propertyInfo.GetValue(data);worksheet.Cells[rowIndex, currentColIndex].Value = value;}currentColIndex++;}}rowIndex++;}// 设置列宽自适应worksheet.Cells.AutoFitColumns();// 保存 Excel 文件FileInfo fileInfo = new FileInfo(Path.Combine(filePath, fileName + ".xlsx"));package.SaveAs(fileInfo);}}/// <summary>/// txt文本导出/// </summary>/// <param name="datas">需要导出的数据集合</param>/// <param name="propertyName">实体类中需要导出属性</param>/// <param name="filePath">文件保存路径</param>public static void ExportTxt(List<T> datas, string propertyName, string filePath, string fileName){// 构建完整的文件路径string fullPath = Path.Combine(filePath, fileName);// 使用 StreamWriter 写入 TXT 文件using (StreamWriter writer = new StreamWriter(fullPath)){// 遍历数据集合foreach (var data in datas){// 通过反射获取指定属性的值PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName);if (propertyInfo != null){object value = propertyInfo.GetValue(data);// 将值写入文件,值之间以逗号分隔writer.WriteLine(value?.ToString());}else{// 如果指定的属性不存在,抛出异常throw new ArgumentException($"Property '{propertyName}' does not exist on type '{typeof(T).Name}'.");}}}}}
}
调用案例1
传入columnNames集合,工具类会遍历columnNames创建表头,然后遍历传入的泛型T的属性一个一个复制
如果columnNames和泛型T的属性的顺序从上到下一一对应则可以用
private void ExportExcel(){List<string> columnNames = new List<string>{#region 记录"生产订单号","请购单号","采购单号","料号","品名","规格描述","现存量","可用量","含税单价","含税金额","单位","采购数量_计量","收货数量_计量","已退货数_计价","实际入库数","入库单号","已暂收数量_计量","最后交货日期","品质异常报告日期","品质问题描述","处理结论","未交数量_计量","交货结案日期","请购日期","PMC交单日期","采购日期","采购周期","理论交期","要求交期","订单回传日期","采购回复交期","色板_模板_图纸提供情况","异常反馈","预付款比例","预付款支付日期","尾款比例","采购到货日期","财务交单日期","尾款支付日期","请购制单人","请购人","请购单备注","采购制单人","采购员","采购单备注","供应商名称","逾期天数_负数未到期","采购订单结案状态","采购单行号","修改日期_请购","修改日期_采购","PMC要求交货日期"#endregion};List<string> columnIgnores = new List<string> { "isSelected" };// 打开保存文件对话框Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog{Filter = "Excel Files (*.xlsx)|*.xlsx",FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx" // 默认文件名};if (saveFileDialog.ShowDialog() == true) // 用户点击“保存”{string filePath = saveFileDialog.FileName; // 用户选择的文件路径try{// 调用 Excel 导出功能ExcelUtil<ToolStr50>.ExportExcel(Ibo, columnNames, columnIgnores, Path.GetDirectoryName(filePath), Path.GetFileName(filePath));// 通知用户导出完成//MessageBox.Show("导出Excel成功", "成功", MessageBoxButton.OK, MessageBoxImage.Information);}catch (Exception ex){// 错误处理//MessageBox.Show($"导出Excel失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);}}}
效果

调用案例2
传入Column2Property--列名和属性对应关系,不会担心数据和属性顺序问题
private void ExportExcel(){Dictionary<string, string> Column2Property = new Dictionary<string, string>{{ "toolStr24", "请购日期" },{ "toolStr54", "标准周期" },{ "toolStr55", "采购标准周期" },{ "toolStr1", "生产订单号" },{ "toolStr4", "料号" },{ "toolStr5", "品名" },{ "toolStr6", "规格描述" },{ "toolStr11", "单位" },{ "toolStr46", "供应商名称" },{ "toolStr26", "采购建立日期" },{ "toolInt10", "采购周期" },{ "toolStr31", "采购回复交期" },{ "toolStr53", "采购说明" },{ "toolStr2", "来源单号" },{ "toolStr3", "采购订单号" },{ "toolStr49", "行号" },{ "toolInt2", "现存量" },{ "toolInt3", "采购数量(计量)" },{ "toolInt4", "收货数量(计量)" },{ "toolInt5", "已退货数(计量)" },{ "toolInt6", "实际入库数(计量)" },{ "toolDouble1", "含税单价" },{ "toolDouble2", "含税金额" },{ "toolStr16", "入库单号" },{ "toolStr44", "采购员" },{ "toolStr40", "请购人" },{ "toolStr43", "采购制单人" },//{ "toolStr40", "请购制单人" },{ "toolStr42", "请购单备注" },{ "toolStr48", "采购订单结案状态" },{ "toolInt7", "已暂收数量(计量)" },{ "toolStr18", "最后交货日期" },{ "toolInt8", "逾期天数(负数未到期)" },{ "toolStr19", "品质异常报告日期" },{ "toolStr20", "品质问题描述" },{ "toolStr21", "处理结论" },{ "toolInt9", "未交数量(计量)" },{ "toolStr23", "交货结案日期" },{ "toolStr25", "PMC交单日期" },{ "toolStr28", "采购理论交期" },{ "toolStr29", "要求交期" },{ "toolStr30", "订单回传日期" },{ "toolStr32", "色板_模板_图纸提供情况" },{ "toolStr33", "异常反馈" },{ "toolInt11", "预付款比例" },{ "toolStr35", "预付款支付日期" },{ "toolInt12", "尾款比例" },{ "toolStr39", "尾款支付日期" },{ "toolStr45", "备注" },{ "toolStr8", "可用量" },{ "toolStr37", "采购到货日期" },{ "toolStr38", "财务交单日期" },{ "toolStr50", "修改日期_请购" },{ "toolStr51", "修改日期_采购" },{ "toolStr52", "PMC要求交货日期" },//{ "toolStr54", "标准周期" },};List<string> columnIgnores = new List<string> { "isSelected" };// 打开保存文件对话框Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog{Filter = "Excel Files (*.xlsx)|*.xlsx",FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx" // 默认文件名};if (saveFileDialog.ShowDialog() == true) // 用户点击“保存”{string filePath = saveFileDialog.FileName; // 用户选择的文件路径try{// 调用 Excel 导出功能ExcelUtil<ToolStr50>.ExportExcel(Ibo, Column2Property, columnIgnores, Path.GetDirectoryName(filePath), Path.GetFileName(filePath));// 通知用户导出完成//MessageBox.Show("导出Excel成功", "成功", MessageBoxButton.OK, MessageBoxImage.Information);}catch (Exception ex){// 错误处理//MessageBox.Show($"导出Excel失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);}}}
效果

相关文章:
C#封装EPPlus库为Excel导出工具
1,添加NUGet包 2,封装工具类 using OfficeOpenXml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection;namespace GMWPF.utils {public class ExcelUtil<T>{/// <summary>///…...
【LeetCode】【算法】461. 汉明距离
LeetCode 461. 汉明距离 题目描述 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y,计算并返回它们之间的汉明距离。 思路 思路:将两个数转成二进制后求异或结果,就是它们之间的汉明距离。…...
Docker Compose部署Rabbitmq(延迟插件已下载)
整个工具的代码都在Gitee或者Github地址内 gitee:solomon-parent: 这个项目主要是总结了工作上遇到的问题以及学习一些框架用于整合例如:rabbitMq、reids、Mqtt、S3协议的文件服务器、mongodb github:GitHub - ZeroNing/solomon-parent: 这个项目主要是…...
生信技能62 - 常用机器学习算法的R语言实现
1. 加载R包和数据 # 安装R包, 是否update统一选择不更新n BiocManager::install("caret") BiocManager::install("randomForest") BiocManager::install("gbm") BiocManager::install("kernlab") BiocManager::install("glmnet…...
【3D Slicer】的小白入门使用指南二
3D Slicer中DICOM数据加载和三维可视化 任务 数据集下载和解压缩 加载和查看DICOM数据 1)将第一个数据集文件夹,整个往3Dslicer左侧拖动即可 得到 2)选中右侧patient 1就可显示出该患者的基本信息 (第二行蓝色是研究信息;第三行蓝色是序列信息)...
部署搭建AI相关项目时,不用魔法也能轻松自动下载所需大模型
背景 最近搭建了许多AI相关的自动化服务,有些时候因为国内服务器墙了 huggingface.co 访问,导致一些依赖文件和模型下载不下来,手动去下载又特别麻烦,今天教你一个小招,轻松解决这个问题 开搞 1:首先确定…...
zookeeper之节点基本操作
ZooKeeper是一个分布式协调服务,它的节点操作包括创建、查询、更新、删除等,以下是ZooKeeper节点的基本操作介绍: 1. 创建节点 持久节点(Persistent Node) 含义:持久节点是ZooKeeper中最基本的节点类型。创建后,除非显式删除,否则它将一直存在于ZooKeeper树中,即使创…...
技术最好 ≠ 最适合:数字化转型切忌盲目追求最先进的技术
企业引入新兴技术时面临的挑战 企业在引入新兴技术时会面临一定挑战,根据调查结果显示,企业在引入新兴技术时做出决策的三个最重要考量因素分别是: 价格与投资回报 新兴技术成熟度 新兴技术与业务的适配性 不要盲目追求最先进的技术 企业…...
数字IC后端教程之Innovus hold violation几大典型问题
今天小编给大家分享下数字IC后端实现Physical Implementation过程中经常遇到的几个hold violation问题。每个问题都是小编自己在公司实际项目中遇到的。 数字后端实现静态时序分析STA Timing Signoff之min period violation Q1: 在Innouvs postCTS时序优化的log中我们经常会看…...
rust并发
文章目录 Rust对多线程的支持std::thread::spawn创建线程线程与 move 闭包 使用消息传递在线程间传送数据std::sync::mpsc::channel()for received in rx接收两个producer 共享状态并发std::sync::Mutex在多个线程间共享Mutex,使用std::sync::Arc 参考 Rust对多线程…...
力扣 最小路径和
又是一道动态规划基础例题。 题目 这道题可以类似不同路径。先把左上角格子进行填充,然后用一个数组去更新每走到一个格的数字总和,首先处理边界问题,把最左边的列只能由上方的行与原来的格子数值的和,同理,最上方的行…...
Scala中的可变Map操作:简单易懂指南 #Scala Map #Scala
引言 在编程中,Map是一种常见的数据结构,用于存储键值对。Scala提供了不可变Map和可变Map两种类型,它们在处理数据时有不同的特性和用途。本文将通过一个简单的示例,带你了解Scala中可变Map的基本操作,包括添加元素、…...
【go从零单排】XML序列化和反序列化
🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 语言中,处理 XML 数据主要使用 encoding/xml 包。这个包提供了…...
在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5
在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5 1. 安装 Oracle Database 23ai2. 连接 Oracle Database 23c3. 重启启动后,手动启动数据库4. 重启启动后,手动启动 Listener5. 手动启动 Pluggable Database6. 自动启动 Pluggable Database7. 设置开…...
在 Ubuntu 上安装 `.deb` 软件包有几种方法
在 Ubuntu 上安装 .deb 软件包有几种方法,可以使用命令行工具,也可以通过图形界面进行安装。以下是几种常见的安装方法: 方法 1:使用 dpkg 命令安装 .deb 包 打开终端。 使用 dpkg 命令安装 .deb 包: sudo dpkg -i /…...
一文了解Android本地广播
在 Android 开发中,本地广播(Local Broadcast)是一种轻量级的通信机制,主要用于在同一应用进程内的不同组件之间传递消息,而无需通过系统的全局广播机制。这种方法既可以提高安全性(因为广播仅在应用内传播…...
Ingress nginx 公开TCP服务
文章目录 背景搞起拓展( PROXY Protocol )参考 背景 公司业务繁多, HTTP、GRPC、TCP多种协议服务并存,Kubernetes流量入口复杂,所以萌生了通过LoadBalancer Ingress-nginx 的方式完全的结果入口流量,当然在高并发的场景下可以对…...
谷歌浏览器支持的开发者工具详解
谷歌浏览器(Google Chrome)是全球最受欢迎的网页浏览器之一,它不仅提供了快速、安全的浏览体验,还为开发者提供了强大的开发者工具。本文将详细介绍如何使用谷歌浏览器的开发者工具,并解答一些常见问题。(本…...
【数据结构】汇编 、机器语言 高级语言 简析。
汇编语言、机器语言和高级语言 1. 机器语言(Machine Language) 定义:机器语言是计算机能够直接执行的、用二进制编码的指令集,属于最低级别的编程语言。它由 0 和 1 组成,每条指令由一串二进制数表示。机器语言与计算…...
【青牛科技】GC3901,强势替代 A3901/ALLEGRO应用于摇头机等产品中
在电子工程的浩瀚世界里,不断追求更优性能、更高效率和更低成本的芯片解决方案,是每一位电子工程师的不懈目标。今天,我们要为大家隆重介绍一款足以让你眼前一亮的芯片 —— 芯麦 GC3901,它将以强大的实力成为 A3901/ALLEGRO 的完…...
单一职责原则 登录功能重构笔记
核心定义单一职责原则:一个类只干一件事,只有一个修改的理由,避免功能杂糅、代码耦合。原有问题原始 Login 登录类,把界面展示、数据库连接、数据查询、登录校验、程序启动全部堆在一个类里,职责混乱,任何小…...
2026出纳岗位新人如何快速提升能力:从基础上手到能力跃升的最快路径
2026年,出纳岗位已经不再只是“收付款、跑银行、登记现金日记账”这么简单。随着企业财务数字化、业财一体化和AI工具普及,新人想快速成长,必须同时具备规范意识、系统操作能力、数据思维和风险意识。这也是为什么越来越多财务新人会关注像CD…...
Unity XLua调试失败原因与sourceMapPathOverrides终极配置
1. 这不是“配个插件就能跑”的事:为什么90%的UnityXLua调试配置会卡在“找不到源码”上EmmyLua VSCode 调试 XLua,这个组合在Unity Lua热更项目里几乎是事实标准。但你有没有遇到过这样的场景:断点明明打在Lua文件里,VSCode也显…...
2026 收藏版|程序员转行 AI 大模型应用开发,5 步零基础上岸学习路线
身为程序员,或是打算跨界进军AI应用开发赛道的朋友,真心建议大胆投递岗位,别被招聘简章里严苛的任职要求劝退。诸如精通大模型底层原理、具备多年AI从业经验这类条件,大多只是企业理想招聘标准。 身边不少同行都是秉持先入职深耕、…...
PwnKit漏洞深度解析:pkexec环境变量劫持与Linux提权原理
1. 这个漏洞不是“又一个提权”,而是Linux权限模型的照妖镜你可能已经看过不少关于CVE-2021-4034的通报,标题里常带着“高危”“远程可利用”“影响所有主流发行版”这类字眼。但说实话,我第一次在Debian 11上复现成功时,并没有立…...
【云计算学习之路】学习Centos7系统:服务搭建(VSFTP)
FTP简介及快速构建VSFTP服务器FTP简介及快速构建VSFTP服务器一、前言二、FTP服务核心简介2.1 FTP基本概念2.2 FTP两种工作模式1. 主动模式(Active Mode)2. 被动模式(Passive Mode)2.3 VSFTP服务核心优势三、实验环境预处理3.1 网络…...
五轴龙门机床厂家推荐,五轴龙门机床哪家好?
五轴龙门机床厂家推荐,五轴龙门机床哪家好?五轴龙门机床性能参数与场景适配分析。五轴龙门机床是高端装备制造的核心加工设备,广泛应用于航空航天、新能源、重工装备等领域。本文基于海天精工、纽威数控、环球工业机械、济南二机床四款主流国…...
HsMod深度解析:基于BepInEx的炉石传说全方位模改进阶指南
HsMod深度解析:基于BepInEx的炉石传说全方位模改进阶指南 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 你是否厌倦了炉石传说中繁琐的动画等待?是否渴望更高效的游…...
DMXAPI:国产多模态大模型API聚合平台,让开发者一键调用通义千问等主流模型
在国产大模型百花齐放的今天,如何高效、稳定地接入各类模型能力,成为开发者和企业面临的核心痛点。DMXAPI 应运而生,作为中国多模态大模型API聚合平台,致力于打造"国产模型一站式调用中心",让开发者无需对接…...
工厂MES数据自动采集怎样用AI完成?资深架构师的非侵入式集成落地指南
摘要: 我是架构师老王。在2026年工业数字化转型的深水区,工厂MES数据自动采集已不再是简单的“连线接口”,而是演变为一场关于“感知、决策与执行”的架构革命。面对老旧系统API缺失、烟囱式架构林立以及信创环境下严苛的安全合规要求&#x…...
