.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. .net 学习笔记2

      托管代码.非托管代码 语法糖: 写C#代码时,遵守简单的语法.编译时编译器将简单的写法编译成正式的复杂的写法. 如: 上面简写了方法,编译时编译器帮助生成完整的代码   Var 关键字指示 编译器 ...

  2. Redis入门——Java接口

    1. maven配置 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis&l ...

  3. mysql的sql执行计划详解

    实际项目开发中,由于我们不知道实际查询的时候数据库里发生了什么事情,数据库软件是怎样扫描表.怎样使用索引的,因此,我们能感知到的就只有 sql语句运行的时间,在数据规模不大时,查询是瞬间的,因此,在写 ...

  4. SQL优化(转)

    1. 负向条件查询不能使用索引 select * from order where status!=0 and stauts!=1 not in/not exists都不是好习惯 可以优化为in查询: ...

  5. docker能用来干嘛

    http://blog.csdn.net/wangtaoking1/article/details/44340445   什么是Docker Docker 是一个开源项目,诞生于 2013 年初,最初 ...

  6. [转载]FlipClock.js时钟,计数,3D翻转插件

    1.FlipClock.js能够自动定义计数,时钟的翻牌效果,调用简单,下面简单记录下用法 2.官网地址:http://www.flipclockjs.com/ 3.调用2个文件 <link h ...

  7. 模拟ATM的功能

    import java.io.FileReader; import java.io.FileWriter; import java.io.PrintWriter; import java.util.A ...

  8. asp.net热门框架

    http://developer.51cto.com/art/201501/464292.htm

  9. input 的radio checkbox 和 select 相关操作

    1  select 获取和设置值,以及onchange事件 1下拉框option没有checked事件 可通过select 的 onchange事件进行监控,以获取其值 <select name ...

  10. 将表单序列化为JSON对象

    将表单序列化为JSON对象的工具方法: $(function() { //工具方法,可以将指定的表单中的输入项目序列化为JSON数据 $.fn.serializeJson = function() { ...