这期内容当中小编将会给大家带来有关SpringBoot项目中利用POI实现导出Excel,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
一、准备工作
1、pom依赖
在pom.xml中加入POI的依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.11-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.11-beta1</version> </dependency>
2、自定义注解
自定义注解,用于定义excel单元格的相关信息,用在需要导出的类上。
大家可以根据自己的实际需求来定义更多的内容。
@Retention(RetentionPolicy.RUNTIME) public @interface ExcelResources { int order() default 9999;//定义字段在excel的单元格列坐标位置 String title() default "";//定义列坐标对应的标题 int cloumn() default 100;//定义列宽 String pattern() default "";//定义日期显示格式 }
3、定义需要导出的实体
举例说明@ExcelResources 的应用场景,我们创建一个demoModel,包含姓名、年龄、性别、日期。
后边的excel导出例子也采用这个实体类来举例。
@Data public class ExcelDemoModel { @ExcelResources(order=0,title = "姓名",cloumn = 10) private String name; @ExcelResources(order=1,title = "年龄",cloumn = 10) private Integer age; @ExcelResources(order=2,title = "创建时间",cloumn = 24,pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; @ExcelResources(order=3,title = "性别",cloumn = 10) private SexType sex;//枚举 }
4、定义导出辅助类
用于存放导出的excel对应标题和列宽
@Data @NoArgsConstructor @AllArgsConstructor public class TitleAndCloumn { private String title;//标题 private int cloumn;//列宽 }
二、具体的导出方法
1、导出主要方法
@Service public class ExcelService { private static float title_row_height=30;//标题行高 private static float data_row_height=25;//数据行高 public void exportExcel(HttpServletRequest request, HttpServletResponse response, String fileName ,List<?> excelDatas,Class<?> clz ) { try { HSSFWorkbook resultWb=new HSSFWorkbook(); HSSFSheet sheet=resultWb.createSheet();//创建sheet //根据类类型信息获取导出的excel对应的标题和列宽 key-列号,value-标题和列宽 HashMap<Integer, TitleAndCloumn> orderTitleAndCloumnMap=getTitleAndCloumnMap(clz); //设置列宽 orderTitleAndCloumnMap.forEach((k,v) -> { sheet.setColumnWidth(k, v.getCloumn()*256); }); HSSFRow row0=sheet.createRow(0); //设置标题行高 row0.setHeightInPoints(title_row_height); //创建标题单元格格式 HSSFCellStyle titleCellStyle=getCellStyle(resultWb,11,true,HSSFColor.BLACK.index); //填充标题行内容 orderTitleAndCloumnMap.forEach((k,v) -> { HSSFCell row0Cell=row0.createCell(k); row0Cell.setCellValue(v.getTitle()); row0Cell.setCellStyle(titleCellStyle); }); //创建正文单元格格式 HSSFCellStyle dataStyle = getCellStyle(resultWb,11,false,HSSFColor.BLACK.index); //将正文转换为excel数据 int rowNum=1; for(Object data:excelDatas){ HSSFRow row=sheet.createRow(rowNum++); row.setHeightInPoints(data_row_height); //获取对象值 key-列号 value-String值 HashMap<Integer,String> orderValueMap=getValueMap(data); orderValueMap.forEach((k,v) ->{ HSSFCell cell=row.createCell(k); cell.setCellValue(v); cell.setCellStyle(dataStyle); } ); } String downFileName=fileName+".xls"; response.setContentType("application/vnd.ms-excel; charset=UTF-8");// application/x-download response.setHeader("Content-Disposition", "attachment; " +encodeFileName(request, downFileName)); OutputStream outputStream = response.getOutputStream(); resultWb.write(outputStream); outputStream.flush(); outputStream.close(); resultWb.close(); }catch (Exception e1) { e1.printStackTrace(); } } }
2、通过反射获取excel标题和列宽
/** * 获取类的属性对应单元格标题和列宽 * @param * @return */ private static HashMap<Integer, TitleAndCloumn> getTitleAndCloumnMap(Class<?> clz) { HashMap<Integer, TitleAndCloumn> orderTitleAndCloumnMap=new HashMap<>(); Field[] fs = clz.getDeclaredFields(); for(Field f:fs) { f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)) { Integer order=f.getAnnotation(ExcelResources.class).order(); String title=f.getAnnotation(ExcelResources.class).title(); int cloumn=f.getAnnotation(ExcelResources.class).cloumn(); TitleAndCloumn titleAndCloumn=new TitleAndCloumn(title,cloumn); orderTitleAndCloumnMap.put(order,titleAndCloumn); } } return orderTitleAndCloumnMap; }
3、创建CellStyle
通过传入参数定义简单地CellStyle
public HSSFCellStyle getCellStyle(HSSFWorkbook workbook,int fontSize,boolean isBoleaWeight,short color){ HSSFCellStyle style = 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); HSSFFont font = workbook.createFont(); font.setFontHeightInPoints((short) fontSize);//字号 font.setColor(color);//颜色 font.setFontName("宋体");//字体 if(isBoleaWeight){ font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //字体加粗 } style.setWrapText(true); style.setFont(font); return style; }
4、通过反射获取对象信息并处理成String字符串
我这里只涉及到基本数据类型和Date以及枚举的值获取和转换,小伙伴可以根据自己的实际情况进行修改。
/** * 获取对象的属性对应单元格坐标和值的键值对 * @param obj * @return */ private static HashMap<Integer, String> getValueMap(Object obj) throws IllegalAccessException { HashMap<Integer, String> result=new HashMap<>(); Class<?> clz=obj.getClass(); Field[] fs = clz.getDeclaredFields(); for(Field f:fs) { f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)) { Integer order=f.getAnnotation(ExcelResources.class).order(); String value=""; Object valueObj=f.get(obj); if(valueObj!=null) { //日期格式进行特殊处理 if(f.getType()==Date.class){ String pattern=f.getAnnotation(ExcelResources.class).pattern(); if(StringUtils.isEmpty(pattern)){ pattern="yyyy-MM-dd HH:mm:ss"; } SimpleDateFormat sdf=new SimpleDateFormat(pattern); value=sdf.format(valueObj); }else{ value=valueObj.toString();//其他格式调用toString方法,这里枚举就需要定义自己的toString方法 } } result.put(order, value); } } return result; }
5、枚举的定义
如果有用到枚举存储在数据库的小伙伴,可以自定义枚举的toString方法来实现excel导出时候相应的内容
public enum SexType { male("男"), female("女"), ; private String typeName; SexType(String typeName) { this.typeName = typeName; } @Override public String toString() { return typeName; } }
6、encodeFileName
/** * 根据不同的浏览器生成不同类型中文文件名编码 * * @param request * @param fileName * @return * @throws UnsupportedEncodingException */ public static String encodeFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException { String new_filename = URLEncoder.encode(fileName, "UTF8").replaceAll("\\+", "%20"); String agent = request.getHeader("USER-AGENT").toLowerCase(); if (null != agent && -1 != agent.indexOf("msie")) { /** * IE浏览器,只能采用URLEncoder编码 */ return "filename=\"" + new_filename +"\""; }else if (null != agent && -1 != agent.indexOf("applewebkit")){ /** * Chrome浏览器,只能采用ISO编码的中文输出 */ return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\""; } else if (null != agent && -1 != agent.indexOf("opera")){ /** * Opera浏览器只可以使用filename*的中文输出 * RFC2231规定的标准 */ return "filename*=" + new_filename ; }else if (null != agent && -1 != agent.indexOf("safari")){ /** * Safani浏览器,只能采用iso编码的中文输出 */ return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\""; }else if (null != agent && -1 != agent.indexOf("firefox")) { /** * Firfox浏览器,可以使用filename*的中文输出 * RFC2231规定的标准 */ return "filename*=" + new_filename ; } else { return "filename=\"" + new_filename +"\""; } }
三、方法调用案例
1、方法调用
public void exportExcelDemo(HttpServletRequest request, HttpServletResponse response) { //一系列查询处理 List<ExcelDemoModel> demoList=new ArrayList<>(); excelService.exportExcel(request,response,"人员信息demo",demoList,ExcelDemoModel.class); }
2、导出效果
上述就是小编为大家分享的SpringBoot项目中利用POI实现导出Excel了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。