自定義註解導出Excel,可導出多個Sheet

1、定義 @ExcelCol 註解

package com.ly.education.elective.api.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 *
 * FIELD:用於描述域
 * RUNTIME: 在運行時有效(即運行時保留)
 * @auther: fly
 * @date: 2019/10/5 10:59
 * @param:
 * @return:
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelCol {

    /**
     * 列名稱
     * @return
     */
    String name() default "";

    /**
     * 列寬度
     * @return
     */
    int length() default 15;

    /**
     * 列排序
     * @return
     */
    int colNum() default 0;

}

2、創建 ExcelUtil 工具類

package com.ly.education.elective.server.utils;

import com.ly.education.elective.api.annotation.ExcelCol;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @ClassName ExcelUtils
 * @Description:
 * @Author fly
 * @Date 2019/10/5 9:40
 */
@Slf4j
public class ExcelUtils {

    /**
     * 文件後綴名: .xls
     */
    private final static String EXCEL2003 = "xls";

    /**
     * 文件後綴名: .xlsx
     */
    private final static String EXCEL2007 = "xlsx";

    /**
     *
     * 功能描述: 導出 excel
     * @auther: fly
     * @date: 2019/10/5 11:12
     * @param: response     HttpServletResponse
     * @param: dataList        每個sheet數據源集合
     * @param: titleNameList    title 標題集合名稱
     * @param: sheetNameList    sheet 集合名稱
     * @param: cls    實體類
     * @param: filePath    導出 excel 文件路徑
     * @return:
     */
    public static <T> void exportExcel(HttpServletResponse response, List<List<T>> dataList, List<String> titleNameList,
                                       List<String> sheetNameList, Class<T> cls, String filePath) {
        // 該類屬性數組
        Field[] fields = cls.getDeclaredFields();

        // 應用了 @ExcelCol 註解的屬性, 且 colNum 大於 0 的屬性集合
        List<Field> fieldList = Arrays.stream(fields)
                .filter(field -> {
                    ExcelCol annotation = field.getAnnotation(ExcelCol.class);
                    // 該屬性有引用該註解, 且列排序號大於 0
                    if (annotation != null && annotation.colNum() > 0) {
                        // 當該字段用 private 修飾時 isAccessible() 得到的值是 false, 必須要改成 true 纔可以訪問
                        field.setAccessible(true);
                        return true;
                    }
                    return false;
                }).sorted(Comparator.comparing(field -> {
                    int col = 0;
                    ExcelCol annotation = field.getAnnotation(ExcelCol.class);
                    if (annotation != null) {
                        col = annotation.colNum();
                    }
                    return col;
                })).collect(Collectors.toList());

        Workbook workbook = new XSSFWorkbook();

        if (CollectionUtils.isNotEmpty(dataList)) {
            AtomicInteger ak = new AtomicInteger();
            // 循環 sheet
            dataList.forEach(list -> {
                // sheet 名稱
                String sheetName = "";
                int akIndex = ak.getAndIncrement();
                if (sheetNameList != null && akIndex < sheetNameList.size()) {
                    sheetName = sheetNameList.get(akIndex);
                } else {
                    sheetName = "sheet" + akIndex;
                }
                Sheet sheet = workbook.createSheet(sheetName);
                AtomicInteger ai = new AtomicInteger();

                // excel 標題
                if (titleNameList != null && akIndex < titleNameList.size()) {
                    // 創建合併單元格
                    CellRangeAddress region = new CellRangeAddress(0, 0, 0, fieldList.size() - 1);
                    // 在 sheet 裏增加合併單元格
                    sheet.addMergedRegion(region);
                    Row titleRow = sheet.createRow(ai.getAndIncrement());

                    Cell cell = titleRow.createCell(0);

                    CellStyle cellStyle = workbook.createCellStyle();

                    // 水平居中
                    cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
                    // 垂直居中
                    cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);

                    Font font = workbook.createFont();
                    font.setBoldweight(Font.BOLDWEIGHT_BOLD);
                    font.setFontHeightInPoints((short) 20);
                    cellStyle.setFont(font);

                    String titleName = "";
                    if (titleNameList != null && akIndex < titleNameList.size()) {
                        titleName = titleNameList.get(akIndex);
                    } else {
                        titleName = "標題";
                    }

                    cell.setCellStyle(cellStyle);
                    cell.setCellValue(titleName);
                }

                // 列標題
                {
                    // 創建新的一行
                    Row row = sheet.createRow(ai.getAndIncrement());
                    AtomicInteger aj = new AtomicInteger();
                    // 寫入標題
                    fieldList.forEach(field -> {
                        ExcelCol annotation = field.getAnnotation(ExcelCol.class);
                        String columnName = "";
                        if (annotation != null) {
                            columnName = annotation.name();
                            sheet.setColumnWidth(annotation.colNum() - 1, annotation.length() * 256);
                        }
                        // 創建新的一列
                        Cell cell = row.createCell(aj.getAndIncrement());

                        CellStyle cellStyle = workbook.createCellStyle();
                        // 水平居中
                        cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
                        // 垂直居中
                        cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);


                        Font font = workbook.createFont();
                        // 字體
                        font.setBoldweight(Font.BOLDWEIGHT_BOLD);
                        cellStyle.setFont(font);

                        // 列樣式
                        cell.setCellStyle(cellStyle);
                        // 列名稱
                        cell.setCellValue(columnName);
                    });
                }

                // 循環數據集合
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(t -> {
                        // 創建新的一行
                        Row row1 = sheet.createRow(ai.getAndIncrement());
                        AtomicInteger aj = new AtomicInteger();

                        // 循環屬性集合
                        fieldList.forEach(field -> {
                            // 屬性類型
                            Class<?> type = field.getType();
                            Object value = "";
                            try {
                                // 屬性值
                                value = field.get(t);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                            Cell cell = row1.createCell(aj.getAndIncrement());

                            CellStyle cellStyle = workbook.createCellStyle();
                            // 水平居中
                            cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
                            // 垂直居中
                            cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);

                            cell.setCellStyle(cellStyle);
                            if (value != null) {
                                // 如果屬性類型爲 Date
                                if (type == Date.class) {
                                    cell.setCellValue(value.toString());
                                } else {
                                    cell.setCellValue(value.toString());
                                }
                            }
                        });
                    });
                }
            });
        }

        String sheet = "";
        if (sheetNameList != null && !sheetNameList.isEmpty()) {
            sheet = sheetNameList.get(0);
        } else {
            sheet = "sheet0";
        }
        // 瀏覽器下載 excel
        buildExcelDocument("abbot.xlsx", workbook, response, filePath);
    }

    /**
     *
     * 功能描述: 瀏覽器下載 Excel
     * @auther: fly
     * @date: 2019/10/5 11:40
     * @param:
     * @return:
     */
    private static void buildExcelDocument(String fileName, Workbook workbook, HttpServletResponse response, String filePath) {
        try {

            FileOutputStream outputStream = new FileOutputStream(filePath);
            workbook.write(outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

3、在實體類的屬性上標上註解

package com.ly.education.elective.api.vo;

import com.ly.education.elective.api.annotation.ExcelCol;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

/**
 * @author fly
 *
 */
@Getter
@Setter
@ToString
public class CourseSelectionListVo implements Serializable {

    /**
     * 序列號
     */
    private static final long serialVersionUID = -9003609292510835997L;

    /**
     * 學生學號
     */
    @ExcelCol(name = "學號", colNum = 1)
    private String studentCode;

    /**
     * 學生姓名
     */
    @ExcelCol(name = "姓名", colNum = 2)
    private String studentName;

    /**
     * 學生行政班級名稱
     */
    @ExcelCol(name = "行政班級", colNum = 5)
    private String administrativeClassName;

    /**
     * 專業名稱
     */
    @ExcelCol(name = "年級專業", colNum = 4, length = 25)
    private String gradeMajorName;

    /**
     * 學生學院名稱
     */
    @ExcelCol(name = "學院", colNum = 3)
    private String studentDepartmentName;

     
}

 

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