国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

通用的高度可擴展的Excel導(dǎo)入實現(xiàn)(附Demo)

2019-11-17 01:27:42
字體:
供稿:網(wǎng)友

通用的高度可擴展的Excel導(dǎo)入實現(xiàn)(附Demo)

Demo源碼

背景

  通過程序?qū)xcel導(dǎo)入到數(shù)據(jù)庫中是一項非常常見的功能。通常的做法是:先將excel轉(zhuǎn)成DataTable,然后將DataTable轉(zhuǎn)換成List<T>,最終通過List<T>導(dǎo)入進數(shù)據(jù)庫。

  同時,一般的ExcelUtil基類也會提供類似List<T> GetEntityListFromFile<T>(string fileName)的實現(xiàn),但是這些實現(xiàn)一般都是機械化地對應(yīng),缺少一些自定義的操作。

問題

  在我的開發(fā)過程中,就導(dǎo)入excel這一塊就碰到了以下的一些問題:

  1.   excel中的列名可能不止一個(客戶可能沒有下載模板或者模板的版本不對,導(dǎo)致同一列可能有多個列名,例如【ID】和【編號】可能都對應(yīng)實體類中的【ID】列)
  2.   excel中的列可能對應(yīng)著實體類中的多個列(例如實體類中有【ID】、【Name】兩個字段,而excel模板中只有【ID】,我們需要通過excel中的【ID】從數(shù)據(jù)庫中找到Name值去填充實體類的【Name】)
  3.   需要對excel中某些數(shù)據(jù)的有效性做驗證,包括但不限于“數(shù)據(jù)類型有效”,“數(shù)據(jù)在數(shù)據(jù)庫中的存在性”,“數(shù)據(jù)在數(shù)據(jù)庫中的狀態(tài)有效”等等
  4.   需要對excel中的某些列進行自定義的映射(例如實體類和excel中都有【Status】,我們需要將excel中的【Status】寫“1”和寫“激活”的都填充實體類的【Status】為“1”)

  以上這些問題,僅僅通過基類提供的方法是無法實現(xiàn)的,所以本篇文章提供一種高度自定義的Excel導(dǎo)入通過模塊的實現(xiàn),期以解決以上問題。

Demo程序結(jié)構(gòu)概覽

  

  

ps:要下班了,今日就先發(fā)這么多,

  大家可以先下Demo看一下,功能都實現(xiàn)了,有問題可以大家一起交流,

  如果大家想知道具體流程,我就再添加。

實現(xiàn)思路

  首先,需要明確的是我們的需求:

  1. 使用c#技術(shù),將excel導(dǎo)入到程序中,并以List<Entity>的形式進行存在
  2. 可以自定義excel的列名和Entity中屬性的對應(yīng)關(guān)系,支持excel中多個列名對應(yīng)Entity中同一個屬性,也支持Entity中的多個屬性對應(yīng)excel中的一個列名
  3. 可以自定義excel中列的值轉(zhuǎn)換函數(shù),假設(shè)excel中有“狀態(tài)”列對應(yīng)到Entity中的Status屬性,在excel中的“狀態(tài)”列中寫【激活】或者【1】,最終都對應(yīng)到Status的【true】
  4. 可以自定義excel中列的值有效性驗證函數(shù)

  接下來,就簡要講述一下以上功能的實現(xiàn):

  • 類【public class ImportUtil<Entity> where Entity : new()】實現(xiàn)了excel的導(dǎo)入功能,Entity為實體類類型
    /// <summary>    /// 高度可擴展的excel導(dǎo)入 By Dean 20140320    /// 應(yīng)用場景:1 需要支持實體類屬性和excel中列的一對多關(guān)系 如excel中的列名是JHB、聚好幣、PV時候,均認為映射到實體中的JHB字段    ///2 需要支持實體類屬性和excel中列的多對一關(guān)系 如excel中只包含“名稱”列,有同時填充實體類的Code & Name屬性時,可以將Code屬性也對應(yīng)到“名稱”列,然后寫一個轉(zhuǎn)換函數(shù),通過“名稱”從DB中取出Code再映射    /// 功    能:1 可以自動剔除全部為空的行    ///           2 能夠自定義地設(shè)置將excel中的列映射到實體類上的哪個字段,以及映射的方法    ///           3 能夠?qū)xcel中的數(shù)據(jù)的有效性進行自定義的檢查    /// </summary>    /// <typeparam name="Entity"></typeparam>    public class ImportUtil<Entity> where Entity : new()
  • ImportUtil類中有唯一的構(gòu)造函數(shù)【public ImportUtil(Dictionary<string, string> allColumns)】
  public ImportUtil(Dictionary<string, string> allColumns)   {        AllColumns = allColumns;   }
       //實體類列和excel列的對應(yīng)關(guān)系            Dictionary<string, string> allColumns = new Dictionary<string, string>            {                {"ID","編號"},                {"StudentID","學(xué)生編號|學(xué)生ID"},{"StudentName","學(xué)生編號|學(xué)生ID"},                {"Disc

  該構(gòu)造函數(shù)傳入?yún)?shù)allColumns,是一個Dictionary<string,string>類型的,該參數(shù)實現(xiàn)了需求2,字典的Key是實體類Entity中的【屬性名稱】,字典的Value是excel中的【列名稱】,使用|來支持excel的多列名。

  • ImportUtil類中有唯一的對外公開的方法【public List<Entity> GetEntityList】
        /// <summary>        /// 根據(jù)excel文件名獲取實體類列表 《唯一向外部公開的接口》        /// </summary>        /// <param name="fileName">excel文件名</param>        /// <param name="errorInfo">導(dǎo)入過程中的任何錯誤信息都會放到這里面</param>        /// <param name="converterFields">需要進行預(yù)定義類型轉(zhuǎn)換的列</param>        /// <param name="customConverts">需要進行自定義類型轉(zhuǎn)換(key是實體類對應(yīng)的列,value是包含excel中對應(yīng)列的值和操作后的返回值的Func)</param>        /// <param name="dataValidateChecks">在進行excel列映射到實體類之前,對excel列中的值進行的預(yù)檢查</param>        /// <returns>實體類列表</returns>        public List<Entity> GetEntityList(string fileName,                                          List<string> errorInfo,                                          Dictionary<KnownDataType, List<string>> converterFields = null,                                          Dictionary<string, Func<object, object>> customConverts = null,                                          Dictionary<string, Func<object, string>> dataValidateChecks = null)

  該方法有5個輸入?yún)?shù),其中fileName和errorInfo是必輸?shù)模椒ㄗ罱K返回的就是我們所需要的List<Entity>,方法的執(zhí)行過程就是先通過excel的地址將excel導(dǎo)入稱為DataTable,然后將DataTable轉(zhuǎn)換成List<T>,在轉(zhuǎn)換的過程中進行數(shù)據(jù)的有效性驗證和數(shù)據(jù)值的類型轉(zhuǎn)換。

