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

相關文章
相關標籤/搜索