欢迎访问设·集合!

设·集合

您现在的位置是:首页 > 办公软件 > Excel

Java开发中如何用POI优雅的导出Excel文件

设·集合小编 发布时间:2023-03-03 10:58:50 258次最后更新:2024-06-12 10:37:33

前言

故事是这样开始的: 公司给排了几天的工期,让完成 2 个功能模块的开发。其中有一个场景是这样的,从 Excel 导入数据,要求数据不能重复。用户可以下载导入失败的 Excel 文件。

这样就有 2 种实现

  1. 将失败数据存储数据库,需要下载时生成 Excel 下载即可
  2. 将失败数据生成 Excel 文件存储文件服务器,然后返回下载链接。

老大要求按方案二进行。好吧,导出 Excel 是再常见不过的功能了,然而总是觉得以前写的不够优雅,所以决定进行简单的封装,以适应简单场景的 Excel 导出。

实现

Excel 导出的数据源一般是数据库中查询的数据。在 Java 开发这种面向对象的设计中,数据一般都是以对象为载体,填充在集合中的。所以入参之一便设计为 Collection 集合类。

导出的 Excel 一般需要表头说明每列数据的含义,这里计划用注解 反射来进行定义。Excel 无论是通过 HttpServletResponse 还是 File 存储,本质上都是 IO 流操作。

具体实现如下:

pom.xml

        
   
   
    org.apache.poi 
    
     poi-ooxml 
     
      4.1.2
      
    
   
  

注解定义

该注解添加在字段上,标识哪些字段需要导出到 Excel,并且添加表头说明。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelHeader {

    /**
     * 表头
     * @return
     */
    String value() default ``;

    /**
     * 列索引
     * @return
     */
    int columnIndex() default 0;

}

实体类

以下实体类中根据注解可知,age 字段不需要导出到 Excel。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @ExcelHeader(value = `账号`)
    private String username;

    @ExcelHeader(value = `密码`)
    private String password;

    @ExcelHeader(value = `生日`)
    @JsonFormat(pattern = `yyyy-MM-dd HH:mm:ss`)
    @DateTimeFormat(pattern = `yyyy-MM-dd HH:mm:ss`)
    private LocalDateTime birthday;

    // 该字段没有添加注解, Excel不导出
    private Integer age;

    public User(String username, String password, LocalDateTime birthday) {
        this.username = username;
        this.password = password;
        this.birthday = birthday;
    }
}

单元测试

注释已经足够清晰,这里不再过多复述。

@Slf4j
class IdcPoiApplicationTests {

    @Test
    void contextLoads() throws NoSuchFieldException, IllegalAccessException, IOException {
        // 创建模拟数据
        User user1 = new User(`admin`, `123456`, LocalDateTime.now());
        User user2 = new User(`test`, `123456`, LocalDateTime.now());
        List
  
    users = Arrays.asList(user1, user2); // 文件路径 String basePath = `/Users/cuishiying/Documents/spring-cloud-learning/idc-poi/oss/`; String fileName = new SimpleDateFormat(`yyyyMMddHHmmss`).format(new Date()).toString()  `.xls`; // 将Excel写入文件 HSSFWorkbook workbook = exportExcel(users, User.class); workbook.setSheetName(0,`sheetName`);//设置sheet的Name // 无论是通过HttpServletResponse导出还是导出到本地磁盘,本质都是IO操作,所以这里将IO操作提取到外层。 workbook.write(new File(basePath   File.separator   fileName)); } /** * * @param data 需要导出的数据 * @param clz 数据对应的实体类 * @param 
   
     泛型 * @return Excel文件 * @throws NoSuchFieldException * @throws IllegalAccessException */ public 
    
      HSSFWorkbook exportExcel(List
     
       data, Class
      
        clz) throws NoSuchFieldException, IllegalAccessException { Field fields = clz.getDeclaredFields(); List
       
         headers = new LinkedList<>(); List
        
          variables = new LinkedList<>(); // 创建工作薄对象 HSSFWorkbook workbook=new HSSFWorkbook();//这里也可以设置sheet的Name // 创建工作表对象 HSSFSheet sheet = workbook.createSheet(); // 创建表头 Row rowHeader = sheet.createRow(0); // 表头处理 for (int h = 0; h < fields.length; h  ) { Field field = fieldsh; if (field.isAnnotationPresent(ExcelHeader.class)) { // 表头 ExcelHeader annotation = field.getAnnotation(ExcelHeader.class); headers.add(annotation.value()); rowHeader.createCell(h).setCellValue(annotation.value()); // 字段 variables.add(field.getName()); } } // 数据处理 for (int i = 0; i < data.size() ; i  ) { //创建工作表的行(表头占用1行, 这里从第二行开始) HSSFRow row = sheet.createRow(i   1); // 获取一行数据 T t = data.get(i); Class
          aClass = t.getClass(); // 填充列数据 for (int j = 0; j < variables.size(); j  ) { Field declaredField = aClass.getDeclaredField(variables.get(j)); declaredField.setAccessible(true); String key = declaredField.getName(); Object value = declaredField.get(t); row.createCell(j).setCellValue(value.toString()); } } log.info(`Excel文件创建成功`); return workbook; } } 
        
       
      
     
    
   
  

总结

上边的案例只是表达基本设计思路,并不严谨。大家项目中使用的话还请斟酌。本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】支持一下。

广告位

热心评论

评论列表