SpringBoot整合POI导出通用Excel的方法示例
一、准备工作
1、pom依赖
在pom.xml中加入POI的依赖
org.apache.poi poi-ooxml 3.11-beta1 org.apache.poi poi-ooxml-schemas 3.11-beta1
2、自定义注解
自定义注解,用于定义excel单元格的相关信息,用在需要导出的类上。
大家可以根据自己的实际需求来定义更多的内容。
@Retention(RetentionPolicy.RUNTIME) public@interfaceExcelResources{ intorder()default9999;//定义字段在excel的单元格列坐标位置 Stringtitle()default"";//定义列坐标对应的标题 intcloumn()default100;//定义列宽 Stringpattern()default"";//定义日期显示格式 }
3、定义需要导出的实体
举例说明@ExcelResources的应用场景,我们创建一个demoModel,包含姓名、年龄、性别、日期。
后边的excel导出例子也采用这个实体类来举例。
@Data publicclassExcelDemoModel{ @ExcelResources(order=0,title="姓名",cloumn=10) privateStringname; @ExcelResources(order=1,title="年龄",cloumn=10) privateIntegerage; @ExcelResources(order=2,title="创建时间",cloumn=24,pattern="yyyy-MM-ddHH:mm:ss") privateDatecreateTime; @ExcelResources(order=3,title="性别",cloumn=10) privateSexTypesex;//枚举 }
4、定义导出辅助类
用于存放导出的excel对应标题和列宽
@Data @NoArgsConstructor @AllArgsConstructor publicclassTitleAndCloumn{ privateStringtitle;//标题 privateintcloumn;//列宽 }
二、具体的导出方法
1、导出主要方法
@Service publicclassExcelService{ privatestaticfloattitle_row_height=30;//标题行高 privatestaticfloatdata_row_height=25;//数据行高 publicvoidexportExcel(HttpServletRequestrequest,HttpServletResponseresponse,StringfileName,List>excelDatas,Class>clz){ try{ HSSFWorkbookresultWb=newHSSFWorkbook(); HSSFSheetsheet=resultWb.createSheet();//创建sheet //根据类类型信息获取导出的excel对应的标题和列宽key-列号,value-标题和列宽 HashMaporderTitleAndCloumnMap=getTitleAndCloumnMap(clz); //设置列宽 orderTitleAndCloumnMap.forEach((k,v)->{ sheet.setColumnWidth(k,v.getCloumn()*256); }); HSSFRowrow0=sheet.createRow(0); //设置标题行高 row0.setHeightInPoints(title_row_height); //创建标题单元格格式 HSSFCellStyletitleCellStyle=getCellStyle(resultWb,11,true,HSSFColor.BLACK.index); //填充标题行内容 orderTitleAndCloumnMap.forEach((k,v)->{ HSSFCellrow0Cell=row0.createCell(k); row0Cell.setCellValue(v.getTitle()); row0Cell.setCellStyle(titleCellStyle); }); //创建正文单元格格式 HSSFCellStyledataStyle=getCellStyle(resultWb,11,false,HSSFColor.BLACK.index); //将正文转换为excel数据 introwNum=1; for(Objectdata:excelDatas){ HSSFRowrow=sheet.createRow(rowNum++); row.setHeightInPoints(data_row_height); //获取对象值key-列号value-String值 HashMap orderValueMap=getValueMap(data); orderValueMap.forEach((k,v)->{ HSSFCellcell=row.createCell(k); cell.setCellValue(v); cell.setCellStyle(dataStyle); } ); } StringdownFileName=fileName+".xls"; response.setContentType("application/vnd.ms-excel;charset=UTF-8");//application/x-download response.setHeader("Content-Disposition","attachment;" +encodeFileName(request,downFileName)); OutputStreamoutputStream=response.getOutputStream(); resultWb.write(outputStream); outputStream.flush(); outputStream.close(); resultWb.close(); }catch(Exceptione1){ e1.printStackTrace(); } } }
2、通过反射获取excel标题和列宽
/** *获取类的属性对应单元格标题和列宽 *@param *@return */ privatestaticHashMapgetTitleAndCloumnMap(Class>clz){ HashMap orderTitleAndCloumnMap=newHashMap<>(); Field[]fs=clz.getDeclaredFields(); for(Fieldf:fs){ f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)){ Integerorder=f.getAnnotation(ExcelResources.class).order(); Stringtitle=f.getAnnotation(ExcelResources.class).title(); intcloumn=f.getAnnotation(ExcelResources.class).cloumn(); TitleAndCloumntitleAndCloumn=newTitleAndCloumn(title,cloumn); orderTitleAndCloumnMap.put(order,titleAndCloumn); } } returnorderTitleAndCloumnMap; }
3、创建CellStyle
通过传入参数定义简单地CellStyle
publicHSSFCellStylegetCellStyle(HSSFWorkbookworkbook,intfontSize,booleanisBoleaWeight,shortcolor){ HSSFCellStylestyle=workbook.createCellStyle(); style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); HSSFFontfont=workbook.createFont(); font.setFontHeightInPoints((short)fontSize);//字号 font.setColor(color);//颜色 font.setFontName("宋体");//字体 if(isBoleaWeight){ font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//字体加粗 } style.setWrapText(true); style.setFont(font); returnstyle; }
4、通过反射获取对象信息并处理成String字符串
我这里只涉及到基本数据类型和Date以及枚举的值获取和转换,小伙伴可以根据自己的实际情况进行修改。
/** *获取对象的属性对应单元格坐标和值的键值对 *@paramobj *@return */ privatestaticHashMapgetValueMap(Objectobj)throwsIllegalAccessException{ HashMap result=newHashMap<>(); Class>clz=obj.getClass(); Field[]fs=clz.getDeclaredFields(); for(Fieldf:fs){ f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)){ Integerorder=f.getAnnotation(ExcelResources.class).order(); Stringvalue=""; ObjectvalueObj=f.get(obj); if(valueObj!=null){ //日期格式进行特殊处理 if(f.getType()==Date.class){ Stringpattern=f.getAnnotation(ExcelResources.class).pattern(); if(StringUtils.isEmpty(pattern)){ pattern="yyyy-MM-ddHH:mm:ss"; } SimpleDateFormatsdf=newSimpleDateFormat(pattern); value=sdf.format(valueObj); }else{ value=valueObj.toString();//其他格式调用toString方法,这里枚举就需要定义自己的toString方法 } } result.put(order,value); } } returnresult; }
5、枚举的定义
如果有用到枚举存储在数据库的小伙伴,可以自定义枚举的toString方法来实现excel导出时候相应的内容
publicenumSexType{ male("男"), female("女"), ; privateStringtypeName; SexType(StringtypeName){ this.typeName=typeName; } @Override publicStringtoString(){ returntypeName; } }
6、encodeFileName
/** *根据不同的浏览器生成不同类型中文文件名编码 * *@paramrequest *@paramfileName *@return *@throwsUnsupportedEncodingException */ publicstaticStringencodeFileName(HttpServletRequestrequest,StringfileName) throwsUnsupportedEncodingException { Stringnew_filename=URLEncoder.encode(fileName,"UTF8").replaceAll("\\+","%20"); Stringagent=request.getHeader("USER-AGENT").toLowerCase(); if(null!=agent&&-1!=agent.indexOf("msie")) { /** *IE浏览器,只能采用URLEncoder编码 */ return"filename=\""+new_filename+"\""; }elseif(null!=agent&&-1!=agent.indexOf("applewebkit")){ /** *Chrome浏览器,只能采用ISO编码的中文输出 */ return"filename=\""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+"\""; }elseif(null!=agent&&-1!=agent.indexOf("opera")){ /** *Opera浏览器只可以使用filename*的中文输出 *RFC2231规定的标准 */ return"filename*="+new_filename; }elseif(null!=agent&&-1!=agent.indexOf("safari")){ /** *Safani浏览器,只能采用iso编码的中文输出 */ return"filename=\""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+"\""; }elseif(null!=agent&&-1!=agent.indexOf("firefox")) { /** *Firfox浏览器,可以使用filename*的中文输出 *RFC2231规定的标准 */ return"filename*="+new_filename; }else { return"filename=\""+new_filename+"\""; } }
三、方法调用案例
1、方法调用
publicvoidexportExcelDemo(HttpServletRequestrequest,HttpServletResponseresponse){ //一系列查询处理 ListdemoList=newArrayList<>(); excelService.exportExcel(request,response,"人员信息demo",demoList,ExcelDemoModel.class); }
2、导出效果
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。