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

来源:互联网 发布:苹果音乐软件 itunes 编辑:程序博客网 时间:2024/05/21 10:32

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

  工作中我们可能会遇到要将多个对象作为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@AllArgsConstructorpublic 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@AllArgsConstructorpublic 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

阅读全文
0 0
原创粉丝点击