使用POI以注解对象为单位导出多个sheet表

  谢谢大家牺牲自己宝贵的时间阅读拙作,这是在下的第一篇博客,若有疏忽和不当之处,请多多指正,谢谢,下面进入正题。

  工作中我们可能会遇到要将多个对象作为sheet表导入excel的情况,下面就是我应对这种情况对poi进行的一次简单封装。

  需要引入的pom:

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

  <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
ps:事实上我们只需要poi就足够完成所有功能的实现,lombok的引入是为了提高编写的效率和代码的可读性,作为个人来说,如果为了练习的话不建议使用lombok。

  首先,为了简化导出表时对于列的操作,我们可以先对需要导出的对象添加一个注解标签,以便于之后的操作,此处就使用ExcelAttribute作为注解名称:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelAttribute {
    //列名
    String name();
    //列序号
    int column();
    //是否需要导出
    boolean isExport() default true;
    //单元格是否需要自适应
    boolean isAdaptive() default false;
}
 本次我是以Map的方式传递参数的,因为使用key值作为sheet名称会显得更加直观一些,如果有需要可以再添加一个ExcelSheet的注解,标记在所需要导出的类的类名上

 以List<List<?>>的形式传递参数,如果需要使用,只需要在抓取list<?>的泛型后扫描该注解即可,本次就为了节省篇幅就不作介绍了。

  我们建立完注解,便可以进行工具类的编写,此处导出为2003版的excel:

    /**
     * @param datas 导出报表,以key值作为表名
     * @return
     */
    public static Workbook exportExcelByMaps(Map<String,List<?>> datas){
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
        //遍历Map
        for(Map.Entry<String, List<?>> map : datas.entrySet()){
            List<?> list = map.getValue();
            //将key值设为sheet名称
            HSSFSheet sheet = hssfWorkbook.createSheet(map.getKey());
            //判断map的值是否为空
            if(null == map.getValue() || map.getValue().size() == 0)
                continue;
            //使用反射抓取list的泛型
            Type type = list.getClass().getGenericSuperclass();
            ParameterizedType p = (ParameterizedType)type;
            Class cls = (Class)p.getActualTypeArguments()[0];
            //可能有即便list可能传递为空,也需要导出到表格的情况发生,所以弃置定位取类型的方法
            //Field[] fields = list.get(0).getClass().getDeclaredFields();
            Field[] fields = cls.getDeclaredFields();
            Row titleRow = sheet.createRow(0);
            for (int i = 0, m = fields.length; i < m; i++){
                //判断该属性是否是需要导出的列,不是则直接跳过
                if(!fields[i].isAnnotationPresent(ExcelAttribute.class)){
                    continue;
                }
                //获取属性的对应注解
                ExcelAttribute excelAttribute = fields[i].getAnnotation(ExcelAttribute.class);
                if(excelAttribute.isExport()) {
                    int colum = excelAttribute.column() - 1;
                    Cell cell = titleRow.createCell(colum);
                    cell.setCellValue(excelAttribute.name());
                    if(excelAttribute.isAdaptive()) {
                        sheet.autoSizeColumn(colum);
                    }
                }
                continue;
            }
            //遍历list
            int startIndex = 0;
            int endIndex = list.size();
            Row row = null;
            Cell cell = null;
            for(int i = startIndex; i < endIndex; i++){
                row = sheet.createRow(i+1-startIndex);
                //如果list为空或者size为0则跳过
                if(list.size() == 0 || null == list){
                    continue;
                }
                Object o = list.get(i);
                for(int m = 0;m<fields.length;m++){
                    Field field = fields[m];
                    if(!field.isAnnotationPresent(ExcelAttribute.class)){
                        continue;
                    }
                    field.setAccessible(true);
                    ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
                    try{
                        //判断该属性在现有需求下是否需要导出
                        if(attr.isExport()){
                            //让列的宽度自适应
                            if(attr.isAdaptive()){
                                sheet.autoSizeColumn(attr.column() - 1);
                            }
                            cell = row.createCell(attr.column() - 1);
                            cell.setCellValue(field.get(o) == null? "":String.valueOf(field.get(o)));
                        }
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        return hssfWorkbook;
    }

完成了工具类的编写之后我们需要设定下导出的方式,一般来说,我们经常使用的就是指定路径导出或者以流的方式附加在HttpServletResponse中

 /**
     * 将workbook附加在response中
     */
    public static void export2Response(Workbook workbook , String fileName,HttpServletResponse response){
        try{
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String((fileName + ".xls").getBytes("GBK"), "iso-8859-1"));
            workbook.write(response.getOutputStream());
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 将excel输出至本地路径
     */
    public static void export2Path(Workbook workbook , String fileName,String path){
        File dir = new File(path);
        //路径不存在则创建
        if(!dir.exists()||!(dir.isDirectory())){
            dir.mkdir();
        }
        String filePath = path.concat(fileName).concat(".xls");
        File file = new File(filePath);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file);
            workbook.write(out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException ioe){
            ioe.printStackTrace();
        } finally {
            //关闭流
            if(null != out) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
测试用实体类:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    @ExcelAttribute(column = 1,name = "姓名",isAdaptive = true)
    private String name;
    @ExcelAttribute(column = 2,name = "年龄",isAdaptive = true)
    private String age;
    @ExcelAttribute(column = 3,name = "性别",isAdaptive = true)
    private String gender;
    @ExcelAttribute(column = 4,name = "注释",isExport = false)
    private String mark;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class DogeInfo {
    @ExcelAttribute(column = 4,name = "姓名a",isAdaptive = true)
    private String name;
    @ExcelAttribute(column = 3,name = "年龄a",isAdaptive = true)
    private String age;
    @ExcelAttribute(column = 1,name = "性别a",isAdaptive = true)
    private String gender;
    @ExcelAttribute(column = 2,name = "注释a",isExport = false)
    private String mark;
}

测试片段:

 public static Workbook exportExcel(){
        Map<String, List<?>> temp = new HashMap<>();
        UserInfo tempUser1 = new UserInfo("alien","11","1","clone");
        UserInfo tempUser2 = new UserInfo("寿限无寿限无EWQEWQEWQEWQE","2222222","22","dsadsa");
        UserInfo tempUser3 = new UserInfo("dwqdwqdw","222","2","2");
        DogeInfo dogeInfo1 = new DogeInfo("alien","11","1","clone");
        DogeInfo dogeInfo12 = new DogeInfo("寿限无寿限无EWQEWQEWQEWQE","2222222","22","dsadsa");
        DogeInfo dogeInfo13 = new DogeInfo("dwqdwqdw","222","2","2");
        List<UserInfo> users = new ArrayList<UserInfo>(){{add(tempUser1);add(tempUser2);add(tempUser3);}};
        List<DogeInfo> dogeInfos = new ArrayList<DogeInfo>(){{add(dogeInfo13);add(dogeInfo12);add(dogeInfo1);}};
        List<DogeInfo> dogeInfos1 = new ArrayList<>();
        temp.put("user",users);
        temp.put("doge",dogeInfos);
        temp.put("doge2",dogeInfos1);
        temp.put("doge3",null);
        Workbook workbook = ExcelUtils.exportExcelByMaps(temp);
        return  workbook;
    }
    public static void main(String[] args){
        System.out.print(args.toString());
        Workbook workbook = exportExcel();
        ExcelUtils.export2Path(workbook,"temp","D:/File/");
    }

  由于时间关系,写的略有仓促,请见谅,如果有什么纰漏之处,万望指正,谢谢。

 代码git地址:https://github.com/yangzan0816/ExcelExport.git

猜你喜欢

转载自blog.csdn.net/yangzan0816/article/details/78457551