哈哈~~~很高興還活着。總算加班加點的把最后一類EXCEL模板的解析做完了...
前面幾篇文章介紹了博主最近項目中對於復雜excel表頭的解析,寫得不好,感謝園友們的支持~~~
今天再簡單講訴一下另一種“變異”EXCEL表頭模板——矩陣表頭模板的解析(博主感覺這種模板雖說怪異,但是偶爾也能遇到,的確是有一定的實用性),我們用一個流量流向的excel作為例子來講解:
先來解釋一下這個表頭:
1、“上表頭”看似復雜,按我們前幾篇文章說到的XML配置規則集的方法,輕易就能解析
2、這個表頭“上表頭”、“左表頭”內容不定,行列數不定
我相信這種表頭還是有一定價值的,值得做一個了解。
由於“上表頭”列不定,我們就不能按常規的思想,以列為數據庫字段來建表存儲。在建實體類時,博主偶然聯想到了大一高數(也不枉我考了90分)學到的矩陣,總感覺很神似,於是乎就以“矩陣類EXCEL模板”命名之。
然后取變化的“上表頭”、“左表頭”為屬性字段,最終新建實體類如下:
1 /// <summary> 2 /// XX年XX月西江航運干線貨物流量流向 3 /// PS_XJ_VolumeAndDirection 4 /// </summary> 5 public class CargoFlowVolumeAndDirectionInXjItem : DataFoundationItem 6 { 7 /// <summary> 8 /// 該表項在表格中的索引位置 9 /// </summary> 10 public int Index { get; set; } 11 12 /// <summary> 13 /// 貨物重量(或同期比) 14 /// CargoWeight 15 /// </summary> 16 public double CargoWeight { get; set; } 17 18 /// <summary> 19 /// 出發航段、支流 20 /// LeavingPort 21 /// </summary> 22 public string LeavingSegment { get; set; } 23 24 /// <summary> 25 /// 到達航段、支流 26 /// ArrivingPort 27 /// </summary> 28 public string ArrivingSegment { get; set; } 29 }
當然,這么存也不是3/5分鍾想出來的,只是偶發奇想。
很明顯,這次我們需要重構的依然只是表頭解析方法GetExcelHeaders()和解析Excel數據的方法GetExcelDatas()。
我們先來看表頭,以前我們是把列全部配置到XML文件作為規則集,我們這次做得再像矩陣一點,在XML規則集中配置“X軸”、“Y軸”分別用來代表“上表頭”、“左表頭”,再外加一個字段配置具體的值就OK:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <module> 3 <add firstHeaderRow="5" lastHeaderRow="7" /> 4 <add headerText="Y軸" propertyName="LeavingSegment" dataType="System.String"/> 5 <add headerText="X軸" propertyName="ArrivingSegment" dataType="System.String"/> 6 <add headerText="值" propertyName="CargoWeight" dataType="System.double"/> 7 </module>
哈哈,有木有很簡潔的感覺。
具體解析EXCEL表頭的方法在第三篇文章GetExcelHeaders():
http://www.cnblogs.com/csqb-511612371/p/4891492.html
我們只需要把第42行-52行,規則集的驗證干掉,這次我們把表頭作為一個“X軸”數據先存起來,那么我們就能得到類似下面的表頭信息:
0,出發
1,到達總計
2,同期比(%)
3,干線合計
4,肇慶
...
接下來就來重構我們解析excel數據的方法GetExcelDatas(),在第三篇文章第7點。
我們注意第26/27行,以前的模板我們都是在這兒通過表頭與規則集匹配查找到相應DTO屬性進行賦值。
但是這次我們的規則集中並未對表頭進行配置(因為表頭內容不定),而是只配置了“X軸”、“Y軸”與“值”,那么我們重構這兩行代碼:
1 // 產生一個新的泛型對象 2 var model = Activator.CreateInstance<TableDTO>(); 3 // 獲取第i行第一列值 4 string rowItem = dataRow.GetCell(0).ToString(); 5 if (rowItem == "") 6 { 7 break; 8 } 9 //添加Y軸值到DTO對象 10 Regular YHeader = list.Find(h => h.HeaderText == "Y軸"); 11 string YProperty = YHeader.PropertyName; 12 PropertyInfo YProp = model.GetType().GetProperty(YProperty); 13 YProp.SetValue(model, rowItem, null); 14 15 16 //添加X軸值到DTO對象 17 Regular XHeader = list.Find(h => h.HeaderText == "X軸"); 18 string XProperty = XHeader.PropertyName; 19 PropertyInfo XProp = model.GetType().GetProperty(XProperty); 20 XProp.SetValue(model, dict[j], null); 21 22 23 string value = ""; 24 Regular header = list.Find(h => h.HeaderText == "值"); 25 string property = header.PropertyName; 26 PropertyInfo prop = model.GetType().GetProperty(property);
注:
1.第四行我們一直取第一列值,作為Y軸,當我們在循環X軸數據時,應當不變。
2.第20行,我們上面說到,已經把當前“上表頭”全部存入到了表頭解析數據dict字典中,所以X軸只需要按索引取出“上表頭”值即可
3.然后第24行,我們取出對單元格具體值的配置屬性,接下來就是以前的代碼獲取單元格值,反射賦值到該屬性中即可
重構到這一步,我們已經基本完成了對“矩陣類EXCEL模板”的數據解析。我們可以預料返回的DTO集合數據將是:
1423.53 總計 到達總計
111.2 總計 同期比(%)
525.24 總計 干線合計
......
111.2 同期比(%) 到達總計
0 同期比(%) 同期比(%)
130.7 同期比(%) 干線合計
......
我們只需要在DTO向實體做Mapper的時候,將Index屬性按從0開始遞加賦值即可。
至此,博主想分享的EXCEL操作系列就告一段落。
雖然還有一些更加復雜的excel(玫瑰圖等),但是博主感覺都很小眾化,這輩子遇上一次就算倒霉的了,就不再做方案分享了。
寫了六篇了,才感覺整體文章命名不好,其實NPOI在博主的項目中只起到了一個操作EXCEL的開源工具作用,使用其他開源組件可以隨意替換它。
主要想介紹用XML搭橋做規則集的一種excel解析思想。
希望對您有所幫助。如有寫的不對不好的地方,請指出,一定虛心請假...
原創文章,代碼都是從自己項目里貼出來的。轉載請注明出處哦,親~~~