java導出數據之導出Excel

報表數據展現時,常見的原則都是所見即所得。
這裏主要用到了POI及處理Excel需要jar包
完整代碼請下載查看:鏈接https://pan.baidu.com/s/1shgo4d290lnIA-ucv6qowg 提取碼:51q3

代碼相關

註解部分

/**
 * 註解類
 */
@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

結果

在這裏插入圖片描述

說明

這裏通過註解以及使用反射的方式設置表頭,以及可設置顯示順序,同時預留多語言接口,可以根據自己的需求進行擴展。但是就目前使用反射或不使用反射導出數據,在導出時間上有明顯差異。
以50w條數據爲例,僅爲個人電腦測試在這裏插入圖片描述
從下面的結果看來還是不使用反射的稍好,這裏用到反射的目的是,可以在實體中指明哪些是可以打印的數據。

都不是用反射,使用普通map記錄

平均用時11s[測試四次結果12337,10559,10578,11418]
在這裏插入圖片描述

僅表頭使用反射

平均用時約11s[測試四次結果11127,12896,11061,11584]
在這裏插入圖片描述

表頭以及內容都使用反射

平均用時約16s[測試四次結果17182,16328,17150,16891]
在這裏插入圖片描述


結束

以上僅爲個人測試,不代表真實數據,僅供參考。
如有錯誤之處,望指導。謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章