若依框架 Excel 导出多个 Sheet 页

若依框架 Excel 导出多个 Sheet 页

基于 若依 框架开发了个项目,但是在导出 Excel 的时候发现无法导出多个 Sheet 页。于是就看了下 若依 的导出工具类 ExcelUtil ,决定自己改一版。
首先网络上也有许多基于 若依 框架改版后实现导出多个 Sheet 页的实现类或者代码逻辑,看了下基本都是鸡肋,因为根本没有把灵魂逻辑实现。
为什么要用若依导出???还不是因为只要在导出的实体类配置一个 @Excel 注解,然后在注解中加入相应的属性比如 dateFormat = "yyyy-MM-dd" 再比如 dictType = "personnel_shift_type" 就能实现满足大部分业务的 Excel。
那么,为了这个好用的 @Excel 注解在导出多个 Sheet 页时能继续发扬光大,就实现了一个新的工具类 ExcelMultipleSheetsUtil
另外这个工具类我只实现了 @Excel 注解中 name、width、dateFormat、dictType 四个属性的值填充,这已经满足了大多数业务场景。但肯定有个 readConverterExp 属性很多人会用到。用这个属性还是赶紧换成 dictType 吧。与其在 readConverterExp 中配置那种 readConverterExp = "0=男,1=女,2=未知" 死值,还不如动态配置 dictType 让字典值转换更灵活。要是字典值改来改去,实体类跟着改然后再重新发布代码啥的,想着都烦 F**k!
ExcelMultipleSheetsUtil 工具类如下:

public class ExcelMultipleSheetsUtil {

