本文共 10057 字,大约阅读时间需要 33 分钟。
接上一篇
前一篇的是大概能用但是不一定好用的版本
后来我又重新封装扩展了一下
支持自定义更多东西(但是封装地是否有必要我就说不清了)
上个版本封装之后的使用代码:
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;}
设计逻辑是 一个单元格 对应 实体中的一个字段
这个设计一开始是没什么问题的,将excel中的数据导入到 DTO集合 中,然后就可以进行下一步的操作
但在实际使用的时候发现,拿到 DTO集合 之后,总是需要再套个 foreach
做一些初始化操作
比如:
基于以上的需要,重新修改后的调用代码如下:
public ICollectionExcelImport(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 的同时进行初始化操作,所以委托这东西必不可少
FuncInit { 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 ExcelOptionAddInit (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; } ......}
配置 接口改变之后,ExcelOperation
的 ExcelToEntity
方法也要进行修改
public static ICollectionExcelToEntity (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 ICollectionExcelImport(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 ICollectionExcelToEntity (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 ICollectionExcelToEntity (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 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 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/