npoi2.3+泛型+反射 根据配置统一解析excel数据到实体的基础方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了npoi2.3+泛型+反射 根据配置统一解析excel数据到实体的基础方法相关的知识,希望对你有一定的参考价值。

解析方法:

        /// <summary>
        /// excel数据解析到实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="sheet">npoi读取到的excel工作表,需要解析的工作表</param>
        /// <param name="startRowIndex">从第几行开始解析 从1开始</param>
        /// <param name="relations">excel和实体的对应关系</param>
        /// <param name="msg">可能存在的错误提示</param>
        /// <returns>实体数据</returns>
        public List<T> Parse<T>(ISheet sheet, int startRowIndex, List<SheetToEntityAttrRelation> relations, out string msg)
        {
            msg = "";
            if (relations == null || relations.Count <= 0)
            {
                msg += "没有excel列名与实体属性的对应关系;";
                return null;
            }
            if (sheet == null)
            {
                msg += "sheet为空;";
                return null;
            }
            List<T> list = new List<T>();
            int rows = sheet.LastRowNum; //行数
            PropertyInfo[] props = typeof(T).GetProperties();
            if (props == null || props.Count() <= 0)
            {
                msg += "类型T的对象中没有属性;";
                return null;
            }
            //逐行读取sheet中的行
            for (int i = startRowIndex - 1; i <= rows; i++)
            {
                var row = sheet.GetRow(i);  //GetRow序号是从0开始的
                if (row == null) continue;
                T obj = (T)Activator.CreateInstance(typeof(T));
                list.Add(obj);
                foreach (SheetToEntityAttrRelation r in relations)
                {
                    //检查配置关系中的属性名在实体中是否存在
                    var currProps = props.Where(e => e.Name.Equals(r.AttrName));
                    if (currProps == null || currProps.Count() <= 0)
                    {
                        msg += "类型T的对象中没有属性:" + r.AttrName + ";";
                        continue;
                    }
                    PropertyInfo prop = currProps.ToList()[0];
                    string data = GetCellValue(row.GetCell(r.ColumnIndex - 1)); //GetCell序号是从为开始的
                    if (!string.IsNullOrEmpty(data))
                    {
                        switch (r.DataType)
                        {
                            case DbType.AnsiString: prop.SetValue(obj, data, null); break;
                            case DbType.Double: prop.SetValue(obj, Convert.ToDouble(data), null); break;
                            case DbType.Int32: prop.SetValue(obj, Convert.ToInt32(data), null); break;
                            case DbType.DateTime:
                                if (string.IsNullOrEmpty(r.TimeFormat)) r.TimeFormat = "yyyyMmdd";
                                DateTime dt;
                                if (DateTime.TryParseExact(data, r.TimeFormat, null, DateTimeStyles.None, out dt))
                                {
                                    prop.SetValue(obj, dt, null);
                                }
                                else
                                {
                                    msg += string.Format("第{0}行第{1}列不是有效的日期格式数据", i + 1, r.ColumnIndex);
                                    continue;
                                }
                                break;
                        }
                    }
                    else
                    {
                        msg += string.Format("第{0}行第{1}数据为空", i + 1, r.ColumnIndex);
                        continue;
                    }
                }
            }
            return list;
        }

        private string GetCellValue(ICell cell)
        {
            string value = "";
            if (cell != null)
            {
                if (cell.CellType.Equals(CellType.String))
                {
                    value = cell.StringCellValue;
                }
                if (cell.CellType.Equals(CellType.Numeric))
                {
                    value = cell.NumericCellValue.ToString();
                }
                if (cell.CellType.Equals(CellType.Boolean))
                {
                    value = cell.BooleanCellValue.ToString();
                }
            }
            return value;
        }

参数中定义的类型:

    /// <summary>
    /// excel工作表字段名与实体字段对应关系
    /// </summary>
    public class SheetToEntityAttrRelation
    {
        /// <summary>
        /// excel列序号,第一列从1开始
        /// </summary>
        public int ColumnIndex { get; set; }
        /// <summary>
        /// 实体属性名
        /// </summary>
        public string AttrName { get; set; }
        /// <summary>
        /// 数据类型:允许string,int32,double,datetime
        /// </summary>
        public DbType DataType { get; set; }

        /// <summary>
        /// 如果数据类型为日期时间,将字符串转为日期时需要指定日期格式:yyyyMMdd,yyyy-MM-dd,yyyyMMddHHmmss,yyyy-MM-dd HH:mm:ss
        /// </summary>
        public string TimeFormat { get; set; }
    }

 

以上是关于npoi2.3+泛型+反射 根据配置统一解析excel数据到实体的基础方法的主要内容,如果未能解决你的问题,请参考以下文章

[Java基础]反射练习之越过泛型检查,运行配置文件制定内容

Java中的“反射泛型容器”你了解多少?

反射和泛型的复习

在泛型方法中返回特定类型,具体取决于运行时没有反射或动态的枚举值

在 Swift 中使用泛型、协议和继承创建对象时的 EXC_BAD_ACCESS

Spring 组件Spring 是如何解析泛型 - ResolvalbeType