NPOI+反射+自定义特性实现上传excel转List及验证
Posted betterlife
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NPOI+反射+自定义特性实现上传excel转List及验证相关的知识,希望对你有一定的参考价值。
1.自定义特性
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class PropertyDescriptionAttribute : Attribute { private bool _allownullorempty = true; public PropertyDescriptionAttribute() { } /// <summary> /// 是否允许为null或空值 /// </summary> public bool AllowNullOrEmpty { get { return this._allownullorempty; } set { this._allownullorempty = value; } } }
2.定义类(假设是用户信息)
public class UploadUserModel { [PropertyDescription(AllowNullOrEmpty = false)] public string Name { get; set; } [PropertyDescription(AllowNullOrEmpty = false)] public string Phone { get; set; } }
自定义特定来标识这两个信息不能为空
3.实现
/// <summary> /// PROPERTY_NAME数组:值与excel列一一对应 /// </summary> private readonly string[] PROPERTY_NAME = { "Name", "Phone" }; private List<UploadUserModel> ExcelToList(HttpPostedFile excelFile) { IWorkbook workbook = null; ISheet sheet = null; int colCount = 0; List<UploadUserModel> users = new List<UploadUserModel>(); if (excelFile.FileName.IndexOf(".xlsx") > 0) { workbook = new XSSFWorkbook(excelFile.InputStream); } else if (excelFile.FileName.IndexOf(".xls") > 0) { workbook = new HSSFWorkbook(excelFile.InputStream); } if (workbook != null) { sheet = workbook.GetSheetAt(0); if (sheet != null && sheet.LastRowNum > 0) { colCount = sheet.GetRow(0).LastCellNum;//获取列数 //从第二行开始解析 for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++) { var curRow = sheet.GetRow(rowIndex);//获取当前行 UploadUserModel user = new UploadUserModel(); Type cType = user.GetType(); //解析列 for (int colIndex = 0; colIndex < colCount; colIndex++) { var curCell = curRow.GetCell(colIndex); if (curCell != null) { curCell.SetCellType(CellType.String);//把单元格设置成String类型,统一取值方式 } //定义PROPERTY_NAME避免if判断 PropertyInfo propertyInfo = cType.GetProperty(PROPERTY_NAME[colIndex]); //获取自定义特性 object[] customAttrs = propertyInfo.GetCustomAttributes(typeof(PropertyDescriptionAttribute), true); if (customAttrs.Length > 0) { PropertyDescriptionAttribute attr = customAttrs[0] as PropertyDescriptionAttribute; if (!attr.AllowNullOrEmpty)//属性值不能为空 { if (curCell == null) { throw new Exception("第" + (rowIndex + 1).ToString() + "行有未填项,请填写后重新上传。"); } else if (string.IsNullOrEmpty(curCell.StringCellValue)) { throw new Exception("第" + (rowIndex + 1).ToString() + "行有未填项,请填写后重新上传。"); } } object cellValue = null; if (curCell == null) { cellValue = ""; } else { cellValue = curCell.StringCellValue; } if (!propertyInfo.PropertyType.IsGenericType) { //非泛型 propertyInfo.SetValue(user, curCell == null ? null : Convert.ChangeType(cellValue, propertyInfo.PropertyType), null); } else { //泛型Nullable<> Type genericTypeDefinition = propertyInfo.PropertyType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>)) { propertyInfo.SetValue(user, curCell == null ? null : Convert.ChangeType(cellValue, Nullable.GetUnderlyingType(propertyInfo.PropertyType)), null); } } } } users.Add(user); } } } else { throw new Exception("Excel解析异常"); } foreach (var item in users) { if (!checkPhoneGS(item.Phone)) { throw new Exception("手机号格式不正确:"+ item.Phone); } } return users; }
不要看着麻烦,核心代码很简单。用反射和定义PROPERTY_NAME数组是为了代码重用。最后那段泛型、非泛型判断可以删除,估计一般用不到
以上是关于NPOI+反射+自定义特性实现上传excel转List及验证的主要内容,如果未能解决你的问题,请参考以下文章
npoi2.3+泛型+反射 根据配置统一解析excel数据到实体的基础方法