前面我们已经实现了反射机制进行excel表格数据的解析,既然有上传就得有下载,我们再来写一个通用的导出方法,利用反射机制实现对系统所有数据列表的筛选结果导出excel功能。

我们来构想一下这样一个画面,管理员筛选出北京的所有员工数据,想导出成excel表格;管理员筛选出北京所有欠费的企业数据,想导出成excel表格;管理员想导出本月的工单报表到excel表格;管理员想导出近3月北京各岗位的运营报表到excel表格......

系统客服真是个神奇的职业,神马都想导出到excel表格!

那么对于我们的程序来说,该怎么做呢!由于每个导出功能对应的数据源都不一样,简单的方法很难做到,只能每个业务单写一个导出功能。

所以,我们再次沿用导入时使用的xml文件配置做桥梁,通过反射技术做具体实现的方法,做一个通用的EXCEL导出工具:传入DTO数据集合与xml规则集,返回excel文件流。

1.我们创建一个xml文件,里面存放所有需要导出功能涉及字段的规则集(博主项目涉及到的导出功能也就10来个列表,约涉及100多个字段(这儿未全部列出),故未分开成多个xml规则文件)

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <module>
  3. <add ExportFieldName="姓名" PropertyName="Name" DataType="System.String"/>
  4. <add ExportFieldName="手机号码" PropertyName="PhoneNumber" DataType="System.String"/>
  5. <add ExportFieldName="性别" PropertyName="Sex" DataType="System.String"/>
  6. <add ExportFieldName="民族" PropertyName="Nation" DataType="System.String"/>
  7. <add ExportFieldName="出生日期" PropertyName="Birthday" DataType="System.String"/>
  8. <add ExportFieldName="身份证号码" PropertyName="Cardid" DataType="System.String"/>
  9. </module>

注:

1.导出的规则相对简单,所以我们创建一个简单的规则集类:

  1. /// <summary>
  2. /// 导出excel-中英文规则类
  3. /// </summary>
  4. public class ExportRegular
  5. {
  6. /// <summary>
  7. /// 属性名称(英文)
  8. /// </summary>
  9. public string PropertyName { get; set; }
  10.  
  11. /// <summary>
  12. /// 数据类型
  13. /// </summary>
  14. public string DataType { get; set; }
  15.  
  16. /// <summary>
  17. /// 导出名称(中文)
  18. /// </summary>
  19. public string ExportFieldName { get; set; }
  20. }

2.然后是解析XML规则集的方法

  1. /// <summary>
  2. /// 解析XML规则集文件
  3. /// </summary>
  4. /// <returns></returns>
  5. public static List<ExportRegular> GetExportRegulars()
  6. {
  7. var result = new List<ExportRegular>();
  8.  
  9. var reader = new XmlTextReader(xmlpath);
  10. var doc = new XmlDocument();
  11. //从指定的XMLReader加载XML文档
  12. doc.Load(reader);
  13.  
  14. foreach (XmlNode node in doc.DocumentElement.ChildNodes)
  15. {
  16. var header = new ExportRegular();
  17.  
  18. if (node.Attributes["PropertyName"] != null)
  19. header.PropertyName = node.Attributes["PropertyName"].Value;
  20. if (node.Attributes["DataType"] != null)
  21. header.DataType = node.Attributes["DataType"].Value;
  22. if (node.Attributes["ExportFieldName"] != null)
  23. header.ExportFieldName = node.Attributes["ExportFieldName"].Value;
  24.  
  25. result.Add(header);
  26. }
  27.  
  28. return result;
  29. }

2.我们的excel导出工具对外暴露两个静态方法:

  1. public static MemoryStream CreateExcelStreamByDatas(List<object> objectDatas, KeyValuePair<string, string> excelHeader)
  2.  
  3. public static MemoryStream CreateExcelStreamByDatas(List<KeyValuePair<List<object>, KeyValuePair<string, string>>> objectDatass)

一个是单sheet表单导出接口,一个是多表单导出接口(例:管理员导出东三省的员工数据,则导出excel含4个表单(1、东三省全部数据;2、辽宁省数据;3、吉林省数据;4、黑龙江省数据))

参数objectDatas是从库中筛选到的结果DTO数据集,excelHeader是一个键值对:key-表头名称,value-sheet表单名称

