.net core 项目

可以从excel读取任何类型(T)的数据,只要T中的field的[Display(Name = "1233")]中的name==excel column header's name

引用的nuget包:

1.EPPlus.Core

2. System.ComponentModel.Annotations

    //类定义
public class ExcelReadServiceAccordingDisplayAttr<T> : IExcelReadService<T> where T : new()
{
ILogBase _logger;
static Dictionary<string, PropertyInfo> _displayAttrDic;
public ExcelReadServiceAccordingDisplayAttr(ILogBase logBase)
{
_logger = logBase;
}
}

  

class ExcelReadServiceAccordingDisplayAttr<T>中方法:

        private List<T> GetData(string excelPath, string sheetName = "", int sheetIndex = 0)
{
try
{
FileInfo existingFile = new FileInfo(excelPath); using (ExcelPackage package = new ExcelPackage(existingFile))
{
ExcelWorksheet sheet = GetSheet(package, sheetName, sheetIndex);
if (sheet == null) return null;
//获取不需要读取的column
List<long> excluedeColumns = GetExcludeCloumns(sheet);
//根据excelheader来获取type T数据对象的列字典
Dictionary<int, PropertyInfo> columnIndexDic = GetColumnIndexDicFromExcelHeader(sheet, excluedeColumns);
//读取excel数据,填充List<T>
List<T> result = GetDatesFromContent(sheet, columnIndexDic, excluedeColumns);
return result;
}
}catch(Exception ex)
{
_logger.Error($"get data from excel exception :{ex.ToString()},excel:{excelPath},sheetIndex:{sheetIndex},entityType:{typeof(T).FullName}");
throw ex;
}
}
       private List<T> GetDateFromSheet(ExcelWorksheet sheet)
{
if (sheet == null) return null;
List<long> excluedeColumns = GetExcludeCloumns(sheet);
//根据excelheader来获取type T数据对象的列字典
Dictionary<int, PropertyInfo> columnIndexDic = GetColumnIndexDicFromExcelHeader(sheet, excluedeColumns);
//读取excel数据,填充List<T>
List<T> result = GetDatesFromContent(sheet, columnIndexDic);
return result;
} private List<T> GetData(byte[] excelContent, string sheetName = "", int sheetIndex = 0)
{
try
{
using (Stream stream = new MemoryStream(excelContent))
{
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet sheet = GetSheet(package, sheetName, sheetIndex);
return GetDateFromSheet(sheet);
}
}
}
catch (Exception ex)
{
_logger.Error($"get data from excel exception :{ex.ToString()},excelContent:{excelContent},sheetIndex:{sheetIndex},entityType:{typeof(T).FullName}");
throw ex;
}
} private ExcelCheckResult CheckDate(byte[] excelContent, string sheetName = "", int sheetIndex = 0)
{
try
{
using (Stream stream = new MemoryStream(excelContent))
{
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet sheet = GetSheet(package, sheetName, sheetIndex);
if (sheet == null) return null;
List<long> excluedeColumns = GetExcludeCloumns(sheet);
//根据excelheader来获取type T数据对象的列字典
Dictionary<int, PropertyInfo> columnIndexDic = GetColumnIndexDicFromExcelHeader(sheet, excluedeColumns);
bool formatResult=FormatSheet(ref sheet, columnIndexDic);
package.Save();
if (!formatResult)
{
return new ExcelCheckResult() { CheckResult = false, CheckMsg = "format error!" };
}
return CheckExcel(ref sheet, columnIndexDic);
}
}
}
catch (Exception ex)
{
_logger.Error($"get data from excel exception :{ex.ToString()},excelContent:{excelContent},sheetIndex:{sheetIndex},entityType:{typeof(T).FullName}");
throw ex;
}
} /// <summary>
/// 根据 DisplayAttribute 的 Description 来格式化sheet
/// </summary>
/// <param name="sheet"></param>
/// <param name="columnIndexDic"></param>
private bool FormatSheet( ref ExcelWorksheet sheet, Dictionary<int, PropertyInfo> columnIndexDic)
{
try
{
var typeOfObject = typeof(T);
var columnIndexDicForDisplayAttr = new Dictionary<int, DisplayAttribute>();
foreach (var columnInfo in columnIndexDic)
{
int columnKey = columnInfo.Key;
PropertyInfo columnProperty = columnInfo.Value;
var attr = columnProperty.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
if (attr != null && !string.IsNullOrEmpty(attr.Description))
{
var originalFormat = sheet.Column(columnKey).Style.Numberformat.Format;
sheet.Column(columnKey).Style.Numberformat.Format = attr.Description;
_logger.Warn($"change cloumn{columnKey} formate({ originalFormat}=>{attr.Description}):(class:{typeOfObject.FullName},property:{columnProperty.Name})");
}
}
return true;
}
catch (Exception ex)
{
_logger.Error($"excel Format error. columnIndexDic:{JsonConvert.SerializeObject(columnIndexDic.Keys)}", ex);
return false;
}
} private ExcelCheckResult CheckExcel(ref ExcelWorksheet sheet, Dictionary<int, PropertyInfo> columnIndexDic)
{
var excelCheckResult = new ExcelCheckResult() {
CheckResult=true,
CheckMsg="Succeed!"
};
var columnPropertyDic = columnIndexDic.Values.ToLookup(p=>p.Name).ToDictionary(kp => kp.Key, kp => kp.FirstOrDefault()); Dictionary<string, PropertyInfo> requiredPropertyDic= GetRequireDicFromType();
StringBuilder msg = new StringBuilder();
foreach (var requiredProperty in requiredPropertyDic)
{
var properName = requiredProperty.Key;
if (!columnPropertyDic.ContainsKey(properName))
{
msg.AppendLine($"{properName} is required!");
_logger.Warn($"property:({properName}) is required ! columnIndexDic:{JsonConvert.SerializeObject(columnIndexDic.Keys)}");
}
}
if (!string.IsNullOrEmpty(msg.ToString()))
{
excelCheckResult.CheckResult = false;
excelCheckResult.CheckMsg = msg.ToString();
}
return excelCheckResult;
} private Dictionary<string, PropertyInfo> GetRequireDicFromType()
{
Type typeOfObject = typeof(T);
var pds = typeOfObject.GetProperties();
if (pds == null) return null;
var propertyDic = pds.ToLookup(p => {
var attr = p.GetCustomAttribute(typeof(RequiredAttribute)) as RequiredAttribute;
if (attr == null) return "";
return p.Name;
}).ToDictionary(kp => kp.Key, kp => kp.FirstOrDefault());
if (propertyDic == null || propertyDic.Count() == 0)
{
_logger.Warn($"no RequireDic can get from class Type:{typeOfObject.FullName} ");
}
else
{
propertyDic.Remove("");
}
return propertyDic;
}

  

        private List<long> GetExcludeCloumns(ExcelWorksheet sheet)
{
List<long> excludeCloumns = new List<long>();
if (sheet.PivotTables == null) return excludeCloumns;
//排除sheet中透视表的列
foreach (var povotTable in sheet.PivotTables)
{
var startCloumn = povotTable.Address.Start.Column;
var endColumn= povotTable.Address.End.Column;
while (startCloumn <= endColumn)
{
excludeCloumns.Add(startCloumn);
startCloumn++;
}
}
return excludeCloumns;
}
        private ExcelWorksheet GetSheet(ExcelPackage package, string sheetName,int sheetIndex)
{
if (package == null || package.Workbook == null || package.Workbook.Worksheets == null || package.Workbook.Worksheets.Count == 0) return null; ExcelWorksheets excelWorksheets = package.Workbook.Worksheets;
if (!string.IsNullOrWhiteSpace(sheetName))
{
var targetSheet = excelWorksheets.Where(s => s.Name.ToLower().Trim() == sheetName.ToLower());
if (targetSheet == null || targetSheet.Count() == 0) return null;
return targetSheet.FirstOrDefault();
}
else if (sheetIndex > 0 && sheetIndex + 1 <= excelWorksheets.Count())
{
return excelWorksheets[sheetIndex + 1];
}
else
{
return excelWorksheets.FirstOrDefault();
}
}

  

        private Dictionary<int, PropertyInfo> GetColumnIndexDicFromExcelHeader(ExcelWorksheet sheet, List<long> excluedeColumns)
{
if (_displayAttrDic == null)
{
//获取 Dictionary<excel column Header text,DisplayAttribute>
_displayAttrDic = GetDisplayDicFromType(typeof(T));
}
Dictionary<int, PropertyInfo> displayOrderDic = new Dictionary<int, PropertyInfo>();
if (sheet == null) return displayOrderDic;
if(_displayAttrDic == null|| _displayAttrDic.Count == 0)
{
_logger.Warn($"no _displayAttrDic can get .");
return displayOrderDic;
}
//获取 Dictionary<column index,PropertyInfo of class T>
var query1 = (from cell in sheet.Cells[1, 1, 1, sheet.Dimension.Columns] where !excluedeColumns.Contains(cell.Start.Column) select cell);
foreach (var cell in query1)
{
var columnName = cell.Value.ToString().ToLower().Trim();
if (_displayAttrDic.ContainsKey(columnName))
{
var propertyInfo = _displayAttrDic[columnName];
displayOrderDic.Add(cell.Start.Column, propertyInfo);
}
}
if (displayOrderDic == null || displayOrderDic.Count() == 0)
{
_logger.Warn($"no ColumnIndexDic can get from ExcelHeader. sheet:{sheet.Name},_displayAttrDic got no data");
}
return displayOrderDic;
} private Dictionary<string,PropertyInfo> GetDisplayDicFromType(Type typeOfObject)
{
var pds = typeOfObject.GetProperties();
if (pds == null) return null;
//DisplayAttribute 中的Name==excel column Header
var propertyDic = pds.ToLookup(p=> {
var attr = p.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
if (attr == null) return "";
return attr.Name.ToLower().Trim();
}).ToDictionary(kp => kp.Key, kp=> kp.FirstOrDefault());
if(propertyDic==null|| propertyDic.Count() == 0)
{
_logger.Warn($"no DisplayDic can get from class Type:{typeOfObject.FullName} ");
}
return propertyDic;
}

  

         private List<T> GetDatesFromContent(ExcelWorksheet sheet, Dictionary<int, PropertyInfo> columnIndexDic, List<long> excluedeColumns)
{
List<T> result = new List<T>();
//fill list form excel
Dictionary<string, Dictionary<string, object>> enumDic = new Dictionary<string, Dictionary<string, object>>();
var query2 = (from cell in sheet.Cells[2, 1, sheet.Dimension.Rows, sheet.Dimension.Columns] where !excluedeColumns.Contains(cell.Start.Column) select cell);
T temp = default(T);
foreach (var cell in query2)
{
if (cell.Start.Column == 1)
{
if (temp != null) result.Add(temp);
temp = (T)Activator.CreateInstance(typeof(T));
}
if (cell.Value == null || string.IsNullOrWhiteSpace(cell.Value.ToString())) continue;
SetValueAccordingEachCell(cell, temp, columnIndexDic, ref enumDic);
}
if (temp != null) result.Add(temp);
return result;
} //according cell value to set T's property value
private void SetValueAccordingEachCell(ExcelRangeBase cell, T temp, Dictionary<int, PropertyInfo> columnIndexDic, ref Dictionary<string, Dictionary<string, object>> enumDic)
{
try
{
var columnIndex = cell.Start.Column;
if (columnIndexDic == null || columnIndexDic.Count() == 0)
{
_logger.Warn($"no column Index can get from cell(address:{cell.Start.Address} ,value:{cell.Value})");
return;
}
if (!columnIndexDic.ContainsKey(columnIndex))
{
_logger.Warn($"no column Index can get from cell(address:{cell.Start.Address} ,value:{cell.Value}),columnIndexDic:{JsonConvert.SerializeObject(columnIndexDic.Keys)}");
return;
}
var propertyInfo = columnIndexDic[columnIndex];
Type propertyType = propertyInfo.PropertyType;
if (propertyType.IsEnum)
{
Dictionary<string, object> enumDicTemp;
if (enumDic.ContainsKey(propertyType.FullName))
{
enumDicTemp = enumDic[propertyType.FullName];
}
else
{
enumDicTemp = GetEnumDicFromType(propertyType);
enumDic.Add(propertyType.FullName, enumDicTemp);
} object enumValue = null;
if (enumDicTemp != null)
{
if (enumDicTemp.ContainsKey(cell.Value.ToString()))
{
enumValue = enumDicTemp[cell.Value.ToString()];
}
else
{
_logger.Warn($"no enum value can get from enum dictionary:{JsonConvert.SerializeObject(enumDicTemp.Keys)} , enum Type:{propertyType.FullName},cell (address:{cell.Start.Address},value:{cell.Value.ToString()})");
}
}
else
{
_logger.Warn($"no enum dictionary can get from enum Type:{propertyType.FullName} ");
} if (enumValue != null)
{
propertyInfo.SetValue(temp, enumValue);
}
else
{
_logger.Warn($"no enum value can get for cell:{cell.Value} ");
}
return;
}
if (propertyType == typeof(decimal))
{
string cellV = cell.Value.ToString();
decimal multiply = 1;
if (cellV.Contains("%"))
{
multiply = 100;
cellV = cellV.Substring(0, cellV.IndexOf("%") + 1);
}
decimal tempV;
bool convertR = decimal.TryParse(cellV, out tempV);
if (convertR)
{
propertyInfo.SetValue(temp, tempV * multiply);
}
else
{
_logger.Warn($"no decimal value can get for cell:(address:{cell.Address},value:{cell.Value})");
}
return;
}
if (propertyType == typeof(int))
{
propertyInfo.SetValue(temp, Convert.ToInt32(cell.Value));
return;
}
if (propertyType == typeof(long))
{
propertyInfo.SetValue(temp, Convert.ToInt64(cell.Value));
return;
}
if (propertyType == typeof(DateTime))
{
propertyInfo.SetValue(temp, Convert.ToDateTime(cell.Value));
return;
}
if (propertyType == typeof(string))
{
propertyInfo.SetValue(temp, cell.Value.ToString());
return;
}
propertyInfo.SetValue(temp, cell.Value.ToString());
return;
}
catch(Exception ex)
{
_logger.Error($"no property value can set from cell:(address:{cell.Address},value:{cell.Value})");
throw ex;
}
} // get Dictionary<enumn's display name==excel cell value,emumn value>
private Dictionary<string, object> GetEnumDicFromType(Type propertyType)
{
var result = new Dictionary<string, object>();
if (propertyType.IsEnum)
{
var enumValues = propertyType.GetEnumValues();
foreach (var value in enumValues)
{
MemberInfo memberInfo =
propertyType.GetMember(value.ToString()).First();
var descriptionAttribute =
memberInfo.GetCustomAttribute<DisplayAttribute>();
if (descriptionAttribute != null)
{
result.Add(descriptionAttribute.Name, value);
}
else
{
var enumString = Enum.GetName(propertyType, value);
result.Add(enumString, value);
}
}
if (result == null || result.Count() == 0)
{
_logger.Warn($"no EnumDic can get from enum Type:{propertyType.FullName} ");
}
}
return result;
}

  

