.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. react修改app.js添加中文内容后中文部分乱码解决

    [问题]:配置完react后修改app.js内容时添加中文出现如下乱码的中文. [A解决]文档——文本编码——转换文本编码,在弹出窗口修改,确定,搞定 [B解决]首先在EditPlus内:工具——首选 ...

  2. 转:【专题六】UDP编程

    引用: 前一个专题简单介绍了TCP编程的一些知识,UDP与TCP地位相当的另一个传输层协议,它也是当下流行的很多主流网络应用(例如QQ.MSN和Skype等一些即时通信软件传输层都是应用UDP协议的) ...

  3. mysql命令(三)

    创建一个名字为Student库: create database Student; 用以下地命令来查看创建的数据库是否成功: show databases; 进入数据库: use Student; 用 ...

  4. Python框架----cookie和session

    一.cookie和session的介绍 cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. cookie ...

  5. 纯干货:深度学习实现之空间变换网络-part2

    https://www.jianshu.com/p/854d111670b6 纯干货:深度学习实现之空间变换网络-part1 在第一部分中,我们主要介绍了两个非常重要的概念:仿射变换和双线性插值,并了 ...

  6. django创建ORM模型、通过ORM模型操作单个表、ORM模型常用字段

    一.ORM简介 ORM ,全称Object Relational Mapping,中文叫做对象关系映射,通过ORM我们可以通过类的方式去操作数据库,而不用再写原生的SQL语句.通过把表映射成类,把行作 ...

  7. mongodb安装、远程访问设置、基本常用操作和命令以及GUI

    https://www.mongodb.com/download-center?jmp=nav下载对应OS的版本,tar -xzvf解压 对于最新版本比如3.4,windows 7下可能回报api-m ...

  8. MacOS Docker 安装

    使用 Homebrew 安装 macOS 我们可以使用 Homebrew 来安装 Docker. Homebrew 的 Cask 已经支持 Docker for Mac,因此可以很方便的使用 Home ...

  9. Windows死机的话,可能的一些猫病

    一.由硬件引起的原因 [散热不良] 显示器.电源和CPU在工作中发热量非常大,因此保持良好的通风状况非常重要,如果显示器过热将会导致色彩.图象失真甚至缩短显示器寿命.工作时间太长也会导致电源或显示器散 ...

  10. 让bat批处理后台运行,不显示cmd窗口(完全静化)

    背景:由于我有某云的服务器(win server), 上面挂有好几个程序, 为了更好的监控他们, 我使用了一个最笨的方法, 就是下面的方法. 实现:我要监控的程序有三个, 成为ABC吧, 下面先把三个 ...