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

总体博文已迁移到博客园:http://www.cnblogs.com/csqb-511612371/p/4891492.html html


其实需求很明确,就是一大堆不同的excel,每张excel对应数据库的一张表,咱们须要提供用户上传excel,咱们解析数据入库的功能实现。node

那么,这就涉及到一个问题:咱们能够读出excel的表头,可是怎么知道每一个表头具体对应数据库里面的字段呢?数据库

博主通过一段时间的思考与构思,想到一法:如今的状况是咱们有excel表A,对应数据库表B,可是A与B具体属性字段的映射关系咱们不知。那咱们是否是能够有一个A到B的映射文件C呢?c#

我想,说到这,你们就很明了了...spa

第一步:为每张excel建立一个与数据库表对应的映射文件(xml配置文件),咱们称之为规则集,固然,咱们的需求是excel的列表头不变(顺序可换---缘由请继续往下看)设计

<?xml version="1.0" encoding="utf-8" ?>
<module>
  <add firstHeaderRow="5"                lastHeaderRow="7"    sheetCount="1"   Supplementary="0"   />
  <add headerText="年份"                 propertyName="Year"                           dataType="System.Int32"/>
  <add headerText="国内生产总值"         propertyName="GDPValue"                       dataType="System.double"/>
  <add headerText="第一产业"             propertyName="PrimaryIndustryAmount"          dataType="System.double"/>
  <add headerText="第二产业"             propertyName="SecondaryIndustry_TotalAmount"  dataType="System.double"/>
  <add headerText="工业"                 propertyName="SecondaryIndustry_Industry"     dataType="System.double"/>
  <add headerText="建筑业"               propertyName="SecondaryIndustry_Construction" dataType="System.double"/>
  <add headerText="第三产业"             propertyName="ThirdIndustryAmount"            dataType="System.double"/>
  <add headerText="人均国内生产总值(元)" propertyName="GDPPerPerson"                   dataType="System.double"/>
</module>

固然,这个xml文件因为是咱们本身定义的节点,因此每一个单词的意义就不详细解释了。excel

附:excel原表以下:code

其中【剔除行关键字】在后续详细代码中介绍,请继续关注微博。xml

表头含有层级结构,具体读取方法也在后续详细代码中介绍...今天之讲述设计思想与部分基础代码。htm

第二步:新建一个读取咱们本身定义的xml文件的类 RegularXMLReaderService.cs:

public class RegularXMLReaderService : IRegularXMLReaderService
    {
        public List<Regular> GetXMLInfo(string xmlpath)
        {
            //xmlpath为xml的路径名称
            var reader = new XmlTextReader(xmlpath);
            var doc = new XmlDocument();
            //从指定的XMLReader加载XML文档
            doc.Load(reader);

            var headerList = new List<Regular>();
            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                var header = new Regular();

                if (node.Attributes["firstHeaderRow"] != null)
                    header.HeaderRegular.Add("firstHeaderRow", int.Parse(node.Attributes["firstHeaderRow"].Value));
                if (node.Attributes["lastHeaderRow"] != null)
                    header.HeaderRegular.Add("lastHeaderRow", int.Parse(node.Attributes["lastHeaderRow"].Value));
                if (node.Attributes["sheetCount"] != null)
                    header.HeaderRegular.Add("sheetCount", int.Parse(node.Attributes["sheetCount"].Value));
                if (node.Attributes["ExcelType"] != null)
                    header.HeaderRegular.Add("ExcelType", int.Parse(node.Attributes["ExcelType"].Value));
                if (node.Attributes["Supplementary"] != null)
                    header.HeaderRegular.Add("Supplementary", int.Parse(node.Attributes["Supplementary"].Value));

                if (node.Attributes["headerText"] != null)
                    header.HeaderText = node.Attributes["headerText"].Value;
                if (node.Attributes["propertyName"] != null)
                    header.PropertyName = node.Attributes["propertyName"].Value;
                if (node.Attributes["dataType"] != null)
                    header.DataType = node.Attributes["dataType"].Value;

                headerList.Add(header);
            }
            return headerList;
        }
    }

这段代码相信你们都能看懂,不作详细解释。其中设计到一个规则集类Regular.cs

/// <summary>
    /// 模板规则类
    /// </summary>
    public class Regular
    {
        /// <summary>
        /// 表头文本   --对应excel表头名称
        /// </summary>
        public string HeaderText { set; get; }
        /// <summary>
        /// 属性名称    --对应数据库字段名称
        /// </summary>
        public string PropertyName { set; get; }
        /// <summary>
        /// 数据类型   ---对应数据库字段类型(用做判断excel数据是否合法用)
        /// </summary>
        public string DataType { set; get; }

        private Dictionary<string, int> _regular = new Dictionary<string, int>();

        /// <summary>
        /// 表头规则  --咱们所定义的具体规则,如咱们文中例子的起始行、结束行、表单数等等
        /// </summary>
        public Dictionary<string, int> HeaderRegular
        {
            get { return _regular; }
            set { _regular = value; }
        }
    }

这个类根据具体需求可能会有所不一样,具体随设计而改变。

第三步:建立一个解析excel数据的类(excel越多越复杂,实现就越困难),此处先假设已建好(详细代码请关注后续博客)

/// <summary>
    /// Excel表格检查与数据读取接口
    /// </summary>
    public interface IExcelImportService
    {
        /// <summary>
        /// 初始化Excel数据及配置文件
        /// </summary>
        /// <param name="filePath">Excel文件</param>
        /// <param name="xmlPath">配置文件</param>
        /// <param name="nullable">能够为空</param>
        void InitDataAndConfig(string filePath, string xmlPath, bool nullable);

        /// <summary>
        /// 综合验证Excel表格符合性
        /// </summary>
        /// <param name="customValidate">某单元项自定义检验接口</param>
        /// <returns></returns>
        UploadExcelFileResult ValidateExcel(ISpecification<KeyValuePair<string, string>> customValidate);

        /// <summary>
        /// 导入EXCEL文件
        /// </summary>
        /// <typeparam name="TableDTO">数据对象DTO</typeparam>
        /// <returns>EXCEL数据集合</returns>
        List<TableDTO> Import<TableDTO>();

        /// <summary>
        /// 导入EXCEL 文件------矩阵类模板
        /// 19.6-长江干线货物流量流向
        /// 20.5-西江航运干线货物流量流向
        /// </summary>
        /// <typeparam name="TableDTO"></typeparam>
        /// <returns></returns>
        List<TableDTO> ImportForMatrix<TableDTO>();
    }

此处是已建好的解析excel接口。(具体实现请参考后续博客)

博主的设计理念是:用户上传一个excel后咱们后台分三步走:

    一、初始化数据(excel文件流、对应配置文件--咱们的规则集xml文件、以及一些其余的配置参数)

    二、验证excel里面的数据合格(经过验证表头能够断定用户是否错误上传excel文件,验证里面数据是否违规(格式错误等)等等须要验证的方面)。验证成功后返回基础表头、附加信息等数据让用户确认并提交;失败后提示具体失败缘由,准肯定位到失败数据行列数。

    三、用户看到验证经过的返回结果,确认无误后点击提交,此时读取数据入库。



至此,咱们整个解析读取入库excel的流程就完成了,重在设计规则类这个设计思想,其中涉及到不少具体实现的代码,请参考后续博客专题。


总体博文已迁移到博客园:http://www.cnblogs.com/csqb-511612371/p/4891492.html

相关文章
相关标签/搜索