报表数据展现时,常见的原则都是所见即所得。
这里主要用到了POI及处理Excel需要jar包
完整代码请下载查看:链接https://pan.baidu.com/s/1shgo4d290lnIA-ucv6qowg 提取码:51q3


文章目录

  • 代码相关
  • 注解部分
  • 实体部分
  • 导出excel核心部分
  • 完整代码请下载查看
  • 结果
  • 说明
  • 都不是用反射,使用普通map记录
  • 仅表头使用反射
  • 表头以及内容都使用反射
  • 结束


代码相关

注解部分

/**
 * 注解类
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface FileName {
    public String defaulename() default "";//显示表头默认名称
    public String languageid() default "";//显示表头对应多语言id,支持多语言的情况下
}

实体部分

/**
 * 用户实体类
 */
class User {
    @FileName(defaulename = "名称", languageid = "")
    public String username;
    @FileName(defaulename = "电话", languageid = "")
    public String mobilenumber;
    @FileName(defaulename = "年龄", languageid = "")
    public Integer age;
    @FileName(defaulename = "邮箱", languageid = "")
    public String em;
    @FileName(defaulename = "其他测试", languageid = "")
    public String othertest;

    public static User getUser() {
        User user = new User();
        user.setUsername("百川" + (int) (Math.random() * 100));
        user.setAge((int) (Math.random() * 100));
        user.setMobilenumber("+86 173" + Math.random() * 100);
        user.setEm((int) (Math.random() * 1000) + "@cc.com");
        user.setOthertest("其他参数测试");
        return user;

    }
    public User() {    }
    public String getOthertest() {        return othertest;    }
    public void setOthertest(String othertest) {        this.othertest = othertest;    }
    public String getUsername() {        return username;    }
    public void setUsername(String username) {        this.username = username;    }
    public String getMobilenumber() {        return mobilenumber;    }
    public void setMobilenumber(String mobilenumber) {        this.mobilenumber = mobilenumber;    }
    public Integer getAge() {        return age;    }
    public void setAge(Integer age) {        this.age = age;    }
    public String getEm() {        return em;    }
    public void setEm(String em) {        this.em = em;    }
}

导出excel核心部分

public void writeExcel(String docname, List<User> users) {
        if (users == null || users.isEmpty()) return;//无数据
        long createtime = new Date().getTime();
        int row = 0;

        HSSFWorkbook wb = new HSSFWorkbook();//创建exe表格
        HSSFSheet sheet = wb.createSheet(docname);//创建工作簿
        try {
            HSSFRow titlerow = sheet.createRow(row++);//创建首行
            boolean hastable = setTableTitle(titlerow, users.get(0));
            if (!hastable) return;//说明首行没有,这个情况说明你的bean对象都不支持导出
            //设置内容
            for (User user : users) {
                HSSFRow valuerow = sheet.createRow(row++);
                setTableBody(valuerow, user);
                if (row % EXECL_MAXNUM == 0) {//需要重新创建工作簿
                    row = 0;
                    sheet = wb.createSheet(docname + "-" + wb.getNumberOfSheets());//创建工作簿
                    titlerow = sheet.createRow(row++);//创建首行
                    setTableTitle(titlerow, users.get(0));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            FileOutputStream os = new FileOutputStream("D:/mywebsit/" + docname + EXECL_TYPE);
            wb.write(os);
            os.flush();
            os.close();
            System.out.println("success");
        } catch (Exception e) {
            System.err.println(e);
        }
        long endtime = new Date().getTime();
        System.out.println("user times " + (endtime - createtime) + "(ms)");
    }
    /**
     * 这里需要传递一个bean对象
     *
     * @param titlerow
     * @param obj
     */
    public boolean setTableTitle(HSSFRow titlerow, Object obj) {
        int col = -1;
        boolean hastitle = false;//用于判断是否有表头
        Field[] fields = obj.getClass().getDeclaredFields();//前面已经保证了一定有数据
        for (Field field : fields) {//用于遍历创建表头
            if (canWriterFileName(field.getAnnotations())) {
                titlerow.createCell(++col).setCellValue(field.getAnnotation(FileName.class).defaulename());//创建单元格
                hastitle = true;
            }
        }
        return hastitle;
    }

    /**
     * 设置表格中的内容
     */
    public void setTableBody(HSSFRow valuerow, Object obj) throws Exception {
        int col = -1;
        Class objClass = obj.getClass();
        Field[] fields = objClass.getDeclaredFields();
        for (Field field : fields) {//用于遍历创建表头
            if (canWriterFileName(field.getAnnotations())) {
                String fieldname = field.getName();
                fieldname = "get" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);//注意这里需要get方法名称规范
                valuerow.createCell(++col).setCellValue(objClass.getMethod(fieldname).invoke(obj).toString());//创建单元格
            }
        }
    }

完整代码请下载查看

链接:https://pan.baidu.com/s/1shgo4d290lnIA-ucv6qowg
提取码:51q3

结果

java 实现excel的复杂导出 java导出excel数据_java导出表格数据

说明

这里通过注解以及使用反射的方式设置表头,以及可设置显示顺序,同时预留多语言接口,可以根据自己的需求进行扩展。但是就目前使用反射或不使用反射导出数据,在导出时间上有明显差异。

以50w条数据为例,仅为个人电脑测试

java 实现excel的复杂导出 java导出excel数据_java 实现excel的复杂导出_02


从下面的结果看来还是不使用反射的稍好,这里用到反射的目的是,可以在实体中指明哪些是可以打印的数据。

都不是用反射,使用普通map记录

平均用时11s[测试四次结果12337,10559,10578,11418]

java 实现excel的复杂导出 java导出excel数据_java 实现excel的复杂导出_03

仅表头使用反射

平均用时约11s[测试四次结果11127,12896,11061,11584]

java 实现excel的复杂导出 java导出excel数据_java导出表格数据_04

表头以及内容都使用反射

平均用时约16s[测试四次结果17182,16328,17150,16891]

java 实现excel的复杂导出 java导出excel数据_java生成excel数据_05


结束

以上仅为个人测试,不代表真实数据,仅供参考。
如有错误之处,望指导。谢谢