3.我们具体来看单表单方法的实现:

  1. /// <summary>
  2. /// 将数据转换成excel文件流输出 ->单表单导出接口
  3. /// </summary>
  4. /// <returns></returns>
  5. public static MemoryStream CreateExcelStreamByDatas(List<object> objectDatas, KeyValuePair<string, string> excelHeader)
  6. {
  7. // 返回对象
  8. var ms = new MemoryStream();
  9.  
  10. // excel工作簿
  11. IWorkbook workbook = new HSSFWorkbook();
  12. //导入数据到sheet表单
  13. CreateExcelSheetByDatas(objectDatas, excelHeader.Key, excelHeader.Value, ref workbook);
  14.  
  15. workbook.Write(ms);
  16. ms.Flush();
  17. ms.Position = ;
  18.  
  19. return ms;
  20. }

我们将具体功能逻辑抽象到了方法CreateExcelSheetByDatas中,

那么多表单的实现只需要修改第13行为:

  1. foreach (KeyValuePair<List<object>, KeyValuePair<string, string>> keyValuePair in objectDatass)
  2. {
  3. //导入数据到sheet表单
  4. CreateExcelSheetByDatas(keyValuePair.Key, keyValuePair.Value.Key, keyValuePair.Value.Value, ref workbook);
  5. }

4.我们来实现最核心的方法CreateExcelSheetByDatas(博主还没来得及重构代码,所有逻辑都写在里面了,略长...)

  1. /// <summary>
  2. /// 根据传入数据新建sheet表单到指定workbook
  3. /// </summary>
  4. /// <param name="objectDatas"></param>
  5. /// <param name="excelHeader"></param>
  6. /// <param name="sheetName"></param>
  7. /// <param name="regulars"></param>
  8. /// <param name="workbook"></param>
  9. private static void CreateExcelSheetByDatas(List<object> objectDatas, string excelHeader, string sheetName, ref IWorkbook workbook)
  10. {
  11. var regulars = GetExportRegulars();
  12.  
  13. // excel sheet表单
  14. ISheet sheet = workbook.CreateSheet(sheetName);
  15. // excel行数
  16. int rows = ;
  17.  
  18. #region 单元格 -表头格式
  19.  
  20. #region 表头字体
  21.  
  22. IFont fontTitle = workbook.CreateFont();
  23. fontTitle.FontHeightInPoints = ;
  24. fontTitle.Boldweight = (short)FontBoldWeight.BOLD;
  25.  
  26. #endregion
  27.  
  28. ICellStyle styleTitle = workbook.CreateCellStyle();
  29. styleTitle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.CENTER;
  30. styleTitle.SetFont(fontTitle);
  31. styleTitle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.CENTER;
  32.  
  33. #endregion
  34.  
  35. #region 单元格 -表体格式
  36.  
  37. #region 表体字体
  38.  
  39. IFont fontMessage = workbook.CreateFont();
  40. fontMessage.FontHeightInPoints = ;
  41.  
  42. #endregion
  43.  
  44. ICellStyle styleMessage = workbook.CreateCellStyle();
  45. styleMessage.Alignment = NPOI.SS.UserModel.HorizontalAlignment.CENTER;
  46. styleMessage.SetFont(fontMessage);
  47. styleMessage.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.CENTER;
  48.  
  49. #endregion
  50.  
  51. // 创建表头并赋值
  52. int firstRowCellCount = GetAttributeCount(objectDatas.First());
  53. IRow headerRow = sheet.CreateRow(rows);
  54. headerRow.HeightInPoints = ;
  55. var headerCell = headerRow.CreateCell();
  56. headerCell.SetCellValue(excelHeader);
  57.  
  58. // 合并表头
  59. var cellRangeAddress = new CellRangeAddress(rows, rows, , firstRowCellCount - );
  60. sheet.AddMergedRegion(cellRangeAddress);
  61. // 设置表头格式
  62. headerCell.CellStyle = styleTitle;
  63.  
  64. //生成表头
  65. if (objectDatas.Any())
  66. {
  67. rows++;
  68. // excel列数
  69. int cells = -;
  70. // 创建数据行
  71. var firstRow = sheet.CreateRow(rows);
  72. firstRow.HeightInPoints = ;
  73. var objectData = objectDatas.FirstOrDefault();
  74. foreach (System.Reflection.PropertyInfo p in objectData.GetType().GetProperties())
  75. {
  76. cells++;
  77. var regular = regulars.Find(t => t.PropertyName == p.Name);
  78. if (regular == null)
  79. {
  80. throw new Exception("导出excel时,出现未配置字段。表:" + objectData.GetType().Name + ",字段:" + p.Name);
  81. }
  82. var firstRowCell = firstRow.CreateCell(cells);
  83. firstRowCell.SetCellValue(regular.ExportFieldName);
  84. sheet.SetColumnWidth(cells, regular.ExportFieldName.Length * * );
  85. firstRowCell.CellStyle = styleMessage;
  86. }
  87. }
  88.  
  89. // 反射object对象,遍历字段
  90. foreach (var objectData in objectDatas)
  91. {
  92. rows++;
  93. // excel列数
  94. int cells = -;
  95. // 创建数据行
  96. var messageRow = sheet.CreateRow(rows);
  97. messageRow.HeightInPoints = ;
  98. foreach (System.Reflection.PropertyInfo p in objectData.GetType().GetProperties())
  99. {
  100. cells++;
  101. var regular = regulars.Find(t => t.PropertyName == p.Name);
  102. var messageCell = messageRow.CreateCell(cells);
  103. var value = p.GetValue(objectData);
  104. if (value == null)
  105. {
  106. messageCell.SetCellValue("");
  107. }
  108. else
  109. {
  110. switch (regular.DataType)
  111. {
  112. case "datetime":
  113. if (Convert.ToDateTime(value) == DateTime.MinValue)
  114. {
  115. messageCell.SetCellValue("");
  116. }
  117. else
  118. {
  119. messageCell.SetCellValue(
  120. Convert.ToDateTime(value).ToString("yyyy-MM-dd HH:mm:ss"));
  121. }
  122. break;
  123. case "int":
  124. messageCell.SetCellValue(Convert.ToInt32(value));
  125. break;
  126. case "double":
  127. messageCell.SetCellValue(Convert.ToDouble(value));
  128. break;
  129. case "bool":
  130. var setValue = "是";
  131. if (!(bool)value)
  132. {
  133. setValue = "否";
  134. }
  135. messageCell.SetCellValue(setValue);
  136. break;
  137. default:
  138. messageCell.SetCellValue(value.ToString());
  139. break;
  140. }
  141. }
  142. messageCell.CellStyle = styleMessage;
  143. }
  144. }
  145. }

