poi導出excel工具類+注解


導出excel作為很多頁面的常用功能,但是不同頁面導出的數據內容和字段不一,不方便操作,本文通過注解和工具類來解決excel通用導出問題

1.注解

通過注解來定義excel字段的名稱,排序和日期格式

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

    /**
     * excel列名
     */
    String value() default "";

    /**
     * 排序
     */
    int sort() default 0;

    /**
     * 日期格式
     */
    String dateFormat() default "";
}

2.實體

定義要導出的數據實體,要導出的字段上加上注解

@Data
public class DataVO {
    /**
     * 設備編號
     */
    @ExcelField(value = "設備編號", sort = 1)
    private String deviceNo;
    /**
     * 創建時間
     */
    @ExcelField(value = "日期", sort = 2, dateFormat = "yyyy-MM-dd")
    private Date createTime;
}

3.導出入口函數

public static <T> void getExcelDate(String title, List<T> list, HttpServletRequest request, HttpServletResponse response) {
        //獲取導出數據
        List<Map<String, Object>> list2 = DataUtil.getModelExcelFields(list);
        // 列名
        Map<String, String[]> map = DataUtil.getModelExcelFieldsToArray(list.get(0).getClass());
        String[] column = map.get("array");
        String[] columnName = map.get("arrayName");
        // 把數據綁定到對應的字段下
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        for (int i = 0; i < list2.size(); i++) {
            objs = new Object[columnName.length];
            for (int j = 0; j < columnName.length; j++) {
                objs[j] = list2.get(i).get(column[j]);
            }
            dataList.add(objs);
        }
        exportExcel(title, columnName, dataList, request, response);
    }

4.獲取導出數據

實體類中標記了注解的字段才會導出,根據反射獲取字段類型和值,其中Date類型的數據轉換成String類型時,通過注解的日期格式來格式化日期

