博客
关于我
使用 EPPlus 封装的 excel 表格导入功能 (二) delegate 委托 --永远滴神
阅读量:395 次
发布时间:2019-03-05

本文共 10057 字,大约阅读时间需要 33 分钟。

使用 EPPlus 封装的 excel 表格导入功能 (二) delegate 委托 --永远滴神

前言

接上一篇

前一篇的是大概能用但是不一定好用的版本

后来我又重新封装扩展了一下

支持自定义更多东西(但是封装地是否有必要我就说不清了)

上个版本的问题

上个版本封装之后的使用代码:

public ICollection
ExcelImport(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;}

设计逻辑是 一个单元格 对应 实体中的一个字段

这个设计一开始是没什么问题的,将excel中的数据导入到 DTO集合 中,然后就可以进行下一步的操作

但在实际使用的时候发现,拿到 DTO集合 之后,总是需要再套个 foreach 做一些初始化操作

比如:

  • 通过身份证号码判断性别
  • 通过用户名查询账单信息
  • 给某个字段赋值
  • 对应导入的数据生成其他的数据
  • ......

基于以上的需要,重新修改后的调用代码如下:

public ICollection
ExcelImport(IFormFile file){ var config = new ExcelImportOption
() .Add("姓名", item => item.Name) .Add("年龄", item => item.Age, item => int.Parse(item)) .Default(item => item.Height, 233) .AddInit(item => { item.Name += "hhhhhhhh"; item.Gender = false; return item; }); ICollection
result = ExcelOperation.ExcelToEntity(file.OpenReadStream(), config); return result;}

代码/设计/想法

由于我想在解析 excel 的同时进行初始化操作,所以委托这东西必不可少

Func
Init { get; set; }

由于现阶段的需求比较简单,不需要什么复杂的参数,所以使用 Func<>Action<> 都可以

定义这个初始化 Init 之后,单纯的 ICollection<ExcelCellOption<T>> 已经是不够用了

所以重新定义了一个 配置

public class ExcelOption
{ public ICollection
> FieldOption { get; set; } = new List
>(); public ICollection
> DefaultOption { get; set; } = new List
>(); public Func
Init { get; set; }}

其中的 DefaultOption 没有也行

然后对 ExcelOption<T> 进行扩展

public static class ExcelOptionExt{    ......    public static ExcelOption
AddInit
(this ExcelOption
origin, Func
action = null) { if (origin.Init == null) origin.Init = action; return origin; } // 没有 DefaultOption 的情况下使用 FieldOption 也行 public static ExcelOption
Default
(this ExcelOption
origin, Expression
> prop, object defaultValue = null) { var member = prop.GetMember(); if (origin.DefaultOption == null) origin.DefaultOption = new List
>(); origin.DefaultOption.Add(new ExcelCellOption
{ PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = string.Empty, Action = item => defaultValue }); return origin; } ......}

配置 接口改变之后,ExcelOperationExcelToEntity 方法也要进行修改