下面簡單介紹一下這5個參數(shù):

  1. fileName,string,需要導(dǎo)入的excel的地址;
  2. errorInfo,List<string>,導(dǎo)入過程中所發(fā)生的錯誤信息;
  3. convertFields,Dictionary<KnownDataType,List<string>>,預(yù)定義的類型轉(zhuǎn)換;excel中的列都是object類型的,而Entity中的屬性卻是強類型的,對于Int,Decimal,Double,DateTime已經(jīng)定義好了相關(guān)的轉(zhuǎn)換函數(shù),僅需將Entity屬性名稱傳入,在進行DataTable轉(zhuǎn)List<Entity>時就能夠?qū)?yīng)Column的值進行預(yù)定義的類型轉(zhuǎn)換
               //預(yù)定義類型轉(zhuǎn)換            Dictionary<KnownDataType, List<string>> convertFields = new Dictionary<KnownDataType, List<string>>            {                {KnownDataType.Int, new List<string> {"ID", "StudentID", "DisciplineID"}},                {KnownDataType.Double, new List<string> {"Score"}}            };
  4. customConverts,Dictionary<string,Func<object,object>>,自定義的類型轉(zhuǎn)換;預(yù)定義的類型轉(zhuǎn)換通常只是將excel中的列轉(zhuǎn)成對應(yīng)的類型或者給個默認值,是通用的操作,但是我們常常需要對excel中的列進行自定義的轉(zhuǎn)換,例如:excel中有“編號”列,設(shè)置同時對應(yīng)到Entity的“ID”、“Name”屬性,而“ID”屬性可以直接使用預(yù)定義轉(zhuǎn)換完成,“Name”列則需要通過“編號”從數(shù)據(jù)庫中找到“Name”再賦值給“Name”。因此,這時候我們需要自定義的轉(zhuǎn)換。寫法如下:
                //自定義類型轉(zhuǎn)換            Dictionary<string, Func<object, object>> customConverts = new Dictionary<string, Func<object, object>>            {                {                    "StudentName", currColumn =>                    {                        int studentID;                        if (currColumn != null && int.TryParse(currColumn.ToString(), out studentID))                        {                            var r = DataPool.EntireStudents.Find(c => c.ID == studentID);                            if (r != null)                            {                                return r.Name;                            }                        }                        return string.Empty;                    }                },                {                    "MakeUpExamTime", currColumn =>                    {                        DateTime colDateTime;                        if (currColumn != null && DateTime.TryParse(currColumn.ToString(), out colDateTime))                        {                            return colDateTime;                        }                        return null;                    }                }            };
  5. dataValidateChecks,Dictionary<string,Func<object,string>>,excel列的數(shù)據(jù)有效性驗證,在Entity的每個屬性的賦值之前都會先驗證一下excel的數(shù)據(jù)是否有效,Key是要驗證的屬性的名字,Value是一個Func,輸入?yún)?shù)就是excel的列值,返回的是string,驗證通過時是string.Empty,驗證不通過返回的是錯誤信息。寫法如下:
                //excel列的數(shù)據(jù)有效性驗證 以下完成了對excel中編號列的值必須為整數(shù)且不為空的驗證的設(shè)定            Dictionary<string,Func<object,string>> dataValidateChecks = new Dictionary<string, Func<object, string>>            {                {                    "ID", currColumn =>                    {                        int idInt;                        if (currColumn!=null&&int.TryParse(currColumn.ToString(),out idInt))                        {                            return string.Empty;                        }                        return "ID不能為空且必須為整數(shù)";                    }                }            };
                //執(zhí)行excel導(dǎo)入            var res = importUtil.GetEntityList(excelPath, errors, convertFields, customConverts, dataValidateChecks);

總結(jié)

  以上就完成了一個excel的自定義導(dǎo)入的功能,謝謝。

Demo源碼


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙游县| 兴安盟| 南昌市| 黔西县| 甘肃省| 怀宁县| 星座| 青州市| 金寨县| 胶州市| 牙克石市| 富川| 灌南县| 阿拉善右旗| 招远市| 黔东| 郸城县| 海门市| 如东县| 醴陵市| 乌兰察布市| 财经| 天等县| 长春市| 大渡口区| 闵行区| 洞头县| 祁阳县| 富民县| 蒲城县| 洪雅县| 广德县| 弥勒县| 班戈县| 惠东县| 阿拉善右旗| 浮山县| 红原县| 榆林市| 杂多县| 千阳县|