文章目录
前言
在系统中,数据库的excel文件导出是一项及为基础的功能。此篇文章将通过实例利用poi实现excel文件导出。
一、POI、HFFS是什么?
POI
Jakarta POI 是apache的子项目,目标是处理ole2对象。它提供了一组操纵Windows文档的Java API 。目前比较成熟的是HSSF接口,处理MS Excel(97-2002)对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。
HFFS
HSSF 是Horrible SpreadSheet Format的缩写,也即“讨厌的电子表格格式”。 也许HSSF的名字有点滑稽,就本质而言它是一个非常严肃、正规的API。通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。
HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多。
参考文档
POI 主页:http://jakarta.apache.org/poi/
初学者如何快速上手使用POI HSSF:http://jakarta.apache.org/poi/hssf/quick-guide.html
二、使用步骤
1.引入poi依赖包
<!--读取excel文件的包--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version></dependency>
2.创建工具类ExportExcel、ClassUtils
ExportExcel.java
publicclassExportExcel<T>{/**
* 将列表数据导出为 Excel 表格
* @param dataList 列表数据
* @param out 输出源
*/publicstaticboolean flag =true;publicstaticvoidexportExcel(List dataList,ServletOutputStream out)throwsIllegalAccessException,IOException{// 空集合直接返回if(dataList.isEmpty()){return;}// 获取泛型 T 的所有成员变量// 这里的第一种是获取原属性名,第二种是获取属性对应的注解 FieldName 的值,即对应的中文名称List<String> fieldList =ClassUtils.getFields(dataList.get(0).getClass());List<String> fieldNameList =ClassUtils.getFieldNames(dataList.get(0).getClass());// 建立一个 Excel 文件,并在文件中创建一个表单HSSFWorkbook workbook =newHSSFWorkbook();HSSFSheet sheet = workbook.createSheet();// 创建行(表头)HSSFRow row = sheet.createRow(0);// 创建单元格,并设置表头居中HSSFCellStyle hssfCellStyle = workbook.createCellStyle();
hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);// 循环设置列名(这里使用注解对应的中文名)HSSFCell hssfCell;for(int i =0; i < fieldNameList.size(); i++){
hssfCell = row.createCell(i);
hssfCell.setCellValue(fieldNameList.get(i));
hssfCell.setCellStyle(hssfCellStyle);}// 为每一行添加数据Map<String,Object> dataMap;for(int i =0; i < dataList.size(); i++){// 添加新的一行
row = sheet.createRow(i +1);// 获取泛型对象 RankResult的成员变量和值的对应关系
dataMap =ClassUtils.getFieldOfValue(dataList.get(i));// 将数据写入该行for(int j =0; j < fieldList.size(); j++){// 先通过 list 获取成员变量名,再通过 map 获取对应的值,转化为 String 之后放入表格中
row.createCell(j).setCellValue(""+ dataMap.get(fieldList.get(j)));}}// 将数据输出,刷出,关闭
workbook.write(out);
out.flush();;
out.close();}}
ClassUtils.java
publicclassClassUtils{/**
* 通过类型返回对应的属性列表
* @param target 目标类型
* @return 属性列表
*/publicstaticList<String>getFields(Class<?> target){// 获取所有成员变量名称List<String> fieldList =newArrayList<>();Field[] declaredFields = target.getDeclaredFields();// 放入 List 集合中for(Field field : declaredFields){
fieldList.add(field.getName());}return fieldList;}/**
* 通过类型返回对应的属性名称列表
* 名称为该属性上的 FieldName(自定义注解) 的值
* @param target 目标类型
* @return 属性对应的中文名称列表
*/publicstaticList<String>getFieldNames(Class<?> target){// 获取所有成员变量名称List<String> fieldList =newArrayList<>();Field[] declaredFields = target.getDeclaredFields();// 放入 List 集合中for(Field field : declaredFields){// 获取该成员变量注解 FieldName 的值,即其对应的中文名称// 这里通过反射,取出了属性中的 value 值,即属性对象的中文名称
fieldList.add(field.getAnnotation(FieldName.class).value());}return fieldList;}/**
* 获取泛型所有的成员及其值的映射
* @param data 泛型对象
* @param <T> 泛型
* @return 成员变量名和成员变量值的映射
*/publicstatic<T>Map<String,Object>getFieldOfValue(T data)throwsIllegalAccessException{// 获取所有成员变量,并建立一个 Map(大小为成员变量的个数)来存放名字和值的对应关系Field[] declaredFields = data.getClass().getDeclaredFields();Map<String,Object> fieldMap =newHashMap<>(declaredFields.length);// 获取每个成员属性对应的值,并映射for(Field field : declaredFields){// 允许访问私有变量的值
field.setAccessible(true);// 获取成员变量的值,并放入 map 中
fieldMap.put(field.getName(), field.get(data));}return fieldMap;}}
3.通过例子实现文件导出
3.1 创建导出注解类FiledName与实体类 ImportTemplate
FileName@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public@interfaceFieldName{String value default"名字";}
ImportTemplate@DatapublicclassImportTemplate{//注解@FieldName用来标注导出的excel的头行备注@FieldName("ID")privateInteger ID;@FieldName("标题")privateString task;@FieldName("需求")privateString demand;@FieldName("迭代")privateString iteration;@FieldName("处理人")privateString member;@FieldName("项目名称")privateString project;@FieldName("需求ID")privateInteger demandID;}
3.2 创建导出文件导出方法与实现
//下载导入模板文件voiddownloadTemplate(ServletOutputStream out)throwsIOException,IllegalAccessException;//Impl@OverridepublicvoiddownloadTemplate(ServletOutputStream out)throwsIOException,IllegalAccessException{//规定返回列表List<ImportTemplate> resultList =newArrayList<>();ImportTemplate template =newImportTemplate();
template.setID(1013516);
template.setTask("这里是任务名称");
template.setDemand("这里是需求名称");
template.setIteration("这里是迭代名");
template.setMember("李四");
template.setProject("这里是项目名");
template.setDemandID(1023123);
resultList.add(template);ExportExcel.exportExcel(resultList, out);if(ExportExcel.flag ==false){System.out.println("数据表导入模板导出出错×");}}
3.3 创建文件导出接口
//下载成员信息模板文件@GetMapping("/downloadTemplate")@ApiOperation(value="下载数据表导入模板", notes="详细描述")@ResponseBodypublicvoiddownloadTemplate(HttpServletResponse response)throwsIOException,IllegalAccessException{// 设置 ContentType 和返回头
response.setContentType("application/binary;charset=UTF-8");
response.setHeader("Content-Disposition","attachment;fileName="+URLEncoder.encode("数据表导入模板"+".xls","UTF-8"));//获得输出流ServletOutputStream out = response.getOutputStream();// 输出 excel 表格数据
rawdataService.downloadTemplate(out);}
后话
以上只是通过一个简单的案例实现数据库数据封装信息的文件导出,poi对excel文件的处理还有很多有意思的地方,对报表业务的功能大有建树,属于比较底层的excel文件处理插件,用于此功能阿里也有一套EasyExcel poi插件,主要解决poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错。
版权归原作者 CO_LA_ 所有, 如有侵权,请联系我们删除。