public static ICollection
ExcelToEntity
(Stream excelStream, ExcelOption
options){ using ExcelPackage pack = new ExcelPackage(excelStream); // 合并 FieldOption 和 DefaultOption var propOptions = options.FieldOption.Concat(options.DefaultOption); 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 => propOptions.Any(opt => opt.ExcelField == item.Value?.ToString().Trim())) .ToDictionary(item => item.Value?.ToString().Trim(), item => item.End.Column); List
data = new List
(); // 将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 propOptions) { 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)); } else option.Prop.SetValue(obj, option.Action == null ? null : option.Action(string.Empty)); } // 实际上只是加了个 Init 操作 if (options.Init != null) obj = options.Init((T)obj); data.Add((T)obj); } return data;}

然后这个阶段就算是大功告成了!

再贴一次使用时的代码

public ICollection
ExcelImport(IFormFile file){ var config = new ExcelImportOption
() .Add("姓名", item => item.Name) .Add("年龄", item => item.Age, item => int.Parse(item)) .Default(item => item.Height, 233) .AddInit(item => { item.Name += "hhhhhhhh"; item.Gender = false; return item; }); ICollection
result = ExcelOperation.ExcelToEntity(file.OpenReadStream(), config); return result;}

完整代码

public class ExcelOperation{    public static ICollection
ExcelToEntity
(Stream excelStream, ExcelOption
options) { using ExcelPackage pack = new ExcelPackage(excelStream); // 合并 FieldOption 和 DefaultOption var propOptions = options.FieldOption.Concat(options.DefaultOption); 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 => propOptions.Any(opt => opt.ExcelField == item.Value?.ToString().Trim())) .ToDictionary(item => item.Value?.ToString().Trim(), item => item.End.Column); List
data = new List
(); // 将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 propOptions) { 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)); } else option.Prop.SetValue(obj, option.Action == null ? null : option.Action(string.Empty)); } if (options.Init != null) obj = options.Init((T)obj); data.Add((T)obj); } return data; } ///
/// 将表格数据转换为指定的数据实体 /// public static ICollection
ExcelToEntity
(Stream excelStream, ICollection
> options) { using ExcelPackage pack = new ExcelPackage(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().Trim())) .ToDictionary(item => item.Value?.ToString().Trim(), item => item.End.Column); List
data = new List
(); // 将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)); } else option.Prop.SetValue(obj, option.Action == null ? null : option.Action(string.Empty)); } data.Add((T)obj); } return data; }}public class ExcelOption
{ public ICollection
> FieldOption { get; set; } = new List
>(); public ICollection
> DefaultOption { get; set; } = new List
>(); public Func
Init { get; set; }}public class ExcelCellOption
{ ///
/// 对应excel中的header字段 /// public string ExcelField { get; set; } ///
/// 对应字段的属性(实际上包含PropName) /// public PropertyInfo Prop { get; set; } ///
/// 就是一个看起来比较方便的标识 /// public string PropName { get; set; } ///
/// 转换 表格 数据的方法 (现在是个鸡肋了) /// public Func
Action { 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 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; } public static ExcelOption
Add
(this ExcelOption
origin, string field, Expression
> prop, Func
action = null) { var member = prop.GetMember(); if (origin.FieldOption == null) origin.FieldOption = new List
>(); origin.FieldOption.Add(new ExcelCellOption
{ PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = field, Action = action }); return origin; } public static ExcelOption
Default
(this ExcelOption
origin, Expression
> prop, object defaultValue = null) { var member = prop.GetMember(); if (origin.DefaultOption == null) origin.DefaultOption = new List
>(); origin.DefaultOption.Add(new ExcelCellOption
{ PropName = member.Name, Prop = (PropertyInfo)member, ExcelField = string.Empty, Action = item => defaultValue }); return origin; } public static ExcelOption
AddInit
(this ExcelOption
origin, Func
action = null) { if (origin.Init == null) origin.Init = action; return origin; }}

未完待续

转载地址:http://lblzz.baihongyu.com/

你可能感兴趣的文章
【MySQL】(九)触发器
查看>>
Oracle 11G环境配置
查看>>
【Python】(十二)IO 文件处理
查看>>
【Oozie】(三)Oozie 使用实战教学,带你快速上手!
查看>>
师兄面试遇到这条 SQL 数据分析题,差点含泪而归!
查看>>
C语言的数值溢出问题(上)
查看>>
8051单片机(STC89C52)以定时器中断模式实现两倒计时器异步计时
查看>>
vue项目通过vue.config.js配置文件进行proxy反向代理跨域
查看>>
android:使用audiotrack 类播放wav文件
查看>>
聊聊我的五一小假期
查看>>
ACM/NCPC2016 C Card Hand Sorting(upc 3028)
查看>>
ubuntu学习笔记-常用文件、命令以及作用(hosts、vim、ssh)
查看>>
SLAM学习笔记-求解视觉SLAM问题
查看>>
程序员应该知道的97件事
查看>>
create-react-app路由的实现原理
查看>>
shell编程(六)语言编码规范之(变量)
查看>>
vimscript学习笔记(二)预备知识
查看>>
Android数据库
查看>>
HTML基础,块级元素/行内元素/行内块元素辨析【2分钟掌握】
查看>>
STM8 GPIO模式
查看>>