    /**
     * 导出excel:可多个sheet页
     *
     * @param data          数据:Map 集合【key == 每一个sheet页的名称,value == sheet页数据】
     * @param excelFileName excel文件名
     * @param suffixName    后缀名
     * @param response      响应
     * @throws IOException 异常
     */
    public static void excelMultipleSheets(Map<String, Object> data, String excelFileName, String suffixName, HttpServletResponse response) throws IOException {
        // 创建工作簿
        try (Workbook workbook = new XSSFWorkbook()) {
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                String sheetName = entry.getKey();
                Object sheetData = entry.getValue();
                Sheet sheet = workbook.createSheet(sheetName);
                if (ObjectUtil.isNotEmpty(sheetData)) {
                    createSheetWithData(sheet, sheetData);
                }
            }

            setResponseHeader(response, excelFileName, suffixName);
            // 写出文件
            workbook.write(response.getOutputStream());
        }
    }

    /**
     * 创建表单并填充数据
     *
     * @param sheet 表单
     * @param data  数据
     */
    private static void createSheetWithData(Sheet sheet, Object data) {
        if (data instanceof List) {
            createSheetWithListData(sheet, (List<?>) data);
        } else {
            createSheetWithObjectData(sheet, data);
        }
    }

    /**
     * 创建列表类型数据对应的Excel表单
     *
     * @param sheet    表单
     * @param dataList 数据列表
     */
    private static void createSheetWithListData(Sheet sheet, List<?> dataList) {
        if (CollUtil.isNotEmpty(dataList)) {
            Object firstItem = dataList.get(0);
            createHeaderRow(sheet, firstItem.getClass());
            int rowIndex = 1;
            for (Object item : dataList) {
                createDataRow(sheet, item, rowIndex++);
            }
        }
    }

    /**
     * 创建对象类型数据对应的Excel表单
     *
     * @param sheet 表单
     * @param data  数据
     */
    private static void createSheetWithObjectData(Sheet sheet, Object data) {
        createHeaderRow(sheet, data.getClass());
        createDataRow(sheet, data, 1);
    }

    /**
     * 创建表头行
     *
     * @param sheet 表单
     * @param clazz 数据类
     */
    private static void createHeaderRow(Sheet sheet, Class<?> clazz) {
        // 创建单元格样式
        CellStyle headerCellStyle = createCellStyle(sheet.getWorkbook());

        // 创建标题行
        Row headerRow = sheet.createRow(0);
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            createHeaderCell(sheet, headerCellStyle, fields, headerRow, i);
        }
    }

    /**
     * 创建数据行
     *
     * @param sheet    表单
     * @param data     数据
     * @param rowIndex 行号
     */
    private static void createDataRow(Sheet sheet, Object data, int rowIndex) {
        // 创建单元格样式
        CellStyle dataCellStyle = createCellStyle(sheet.getWorkbook());

        // 创建数据行
        Row dataRow = sheet.createRow(rowIndex);
        Field[] fields = data.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            createDataCell(dataCellStyle, fields, dataRow, i, data);
        }
    }

    /**
     * 创建单元格样式
     *
     * @param workbook 工作簿
     * @return 单元格样式
     */
    private static CellStyle createCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();

        // 设置 水平和垂直 居中对齐
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置 上 下 左 右 边框及颜色
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());

        // 设置字体
        Font dataFont = workbook.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        cellStyle.setFont(dataFont);

        return cellStyle;
    }

    /**
     * 创建Excel表头单元格
     *
     * @param sheet           表单
     * @param headerCellStyle 单元格样式
     * @param fields          字段
     * @param headerRow       标题行
     * @param i               序号
     */
    private static void createHeaderCell(Sheet sheet, CellStyle headerCellStyle, Field[] fields, Row headerRow, int i) {
        // 默认宽度
        double width = 16;
        Excel excelAnnotation = fields[i].getAnnotation(Excel.class);
        if (excelAnnotation != null && !ObjectUtil.isEmpty(excelAnnotation.width())) {
            width = excelAnnotation.width();
        }

        // 设置宽度
        sheet.setColumnWidth(i, (int) ((width + 0.72) * 256));

        if (excelAnnotation != null) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(excelAnnotation.name());
            cell.setCellStyle(headerCellStyle);
        }
    }

    /**
     * 创建Excel数据单元格
     *
     * @param dataCellStyle 单元格样式
     * @param fields        字段
     * @param dataRow       数据行
     * @param i             序号
     * @param data          数据
     */
    private static void createDataCell(CellStyle dataCellStyle, Field[] fields, Row dataRow, int i, Object data) {
        Cell cell = dataRow.createCell(i);
        cell.setCellStyle(dataCellStyle);

        try {
            fields[i].setAccessible(true);
            Object value = fields[i].get(data);
            handleAnnotationAndSetValue(cell, fields[i], value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理注解并设置单元格值
     *
     * @param cell  单元格
     * @param field 字段
     * @param value 值
     */
    private static void handleAnnotationAndSetValue(Cell cell, Field field, Object value) {
        if (field.isAnnotationPresent(Excel.class) && field.getAnnotation(Excel.class).dictType().length() > 0) {
            value = DictUtils.getDictLabel(field.getAnnotation(Excel.class).dictType(), String.valueOf(value));
        }
        if (field.isAnnotationPresent(Excel.class) && StrUtil.isNotEmpty(field.getAnnotation(Excel.class).dateFormat())) {
            value = DateUtil.format(Convert.convert(Date.class, value), field.getAnnotation(Excel.class).dateFormat());
        }
        cell.setCellValue(ObjectUtil.isEmpty(value) ? null : value.toString());
    }

    /**
     * 设置响应头
     *
     * @param response      响应
     * @param excelFileName 文件名
     * @param suffixName    后缀名
     * @throws UnsupportedEncodingException 编码异常
     */
    private static void setResponseHeader(HttpServletResponse response, String excelFileName, String suffixName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(excelFileName + suffixName, UTF_8));
    }

}

使用示例

public Map<String, Object> getMapTest(CommonBo bo) {
        Map<String, Object> result = new HashMap<>();
        Boolean isPage = bo.getIsPage();
        result.put(isPage ? "sheet1" : "sheet1名字", this.baseMapper.selectDriverProfile(bo));
        result.put(isPage ? "sheet2" : "sheet2名字", this.baseMapper.selectTrafficViolation(bo));
        result.put(isPage ? "sheet3" : "sheet3名字", this.baseMapper.selectSafetyAccident(bo));
        if (!isPage) {
            ExcelMultipleSheetsUtil.excelMultipleSheets(result, "Excel数据" + DateUtil.format(new Date(), "yyyyMMddHHmmss"), XLSX_SUFFIX, response);
        }
        return result;
    }
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值