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 的完…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
