1. 程式人生 > >NPOI+反射+自定義特性實現上傳excel轉List及驗證

NPOI+反射+自定義特性實現上傳excel轉List及驗證

type set custom pre script private property xssf don

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及驗證