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; }
    }
时间: 2024-10-05 06:33:20

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

NPOI操作excel——利用反射机制,NPOI读取excel数据准确映射到数据库字段

> 其实需求很明确,就是一大堆不一样的excel,每张excel对应数据库的一张表,我们需要提供用户上传excel,我们解析数据入库的功能实现. 那么,这就涉及到一个问题:我们可以读出excel的表头,但是怎么知道每个表头具体对应数据库里面的字段呢? 博主经过一段时间的思考与构思,想到一法:现在的情况是我们有excel表A,对应数据库表B,但是A与B具体属性字段的映射关系我们不知.那我们是不是可以有一个A到B的映射文件C呢? 我想,说到这,大家就很明了了... 第一步:为每张excel创建一个与

解析Excel数据

解析Excel数据常用的方式就是使用POI和JXL工具了,这两种工具使用起来有些类似,这里记录一下使用方式提供个参考 POI使用 File file = new File(filePath); FileInputStream fis = new FileInputStream(file); workbook = WorkbookFactory.create(fis); //poi3.6使用一下方式创建workbook //workbook = new HSSFWorkbook(fis); //.

VSTO学习之路:使用Open XML SDK for Office解析Excel数据

Excel2007以后,工作簿是以XML文本保存数据的,用压缩工具打开工作簿文件,结构大致如下: 文件夹下基本全部是xml文本文件.微软提供了Open XML SDK 2.5 for Office,其中定义了和这些xml文件相关的类,帮助我们使用xml的形式解析工作簿里的数据和内容.跳转到微软官方资料          跳转到Open XML SDK 2.5 for Microsoft Office下载连接 在安装了 Open XML SDK 2.5 之后,在项目或应用程序中,添加对以下组件的引

利用 js-xlsx 实现 Excel 文件导入并解析Excel数据成json格式的数据并且获取其中某列数据

演示效果参考如下:XML转JSON 另一个搭配SQL实现:http://sheetjs.com/sexql/index.html 详细介绍: 1.首先需要导入js <script src="http://oss.sheetjs.com/js-xlsx/xlsx.full.min.js"></script> 2.导入文件框 这里importExcel(this)是方法,名字可以自己定义. <input type="file"onchang

DNS各种基本配置(正向解析区域、反向解析区域;主/从;子域;基本安全控制)

DNS服务器所提供的服务是完成将主机名和转换为IP地址的工作.为什么需要将主机名转换为IP地址的工作呢?这是因为,当网络上的一台客户机访问某一服务器上的资源时,用户在浏览器地址栏中输入的是人类便于识记的主机名和域名.而网络上的计算机之间实现连接却是通过每台计算机在网络中拥有的惟一的IP地址来完成的,这样就需要在用户容易记忆的地址和计算机能够识别的地址之间有一个解析,DNS服务器便充当了地址解析的重要角色. 域名严格意义上的称呼为FQDN(Full Qualified Domain Name).域

MHA大杀器——mysql主、从双击热备配置安装解析

MHA的主要作用: 在mysql的主从复制中,当master崩溃了,利用mha实现backup顶替崩溃的master自动切换为master继续工作,从而实现高可用. 下面介绍本次实验的环境: MHA分为manager管理节点和node节点,一般来讲最少是三台服务器,两台node节点,一台manager节点,但本次环境限制,只能使用两台,所以把manager也装在一台node节点上. 两台服务器,两个网口: IP: 10.2.16.253     10.0.0.1  node1 10.2.16.2

Yii2 配置request组件解析 json数据

在基础版本的config目录下 web.php 或者高级版config目录下的main.php中配置 'components' =>[ 'request' => [ 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ], ], ], 在使用Yii::$app->request->post()时 调用yii\web\Request 中的post方法   : public function post($na

Maven之——插件配置与解析

Maven之--插件配置与解析 插件配置就是为绑定插件指定其预定义的参数值.来进一步调整插件目标所执行的任务.可以通过命令行和POM中插件全局配置的形式来配置.不是所有的插件配置都可以通过命令行配置的. 1.    命令行插件配置 如maven-surefire-plugin插件提供一个maven.test.skip参数.当值为true时会跳过执行测试.命令行执行方式: mvninstall –Dmaven.test.skip=true mvn install 可以对比两者在控制台的输出就发现.

Storm 配置图文解析

Storm 配置图文解析 参考阅读:http://www.xiaofateng.com/?p=959 ============================== | sample-topology | | ------------------------ | Task 1 Task 2 Task 3 | | Worker Process 1 | | T1 T2 T3 | | +--------+ | | Spout => Bolt => Bolt | | +------+ | +----+