相关辅助类:

enum class

    public enum AdvertiseType:Int32
{
/// <summary>
/// Search
/// </summary>
[Display(Name = "Search")]
Search = 1, /// <summary>
/// Display
/// </summary>
[Display(Name = "Display")]
Display = 2,
}

T class:

    public class FinancialBillEntity
{
[Display(Name = "类型")]
public BussinessType AdvertiseType{ get; set; } [Display(Name = "平台2343")]
public string AdvertisePlantform { get; set; } [Display(Name = "签约12312")]
public string PlantformSignEntity { get; set; }
}

  

应用:

 //register interface
services.RegisterServiceR<ExcelReadServiceAccordingDisplayAttr<FinancialBillEntity>,IExcelReadService<FinancialBillEntity>>(lifeStyle); //get interface instance
var excelWriteService= services.GetInstance<IExcelWriteService<FinancialBillEntity>>(); //execute interface method
bool result=_excelWriteService.WriteData(financeBills,cmdOptions.OutputFinanceBillExcelPath,cmdOptions.OutputFinanceBillSheetName);

  

  

EPPlus实战篇——Excel读取的更多相关文章

  1. EPPlus实战篇——Excel写入

    .net core 项目 可以向excel写入任何类型(T)的数据,只要T中的field的[Display(Name = "1233", Description = "# ...

  2. python基础 实战作业 ---Excel基本读写与数据处理

    代码地址如下:http://www.demodashi.com/demo/11650.html 看完本篇需要: 10min 作业练习需要: 0.5h~3h(依练习者对python熟悉程度而定) 看完本 ...

  3. 二、Redis基本操作——String(实战篇)

    小喵万万没想到,上一篇博客,居然已经被阅读600次了!!!让小喵感觉压力颇大.万一有写错的地方,岂不是会误导很多筒子们.所以,恳请大家,如果看到小喵的博客有什么不对的地方,请尽快指正!谢谢! 小喵的唠 ...

  4. javamail模拟邮箱功能发送电子邮件-基础实战篇(javamail API电子邮件实例)

    引言: JavaMail 是一种可选的.能用于读取.编写和发送电子消息的包 JavaMail jar包下载地址:http://java.sun.com/products/javamail/downlo ...

  5. Systemd 入门教程:实战篇

    Systemd 入门教程:实战篇 上一篇文章,介绍了 Systemd 的主要命令,这篇文章主要介绍如何使用 Systemd 来管理我们的服务,以及各项的含义: 一.开机启动 对于那些支持 System ...

  6. ArcGIS制图表达Representation实战篇4-自由式制图表达

    ArcGIS制图表达Representation实战篇4-自由式制图表达 by 李远祥 上一章节关于制图表达的控制点中已经介绍过制图表达的编辑功能,利用制图表达的编辑功能,可以实现一些规则以外的效果. ...

  7. 持续集成之 Spring Boot 实战篇

    本文作者: CODING 用户 - 何健 这次实战篇,我们借助「CODING 持续集成」,实现一个简单的 Spring Boot 项目从编码到最后部署的完整过程.本教程还有 B 站视频版,帮助读者更好 ...

  8. 洗礼灵魂,修炼python(82)--全栈项目实战篇(10)—— 信用卡+商城项目(模拟京东淘宝)

    本次项目相当于对python基础做总结,常用语法,数组类型,函数,文本操作等等 本项目在博客园里其他开发者也做过,我是稍作修改来的,大体没变的 项目需求: 信用卡+商城: A.信用卡(类似白条/花呗) ...

  9. javamail模拟邮箱功能--邮件回复-中级实战篇【邮件回复方法】(javamail API电子邮件实例)

    引言: JavaMai下载地址l jar包:http://java.sun.com/products/javamail/downloads/index.html 此篇是紧随上篇文章而封装出来的,阅读本 ...

随机推荐

  1. Groovy常用编程知识点简明教程

    概述 Groovy 是一门基于JVM的动态类型语言,可以与 Java 平台几乎无缝融合(与Java代码一样编译成字节码). 使用 Groovy ,可以增强 Java 应用的灵活性和可扩展性,提升开发效 ...

  2. Go语言专题

    基础语法 Go语言配置开发环境 Go语言语法基础 Go语言面向对象 Go语言并发编程 Go语言搭建开发环境 语言库 Go语言fmt包 Go语言字节处理 Go语言字符串处理 Go语言JSON处理 Go语 ...

  3. XmlDocument操作

    一.基本操作:XmlDocument 写 class Program { static void Main(string[] args) { // 使用DOM操作,常用的类:XmlDocument.X ...

  4. RESTful API 设计指南,RESTful API 设计最佳实践

    RESTful API 设计指南,RESTful API 设计最佳实践 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). ...

  5. AtCoder Beginner Contest 084(AB)

    A - New Year 题目链接:https://abc084.contest.atcoder.jp/tasks/abc084_a Time limit : 2sec / Memory limit  ...

  6. [转载]Javascript:history.go()和history.back()的用法和区别

    Javascript:history.go()和history.back()的用法和区别 简单的说就是:go(-1): 返回上一页,原页面表单中的内容会丢失:back(): 返回上一页,原页表表单中的 ...

  7. 记账本微信小程序开发三

    一.制作登陆界面: 更改全局配置,改颜色,名称: 界面 格式 登录界面 二.页面的跳转 按钮的设置 注册事件 结果

  8. 大神教你Nginx常用基础配置方案

    Nginx的fastcgi模块参数设置 Nginx 有两个配置文件fastcgi_params.fastcgi.conf,两者唯一的区别是,fastcgi.conf 多一个参数 SCRIPT_FILE ...

  9. ACM总结——2017湖南省省赛总结

    2017省赛已经结束了2天了,今天终于有时间,也有勇气来写下这一篇总结.的确,这是我第一次正式的ACM线下赛,我本以为再不济,也可以拿个三等奖,没想到,实力打铁.确实对我打击比较大,以前的确是知道自己 ...

  10. yocto doc

    Yocto Project Overview and Concepts Manual https://www.yoctoproject.org/docs/2.6.1/overview-manual/o ...