通过模板(模板有样式)使用导出工具类(基于自定义注解,反射)导出excel
/** * 抽取工具类通过注解、反射,使用模板打印完成报表生成。 * 通过自定义注解:根据模板列顺序对实体属性 * 添加注解,例@ExcelAttribute(sort = 0) */ @RequestMapping(value = "/export/{type}", method = RequestMethod.GET) public void export(@PathVariable String type) throws Exception { //1.获取excel报表需要的数据 List<User> list = userService.findByType(type); //2.加载模板 Resource resource = new ClassPathResource("template/user.xlsx"); FileInputStream fis = new FileInputStream(resource.getFile()); //3.通过工具类完成下载 new ExcelExportUtil(User.class,2,2).export(response,fis,list,"用户报表.xlsx"); }
package com.*.poi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ExcelAttribute { /** 对应的列名称 */ String name() default ""; /** 列序号 */ int sort(); /** 字段类型对应的格式 */ String format() default ""; }
package com.*.common.poi.utils; import com.*.poi.ExcelAttribute; import lombok.Getter; import lombok.Setter; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.net.URLEncoder; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @Getter @Setter public class ExcelExportUtil<T> { private int rowIndex; private int styleIndex; private String templatePath; private Class clazz; private List<Field> fields; /** * 参数rowIndex为开始写入的行索引 * 参数styleIndex为需要获取表格的样式所在行的索引 */ public ExcelExportUtil(Class clazz,int rowIndex,int styleIndex) { this.clazz = clazz; this.rowIndex = rowIndex; this.styleIndex = styleIndex; fields = new ArrayList<>(); //getDeclaredFields获得当前类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。 //fields.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); while (clazz!=null){//父类字段也获取 fields.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); clazz = clazz.getSuperclass(); if(clazz.getName().equals("java.lang.Object")){ break; } } } /** * 基于注解导出 */ public void export(HttpServletResponse response,InputStream is, List<T> objs,String fileName) throws Exception { XSSFWorkbook workbook = new XSSFWorkbook(is); Sheet sheet = workbook.getSheetAt(0); CellStyle[] styles = getTemplateStyles(sheet.getRow(styleIndex)); AtomicInteger datasAi = new AtomicInteger(rowIndex); for (T t : objs) { Row row = sheet.createRow(datasAi.getAndIncrement()); for(int i=0;i<styles.length;i++) { Cell cell = row.createCell(i); cell.setCellStyle(styles[i]); for (Field field : fields) { if(field.isAnnotationPresent(ExcelAttribute.class)){ field.setAccessible(true); ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class); if(i == ea.sort()) { //取出数据,判空处理,否则设置值时空指针 Object obj = field.get(t); cell.setCellValue(null==obj?"":obj.toString()); } } } } } fileName = URLEncoder.encode(fileName, "UTF-8"); response.setContentType("application/octet-stream"); response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1"))); response.setHeader("filename", fileName); workbook.write(response.getOutputStream()); } /** * 获取模板样式 */ public CellStyle[] getTemplateStyles(Row row) { CellStyle [] styles = new CellStyle[row.getLastCellNum()]; for(int i=0;i<row.getLastCellNum();i++) { styles[i] = row.getCell(i).getCellStyle(); } return styles; } }