注:

1.第18到62行均是对表体、表头字体格式的指定,并创建合并表头名称

2.第66行到88行是在遍历DTO属性,按规则集取出对应中文名称创建表头字段

此处特别说明:博主把所有导出DTO的所有属性字段都是做的简单类型字段,方便做反射。

3.第52行GetAttributeCount方法,是获取DTO对象所有属性个数

4.第91行到145行是按规则集规则将DTO中对应数据写进excel单元格

至此,我们就实现了将DTO集合按规则集导出到excel表格的方法。

我们只需要在各个导出服务中,先查库获取到需要的数据集合,再Map到DTO集合中,作为参数调用EXCEL导出方法即可返回需要的excel文件流。

到这儿,NPOI操作简单模板excel进行导入导出的相关代码就贴完了。如有什么地方写的不对或不好,欢迎指出,一定虚心请教~~~

上一篇博文说到的那些反人类的excel的导入,会在下一篇博文贴出具体实现的代码,敬请期待~~~

原创文章,代码都是从自己项目里贴出来的。转载请注明出处哦,亲~~~

NPOI操作EXCEL(四)——反射机制批量导出excel文件的更多相关文章

  1. NPOI 操作数据库中数据的导入导出(Excel.xls文件) 和null数据的处理。

    App.config: <?xml version="1.0" encoding="utf-8" ?> <configuration> ...

  2. vue将指定区域的表格数据或element-ui中el-table的数据单笔或多笔批量导出excel

    公司在后台管理系统开发中用到了 vue+element-ui 组合的框架,但随着需求的越来越复杂,前端的工作难度也呈几何倍数递增,工作量随之增大.这不,在项目中增加一个将列表数据导出为excel的需求 ...

  3. html table表格导出excel的方法 html5 table导出Excel HTML用JS导出Excel的五种方法 html中table导出Excel 前端开发 将table内容导出到excel HTML table导出到Excel中的解决办法 js实现table导出Excel,保留table样式

    先上代码   <script type="text/javascript" language="javascript">   var idTmr; ...

  4. Excel实用技巧-如何批量提取excel工作表名称

    Excel实用技巧-如何批量提取excel工作表名称 1. 打开Excel文件,点击“公式”栏,进而点击“定义管理器” 2. 在弹出的对话框中,点击新增按钮, 名称:“sheet”,引用位置:“=RE ...

  5. NPOI、MyXls、Aspose.Cells 导入导出Excel(转)

    Excel导入及导出问题产生: 从接触.net到现在一直在维护一个DataTable导s出到Excel的类,时不时还会维护一个导入类.以下是时不时就会出现的问题: 导出问题: 如果是asp.net,你 ...

  6. 利用java反射机制实现读取excel表格中的数据

    如果直接把excel表格中的数据导入数据库,首先应该将excel中的数据读取出来. 为了实现代码重用,所以使用了Object,而最终的结果是要获取一个list如List<User>.Lis ...

  7. .net使用NPOI的XSSFWorkbook进行web开发中导出Excel

    之前也使用过NPOI导出excel,这次是因为在导出的excel里新增了几个列,正好超出了255的限制,所以又要改了. 今天主要出了4个问题: 1. Invalid column index (256 ...

  8. JAVA POI XSSFWorkbook导出扩展名为xlsx的Excel,附带weblogic 项目导出Excel文件错误的解决方案

    现在很多系统都有导出excel的功能,总结一下自己之前写的,希望能帮到其他人,这里我用的是XSSFWorkbook,我们项目在winsang 用的Tomcat,LInux上用的weblogic服务器, ...

  9. MVC 导出Excel 的其中一方法(View导出excel)

    场景:mvc下导出excel 思路:使用View导出excel 步骤: 1.导出标签添加事件 $("#export_A").click(function(){ //省略代码.... ...

随机推荐

  1. Elasticsearch的CRUD:REST与Java API

    CRUD(Create, Retrieve, Update, Delete)是数据库系统的四种基本操作,分别表示创建.查询.更改.删除,俗称"增删改查".Elasticsearch ...

  2. JQuery Sizzle引擎源代码分析

    最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦.有没有吹牛?是不是我说大话了? 什么是Sizzle引擎? 我们经常使用JQuery的选择器查询 ...

  3. domReady的实现

    我们都知道JQ的 $(document).ready(fn) 方法.可以在页面准备就绪后才执行脚本,该方法相比传统的window.onload 事件,它的优势体现于onload事件是需要等到页面中所有 ...

  4. jQuery+CSS3文字跑马灯特效

    jQuery+CSS3文字跑马灯特效是一款将跑马灯背景制作为3D立方体效果,文字在上面移动时,就像是文字投影到墙壁上,在转角出会改变运动方向. 效果展示 http://hovertree.com/te ...

  5. canvas贝塞尔曲线

    贝塞尔曲线 Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线. 曲线定义:起始点.终止点.控制点.通过调整控制点,贝塞尔曲线的形状会发生变化. 1962年,法国数学家Pierr ...

  6. 怎样给div增加resize事件

    当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件,这个事件在window上面触发,那么如何给div元素增加resize事件,监听div的高度或宽度的改变呢? 先来回答另一个问题,监听 ...

  7. H5——表单验证新特性,注册模态框!

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. 移动站适配rel=alternate PC页和H5页适配标注

    鉴于移动化大潮的汹涌和H5页的炫丽普及,百度针对PC页与H5页的跳转适配方式推出了最优方案:1.在pc版网页上,添加指向对应移动版网址的特殊链接rel="alternate"标记, ...

  9. node.js express安装及示例网站搭建

    1.首先肯定是要安装Node.JS windows cmd依次输入如下命令: cd C:\Program Files\nodejs\ npm install -g expressnpm install ...

  10. jquery toggle方法使用出错?请看这里-遁地龙卷风

    这个函数在1.9之前和1.9之后的用法大不相同 1 1.9之间,用于点击元素时函数的轮流执行 toggle(function() { alert(1);//1,3,5,7... },function( ...