我们在第三篇文章中谈到了那些非常反人类的excel模板,博主为了养家糊口,也玩命做出了相应的解析方法...
我们先来看看第一类复杂表头:
......
博主称这类excel模板为略复杂表头模板(蓝色部分为表头部分,蓝色前面几行是博主项目的基础样式,称为元数据),这类excel的表头多为2-3行,甚至于5/6行 ,具有合并层级关系,看似复杂,但只需要在我们以前的基础上稍微做一下重构就可以完美实现解析。
我们以各地区户籍人口城乡构成表头为例:
其实,只要我们能准确解析这类表头所表达的意思,就能复用以前的代码做解析工作
也就是说,重点在于表头解析方法GetExcelHeaders(),
我们返回看第三篇文章中这个方法的代码:
第17行到33行
1 for (int j = headerRow.FirstCellNum; j < cellCount; j++) 2 { 3 if (!string.IsNullOrEmpty(headerRow.GetCell(j).StringCellValue.Trim())) 4 { { 8 string oldValue = dict[j]; 9 dict.Remove(j); 10 dict.Add(j, oldValue + headerRow.GetCell(j).StringCellValue.Trim()); 11 } 12 catch (Exception) 13 { 14 dict.Add(j, headerRow.GetCell(j).StringCellValue.Trim()); 15 } 16 } 17 }
我们在这儿做了一个列的循环,对表头所在行每一列做了一个值合并,那么我们可以预料:这个表头解析出来的结果:
0,地区
1,总人口(年末)(万人)
2,城镇人口人口数
3,比重(%)
4,乡村人口人口数
5,#比重(%)
那么我们的xml配置文件就该写成这样:
encoding=?> 2 <module> lastHeaderRow=/> propertyName=dataType=/> propertyName=dataType=/> propertyName=dataType=/> propertyName=dataType=/> propertyName=dataType=/> propertyName=dataType=/> 10 </module>
注:
1.第三行:5-7代表模板表头所在位置
OK,我们这样做就解析出了这个含有合并单元格的表头,那么接下来的所有流程就和简单表头一样了。
我们来总结一下:
1.修改配置文件xml,按我们的解析规则做映射配置
2.重构表头解析方法,按我们的配置解析表头数据
我们再来看看更复杂的表头模板:
......
这类模板除了表头外,还含有左表头。当然左表头也是需要存入数据库的,只是需要我们能准确解析到合并单元格所表达内容,方便导出是还原excel数据样式
以第一个excel水文特征值为例:
1.表头按合并表头做xml配置
2.左表头深色部分为合并区域,浅色部分为弱区域,可扩充
3.左表头需要解析成
水位.潮汐性质
水位.历年最高潮位
水位.多年平均高潮位
...
好吧,那么我们这次需要重构的就是解析数据的方法GetExcelDatas,我们看看第三篇文章:
中的代码
我们看到第42-45行,对空值只做了简单处理,那么我们先来普及一下NPOI遇到合并单元格怎么取值?
NPOI只能取到合并单元格最左上角单元格的值,其它单元格均为空值。那么既然我们的数据中含有左表头含有合并单元格,这个空值就需要做一个复杂判断了
我们先来捋一捋思路:如果取值时遇到空值,可能是单元格本就是空值,也可能是该单元格是合并单元格,切不在合并坐标左上角...
OK,我们来看重构后的这一段代码
1 if (value == "") 2 { 3 int firstRegionRow = 0; { { 8 int resultIndex = firstRegionRow - lastHeaderRowIndex; oldModel = 11 resultList.Select((p, d) => new { p, d }) 12 .Where(p => p.d == resultIndex) 13 .Select(p => p.p).First(); value = regionValue.ToString(); 16 } 17 } { 20 nullcount++; 21 } 22 }
注:
1.第4行涉及方法IsMergedRegionCell()是用来判断当前空值单元格是否是合并单元格,并返回合并单元格起始行
我们查阅NPOI接口得知,目前并不支持直接判断,只有通过自己的逻辑去判断是否是合并单元格(不知道是否是博主未查到准确的API,如有该API,请指出...)