public static <T> List<Map<String, Object>> getModelExcelFields(List<T> models) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (!models.isEmpty()) {
            for (T model : models) {
                Map<String, Object> map = new HashMap<>(16);
                // 獲取實體類的所有屬性,返回Field數組
                Field[] fields = model.getClass().getDeclaredFields();
                try {
                    // 遍歷所有屬性
                    for (Field field : fields) {
                        ExcelField anno = field.getAnnotation(ExcelField.class);
                        if (anno == null) {
                            continue;
                        }
                        // 獲取屬性的名字
                        String fieldName = field.getName();
                        // 將屬性的首字符大寫,方便構造get,set方法
                        String name = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                        // 獲取屬性的類型
                        String type = field.getGenericType().toString();
                        // 如果type是類類型,則前面包含"class ",后面跟類名
                        if ("class java.lang.String".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            // 調用getter方法獲取屬性值
                            String value = (String) m.invoke(model);
                            if (value != null && (!"".equals(value))) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("int".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            int value = (int) m.invoke(model);
                            map.put(name, value);
                            continue;
                        }
                        if ("double".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            double value = (double) m.invoke(model);
                            map.put(name, value);
                            continue;
                        }
                        if ("class java.lang.Double".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Double value = (Double) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("class java.math.BigDecimal".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            BigDecimal value = (BigDecimal) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("class java.lang.Boolean".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Boolean value = (Boolean) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("long".equals(type) && !("SerialVersionUID".equals(name))) {
                            Method m = model.getClass().getMethod("get" + name);
                            long value = (long) m.invoke(model);
                            if (value != 0) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("class java.lang.Long".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Long value = (Long) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("class java.util.Date".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Date value = (Date) m.invoke(model);
                            String date = null;
                            if (value != null) {
                                try {
                                    if (StringUtil.isNotEmpty(anno.dateFormat())) {
                                        date = DateTools.formatDate(value, anno.dateFormat());
                                    } else {
                                        date = DateTools.formatDate(value, DateTools.DATE_PATTERN_DEFAULT);
                                    }
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                map.put(name, date);
                            }
                            continue;
                        }
                        if ("class java.lang.Integer".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Integer value = (Integer) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                            continue;
                        }
                        if ("class java.lang.Short".equals(type)) {
                            Method m = model.getClass().getMethod("get" + name);
                            Short value = (Short) m.invoke(model);
                            if (value != null) {
                                map.put(name, value);
                            }
                        }
                    }
                } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    e.printStackTrace();
                }
                list.add(map);
            }
        }
        return list;
    }
View Code

5.獲取列名

實體類中標記了注解的字段才會導出,根據注解的sort進行列的排序

public static Map<String, String[]> getModelExcelFieldsToArray(Class clazz) {
        Map<String, String[]> map = new HashMap<>(16);
        // 獲取實體類的所有屬性,返回Field數組
        Field[] fields = clazz.getDeclaredFields();
        List<String> list = new ArrayList<>();
        List<String> listName = new ArrayList<>();
        // 遍歷所有屬性
        Arrays.stream(fields).filter(field -> {
            ExcelField anno = field.getAnnotation(ExcelField.class);
            return anno != null;
        }).sorted(Comparator.comparing(field -> {
            ExcelField anno = field.getAnnotation(ExcelField.class);
            return anno.sort();
        })).forEach(field -> {
            ExcelField anno = field.getAnnotation(ExcelField.class);
            // 獲取屬性的名字
            String fieldName = field.getName();
            // 將屬性的首字符大寫,方便構造get,set方法
            String name = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            list.add(name);
            listName.add(anno.value());
        });
        String[] array = new String[list.size()];
        String[] arrayName = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            array[i] = list.get(i);
            arrayName[i] = listName.get(i);
        }
        map.put("array", array);
        map.put("arrayName", arrayName);
        return map;
    }

6.生成excel文件導出

public static void exportExcel(String title, String[] columnName, List<Object[]> dataList, HttpServletRequest request,
            HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        // 實例化工具類
        ExportExcel ex = new ExportExcel(title, columnName, dataList, request, response);
        try {
            // 導出excel
            ex.export(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

public void export(String path) throws Exception {
        try {
            HSSFWorkbook workbook = getWorkbook();
            String fileName = title + "_" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
            String headStr = "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"";
            if (StringUtil.isNull(path)) {
                try {
                    response.setContentType("application/octet-stream");
                    response.setHeader("Content-Disposition", headStr);
                    OutputStream out1 = response.getOutputStream();
                    workbook.write(out1);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                //判斷是否存在目錄. 不存在則創建
                if (!FileUtil.exists(path)) {
                    FileUtil.createFolder(path);
                }
                //輸出Excel文件
                FileOutputStream out1 = new FileOutputStream(path + File.separator+ fileName);
                workbook.write(out1);
                out1.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

private HSSFWorkbook getWorkbook() {
        // 創建工作簿對象
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 創建工作表
        HSSFSheet sheet = workbook.createSheet(title);

        // 產生表格標題行
        HSSFRow rowm = sheet.createRow(0);
        HSSFCell cellTiltle = rowm.createCell(0);

        //設置標題和單元格樣式
        //獲取列頭樣式對象
        HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
        //單元格樣式對象
        HSSFCellStyle style = this.getStyle(workbook);

        //合並單元格
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (columnName.length)));
        cellTiltle.setCellStyle(columnTopStyle);
        cellTiltle.setCellValue(title);

        // 定義所需列數
        int columnNum = columnName.length + 1;
        // 在索引2的位置創建行(最頂端的行開始的第二行)
        HSSFRow rowRowName = sheet.createRow(2);


        // 將列頭設置到sheet的單元格中
        for (int n = 0; n < columnNum; n++) {
            if (n == 0) {
                //創建列頭對應個數的單元格
                HSSFCell cellRowName = rowRowName.createCell(n);
                //設置列頭單元格的數據類型
                cellRowName.setCellType(CellType.STRING);
                //設置列頭單元格的值
                cellRowName.setCellValue("序號");
                //設置列頭單元格樣式
                cellRowName.setCellStyle(columnTopStyle);
            } else {
                //創建列頭對應個數的單元格
                HSSFCell cellRowName = rowRowName.createCell(n);
                //設置列頭單元格的數據類型
                cellRowName.setCellType(CellType.STRING);
                HSSFRichTextString text = new HSSFRichTextString(columnName[n - 1]);
                //設置列頭單元格的值
                cellRowName.setCellValue(text);
                //設置列頭單元格樣式
                cellRowName.setCellStyle(columnTopStyle);
            }
        }

        //將查詢出的數據設置到sheet對應的單元格中
        for (int i = 0; i < dataList.size(); i++) {
            //遍歷每個對象
            Object[] obj = dataList.get(i);
            //創建所需的行數
            HSSFRow row = sheet.createRow(i + 3);
            for (int j = 0; j < obj.length + 1; j++) {
                //設置單元格的數據類型
                HSSFCell cell;
                if (j == 0) {
                    cell = row.createCell(j, CellType.NUMERIC);
                    cell.setCellValue(i + 1);
                } else {
                    //其余列都為字符串類型並設置單元格的值
                    cell = row.createCell(j, CellType.STRING);
                    if (!"".equals(obj[j - 1]) && obj[j - 1] != null) {
                        cell.setCellValue(obj[j - 1].toString());
                    } else {
                        cell.setCellValue(" ");
                    }
                }
                //設置單元格樣式
                cell.setCellStyle(style);
            }
        }


        //讓列寬隨着導出的列長自動適應
        for (int colNum = 0; colNum < columnNum; colNum++) {
            int columnWidth = sheet.getColumnWidth(colNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                HSSFRow currentRow;
                //當前行未被使用過
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }
                if (currentRow.getCell(colNum) != null) {
                    //取得當前的單元格
                    HSSFCell currentCell = currentRow.getCell(colNum);
                    //如果當前單元格類型為字符串
                    if (currentCell.getCellType() == CellType.STRING) {
                        int length = currentCell.getStringCellValue().getBytes().length;
                        if (columnWidth < length) {
                            //將單元格里面值大小作為列寬度
                            columnWidth = length;
                        }
                    }
                }
            }
            //再根據不同列單獨做下處理
            if (colNum == 0) {
                sheet.setColumnWidth(colNum, (columnWidth - 2) * 200);
            } else {
                if (columnWidth < 252) {
                    sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
                } else {
                    sheet.setColumnWidth(colNum, 6000);
                }
            }
        }
        return workbook;
    }
View Code

至此,導出完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM