
使用 EPPlus 封装的 excel 表格导入功能 Func--小试牛刀
发布日期:2021-05-08 23:20:18
浏览次数:19
分类:博客文章
本文共 7124 字,大约阅读时间需要 23 分钟。
使用 EPPlus 封装的 excel 表格导入功能
前言
最近做系统的时候有很多 excel导入 的功能,以前我前后端都做的时候是在前端解析,然后再做个批量插入的接口
我觉着这样挺好的,后端部分可以做的很简单(很偷懒的)
但是因为各种各样的原因,最终还是需要做个专门的 excel导入 接口
遇到的问题
由于之前从来没有在后端部分处理过表格,所以我选择看一下同事的代码是怎么写的
虽然我之前没写过相关的业务,但是直觉的认为这样写非常麻烦,那个 ExcelHelper
好像也没干什么事,我希望一套操作下来可以把 excel 转成能够直接传入 AddRange
进行批量新增的实体集合
所以我就决定自己封装。
结果展示(略)
public ICollectionExcelImport(IFormFile file){ var config = ExcelCellOption .GenExcelOption("姓名", item => item.Name) .Add("年龄", item => item.Age, item => int.Parse(item)) .Add("性别", item => item.Gender, item => item == "男") .Add("身高", item => item.Height, item => double.Parse(item)); ICollection result = ExcelOperation.ExcelToEntity(file.OpenReadStream(), config); return result;}
最终可以直接生成"初始化"数据的 result
代码/设计/想法
我希望使用的时候通过传入 表格字段
与 数据实体.属性
的关系集合
实现解析表格的同时生成对应的 实体对象
然后我对上述 关系 的定义如下
public class ExcelCellOption{ /// /// 对应excel中的header表头(title) /// public string ExcelField { get; set; } ////// 对应字段的属性(实际上包含PropName) /// public PropertyInfo Prop { get; set; } ////// 就是一个看起来比较方便的标识 /// public string PropName { get; set; } ////// 转换 表格 数据的方法(委托) /// public FuncAction { get; set; }}
之后给他加了个静态方法 GenExcelOption<E>
生成关系集合 ICollection<ExcelCellOption<T>>
public static ICollection> GenExcelOption (string field, Expression > prop, Func action = null){ var member = prop.GetMember(); return new List >{ new ExcelCellOption { PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = field, Action = action } };}
为了方便之后加新的配置项
给返回类型 ICollection<ExcelCellOption<T>>
搞个扩展方法 Add
public static class ExcelOptionExt{ public static ICollection> Add (this ICollection > origin, string field, Expression > prop, Func action = null) { var member = prop.GetMember(); origin.Add(new ExcelCellOption { PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = field, Action = action }); return origin; }}
使用的时候就可以根据excel表格生成对应的 关系集合 (配置)
var config = ExcelCellOption.GenExcelOption("姓名", item => item.Name).Add("年龄", item => item.Age, item => int.Parse(item)).Add("性别", item => item.Gender, item => item == "男").Add("身高", item => item.Height, item => double.Parse(item));
有了配置之后需要根据配置解析excel生成数据实体了
写了个方法如下
public class ExcelOperation{ ////// 将表格数据转换为指定的数据实体 /// public static ICollectionExcelToEntity (Stream excelStream, ICollection > options) { using ExcelPackage pack = new(excelStream); var sheet = pack.Workbook.Worksheets[1]; int rowCount = sheet.Dimension.Rows, colCount = sheet.Dimension.Columns; // 获取对应设置的 表头 以及其 column下标 var header = sheet.Cells[1, 1, 1, colCount ] .Where(item => options.Any(opt => opt.ExcelField == item.Value?.ToString().Trim())) .ToDictionary(item => item.Value?.ToString().Trim(), item => item.End.Column); List data = new(); // 将excel 的数据转换为 对应实体 for (int r = 2; r <= rowCount; r++) { // 将单行数据转换为 表头:数据 的键值对 var rowData = sheet.Cells[r, 1, r, colCount] .Where(item => header.Any(title => title.Value == item.End.Column)) .Select(item => new KeyValuePair (header.First(title => title.Value == item.End.Column).Key, item.Value?.ToString().Trim())) .ToDictionary(item => item.Key, item => item.Value); var obj = Activator.CreateInstance(typeof(T)); // 根据对应传入的设置 为obj赋值 foreach (var option in options) { if (!string.IsNullOrEmpty(option.ExcelField)) { var value = rowData.ContainsKey(option.ExcelField) ? rowData[option.ExcelField] : string.Empty; if (!string.IsNullOrEmpty(value)) option.Prop.SetValue(obj, option.Action == null ? value : option.Action(value)); } // 可以用来初始化与表格无关的字段 如 创建时间 Guid主键 之类的东西 else option.Prop.SetValue(obj, option.Action == null ? null : option.Action(string.Empty)); } data.Add((T)obj); } return data; }}
最终调用
ExcelOperation.ExcelToEntity(file.OpenReadStream(), config)
传入文件流和配置集合即可
完整代码
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Linq.Expressions;using System.Reflection;using AutoMapper.Internal;using OfficeOpenXml;namespace XXX.XXX.XXX.XXX{ public class ExcelOperation { ////// 将表格数据转换为指定的数据实体 /// public static ICollectionExcelToEntity (Stream excelStream, ICollection > options) { using ExcelPackage pack = new(excelStream); var sheet = pack.Workbook.Worksheets[1]; int rowCount = sheet.Dimension.Rows, colCount = sheet.Dimension.Columns; // 获取对应设置的 表头 以及其 column var header = sheet.Cells[1, 1, 1, sheet.Dimension.Columns] .Where(item => options.Any(opt => opt.ExcelField == item.Value.ToString())) .ToDictionary(item => item.Value.ToString(), item => item.End.Column); List data = new(); // 将excel 的数据转换为 对应实体F for (int r = 2; r <= rowCount; r++) { // 将单行数据转换为 表头:数据 的键值对 var rowData = sheet.Cells[r, 1, r, colCount] .Where(item => header.Any(title => title.Value == item.End.Column)) .Select(item => new KeyValuePair (header.First(title => title.Value == item.End.Column).Key, item.Value?.ToString())) .ToDictionary(item => item.Key, item => item.Value); var obj = Activator.CreateInstance(typeof(T)); // 根据对应传入的设置 为obj赋值 foreach (var option in options) { if (!string.IsNullOrEmpty(option.ExcelField)) { var value = rowData.ContainsKey(option.ExcelField) ? rowData[option.ExcelField] : string.Empty; if (!string.IsNullOrEmpty(value)) option.Prop.SetValue(obj, option.Action == null ? value : option.Action(value)); } // 可以用来初始化与表格无关的字段 如 创建时间 Guid主键 之类的东西 else option.Prop.SetValue(obj, option.Action == null ? null : option.Action(string.Empty)); } data.Add((T)obj); } return data; } } public class ExcelCellOption { /// /// 对应excel中的header字段 /// public string ExcelField { get; set; } ////// 对应字段的属性(实际上包含PropName) /// public PropertyInfo Prop { get; set; } ////// 就是一个看起来比较方便的标识 /// public string PropName { get; set; } ////// 转换 表格 数据的方法 /// public FuncAction { get; set; } public static ICollection > GenExcelOption (string field, Expression > prop, Func action = null) { var member = prop.GetMember(); return new List >{ new ExcelCellOption { PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = field, Action = action } }; } } public static class ExcelOptionAdd { public static ICollection > Add (this ICollection > origin, string field, Expression > prop, Func action = null) { var member = prop.GetMember(); origin.Add(new ExcelCellOption { PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = field, Action = action }); return origin; } }}
其实这已经是旧版本了
新的版本过几天大概会发
未完待续
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月07日 20时24分14秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
shell echo单行和多行文字定向写入到文件中
2021-05-09
cmp命令
2021-05-09
Linux 磁盘管理(df fu fdisk mkfs mount)
2021-05-09
jQuery的事件绑定与触发 - 学习笔记
2021-05-09
Linux上TCP的几个内核参数调优
2021-05-09
记一次讲故事机器人的开发-我有故事,让机器人来读
2021-05-09
seo 回忆录百度基本概念(一)
2021-05-09
netcore中使用session
2021-05-09
Android 开发学习进程0.25 自定义控件
2021-05-09
多媒体文件格式全解说(下)--图片
2021-05-09
淘宝WAP版小BUG分析
2021-05-09
asp.net打印网页后自动关闭网页【无需插件】
2021-05-09
【Maven】POM基本概念
2021-05-09
【Java思考】Java 中的实参与形参之间的传递到底是值传递还是引用传递呢?
2021-05-09
【设计模式】单例模式
2021-05-09
远程触发Jenkins的Pipeline任务的并发问题处理
2021-05-09
entity framework core在独立类库下执行迁移操作
2021-05-09
Asp.Net Core 2.1+的视图缓存(响应缓存)
2021-05-09
【wp】HWS计划2021硬件安全冬令营线上选拔赛
2021-05-09