基于easyexcel实现导出excel,包括导出图片以及导出下拉框

发布时间:2024年01月19日

基于easyexcel实现导出excel,包括导出图片以及导出下拉框

1.最基本的导出excel

1.引入maven

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>

2.写一个样式工具类

package com.electronic.web.controller.studyEasyExcelExport;

import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;

/**
 * 导出excel样式罢了
 */
public class ExcelStyleUtils {
    public static HorizontalCellStyleStrategy getStyle() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 15);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 13);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //导出数据水平居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
}

3.写一个导出的实体

package com.electronic.web.controller.studyEasyExcelExport;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;


@Getter
@Setter
@ToString
@HeadFontStyle(fontHeightInPoints = 10)
@HeadRowHeight(20)
public class WorkOrderExcelExportVO {

    @ExcelProperty(value = "派单时间",order = 2)
    @ColumnWidth(22)
    private String orderTime;

    @ExcelProperty(value = "标题",order = 1)
    @ColumnWidth(25)
    private String title;

    @ExcelProperty(value = "工单编号",order = 0)
    @ColumnWidth(25)
    private String orderNo;

    @ExcelProperty(value = "分类",order = 4)
    @ColumnWidth(15)
    private String eventTypeName;

    @ExcelProperty(value = "事件内容",order = 6)
    @ColumnWidth(25)
    private String content;

    @ExcelProperty(value = "事件地址",order = 7)
    @ColumnWidth(25)
    private String address;

    @ExcelProperty(value = "类型",order = 5)
    @ColumnWidth(15)
    private String appealTypeName;

    @ExcelProperty(value = "承办单位",order = 8)
    @ColumnWidth(20)
    private String deptName;

    @ExcelProperty(value = "承办状态",order = 9)
    @ColumnWidth(20)
    private String mainState;

    @ExcelProperty(value = "办理期限",order = 3)
    @ColumnWidth(22)
    private String handleTime;
}

4.写控制层

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;


@RestController
@RequestMapping("/easyexcel/test")
@Slf4j
public class TestEasyExcelController {

    @PostMapping("export/xlsx")
    public ResponseEntity<InputStreamResource> exportXlsx() {
        final Path tempWordPath = exportExcel();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDisposition(
                ContentDisposition
                        .attachment()
                        .filename("***汇总表.xlsx", StandardCharsets.UTF_8)
                        .build());
        try {
            final InputStream in = Files.newInputStream(tempWordPath, StandardOpenOption.DELETE_ON_CLOSE);
            return new ResponseEntity<>(new InputStreamResource(in, "***汇总表.xlsx"), headers, HttpStatus.OK);
        } catch (IOException e) {
            throw new IllegalStateException("文件导出失败..", e);
        }
    }
}

5.写业务层

也就是上面的exportExcel();这个方法

   //下面可以理解为业务层的东西 应该是放在业务层去写的
    public Path exportExcel() {
        //根据条件查询指定数据 注释掉的知识业务罢了
//        Set<Long> orderIdSet;
//        if (null != commandPageParam.getMainDeptId()) if (!DEPT_OPT_SECTION.equals(commandPageParam.getMainDeptId()))
//            orderIdSet = workOrderInfoRepository.selectOrderIdSetByDeptId(commandPageParam.getMainDeptId(), Boolean.TRUE);
//        else
//            orderIdSet = workOrderInfoRepository.selectOrderIdSetByDeptId(commandPageParam.getMainDeptId(), Boolean.FALSE);
//        else
//            orderIdSet = workOrderInfoRepository.selectOrderIdSetByDeptId(commandPageParam.getCurrentDeptId(), Boolean.FALSE);
//        commandPageParam.setOrderIdSet(orderIdSet);
        //        final List<WorkOrderExcelExportVO> exportList = workOrderInfoRepository.selectExcelExportData(commandPageParam);
        // 创建一个包含十行假数据的 List   模拟查出来数据
        List<WorkOrderExcelExportVO> exportList = new ArrayList<>();

        // 添加十行假数据到 exportList
        for (int i = 1; i <= 10; i++) {
            WorkOrderExcelExportVO workOrder = new WorkOrderExcelExportVO();
            workOrder.setOrderTime("2023-07-19");
            workOrder.setTitle("标题" + i);
            workOrder.setOrderNo("工单编号" + i);
            workOrder.setEventTypeName("分类" + i);
            workOrder.setContent("事件内容" + i);
            workOrder.setAddress("事件地址" + i);
            workOrder.setAppealTypeName("类型" + i);
            workOrder.setDeptName("承办单位" + i);
            workOrder.setMainState("承办状态" + i);
            workOrder.setHandleTime("办理期限" + i);
            exportList.add(workOrder);
        }

        log.info("当前共有{}条数据", exportList.size());
        final Path tempPath;
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = ExcelStyleUtils.getStyle();
        try {
            tempPath = Files.createTempFile("workorder", ".xlsx");
            EasyExcel.write(tempPath.toFile(), WorkOrderExcelExportVO.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .sheet("***派单汇总表66")
                    .doWrite(exportList);
        } catch (IOException e) {
            throw new IllegalStateException("文件导出失败, 可能为磁盘空间不足", e);
        }
        return tempPath;
    }

6.自测通过(截图)

在这里插入图片描述

2. 在1基础上导出带图片的excel

1.实体的改动

@Getter
@Setter
@ToString(callSuper = true)
@ContentRowHeight(120)
public class RoadCheckExcelExportVO {

    //查出来的图片url
    @ExcelProperty(value="附件图片",converter = SxjgUrlImageConverter.class, order=11)
    @ColumnWidth(30)
    private String disposeUrl;
    @ExcelProperty(value = "序号",order = 0)
    @ColumnWidth(15)
    private Integer index;

2.自定义的图片转换器 SxjgUrlImageConverter

package com.safesoft.domain.check.vo;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.IoUtils;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;

/**
 * [自定义 图片 转换器,根据图片的url将图片导入到表格中。]
 *
 * @author Kevin.Wan
 * @date 2024/1/19
 **/
public class SxjgUrlImageConverter implements Converter<String> {


    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
                                               GlobalConfiguration globalConfiguration) throws IOException {
        InputStream inputStream = null;
        try {
            if (ObjectUtils.isEmpty(value)) {
                return new WriteCellData<>("图片链接为空");
            }

            // Assuming the value is a relative path
            String absolutePath = getAbsolutePath(value);
            File file = new File(absolutePath);

            if (!file.exists()) {
                return new WriteCellData<>("图片文件不存在");
            }

            inputStream = new FileInputStream(file);
            byte[] bytes = IoUtils.toByteArray(inputStream);
            return new WriteCellData<>(bytes);
        } catch (Exception e) {
            return new WriteCellData<>("图片获取异常");
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * 获取图片的真实路径
     *  
     * @param relativePath 图片路径
     * @return 真实路径
     */
    private String getAbsolutePath(String relativePath) {
        //因为我的图片 数据库存的地址 例如  store/af9227eaada9b744c950de869327adf7.jpg
        //实际上我存放的位置是在    当前项目的根目录,上一级attachments的下面 ,就是为了能找到图片
        final String fileBaseDir = "../attachments";
        final Path storeDirPath = FileSystems.getDefault().getPath(fileBaseDir);

        return storeDirPath.resolve(relativePath).toString();
    }
}

3.效果图

在这里插入图片描述

3. 在1基础上导出下拉框,并且下拉框进行数据校验

3.1 实体的改动

package com.safesoft.domain.keysupervisionvehicle.vo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.safesoft.domain.keysupervisionvehicle.impl.DepartmentConverter;
import com.safesoft.domain.keysupervisionvehicle.impl.PlateColorConverter;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * [重点监测车辆导入模板实体]
 *
 * @author Kevin.Wan
 * @date 2024/1/11
 **/
@Getter
@Setter
@ToString
public class KeySupervisionVehicleExport {

  
    /**
     * 车牌号
     */
    @ExcelProperty(value = "车牌号",order = 1)
    @ColumnWidth(25)
    private String plateNum;

    /**
     * 车牌颜色
     *  车牌颜色只能是order = 2  如果这里修改,KeySupervisionVehicleSheetWriteHandler这个类的车牌颜色下拉框也要修改
     */
    @ExcelProperty(value = "车牌颜色",converter = PlateColorConverter.class,order = 2)
    @ColumnWidth(25)
    private String plateColor;

    /**
     * 挂车车牌
     */
    @ExcelProperty(value = "挂车车牌",order = 3)
    @ColumnWidth(25)
    private String trailerPlateNum;

    /**
     * 挂车车牌颜色
     *  车牌颜色只能是order = 4  如果这里修改,KeySupervisionVehicleSheetWriteHandler这个类的车牌颜色下拉框也要修改
     */
    @ExcelProperty(value = "挂车车牌颜色",converter = PlateColorConverter.class,order = 4)
    @ColumnWidth(25)
    private String trailerPlateColor;

3.2 车牌颜色的转换器PlateColorConverter

package com.safesoft.domain.keysupervisionvehicle.impl;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.safesoft.domain.keysupervisionvehicle.entity.PlateColorEnum;

/**
 * [自定义 Excel 转换器,用于将车牌颜色的标识转换为对应的参数表plate-color的code。]
 *
 * @author Kevin.Wan
 * @date 2024/1/17
 **/
public class PlateColorConverter implements Converter<String> {

    /**
     * 返回支持的 Java 类型
     *
     * @return Java 类型
     */
    @Override
    public Class<String> supportJavaTypeKey() {
        return String.class;
    }

    /**
     * 返回支持的 Excel 类型
     *
     * @return Excel 类型
     */
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }


    /**
     * 将 Excel 数据转换为 Java 数据 (将车牌颜色名称转换为车牌颜色code)
     *
     * @param context 转换上下文
     * @return Java 数据
     */
    @Override
    public String convertToJavaData(ReadConverterContext<?> context) {
        return PlateColorEnum.getPlateColorCode(context.getReadCellData().getStringValue());
    }

    /**
     * 将 Java 数据转换为 Excel 数据 (将车牌颜色code转换为车牌颜色名称)
     *
     * @param context 转换上下文
     * @return Excel 数据
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
        return new WriteCellData<>(PlateColorEnum.getPlateColorName(context.getValue()));
    }

}

3.3 业务层的改动

public Path downloadTemplate() {
    LOGGER.info("导入模板下载");

    final List<KeySupervisionVehicleExport> keySupervisionVehicleExportList = Collections.emptyList();

    final Path tempPath;
    HorizontalCellStyleStrategy horizontalCellStyleStrategy = ExcelStyleUtils.getStyle();
    try {
        tempPath = Files.createTempFile("keySupervisionVehicleExport", ".xlsx");
        EasyExcelFactory.write(tempPath.toFile(), KeySupervisionVehicleExport.class)
                .registerWriteHandler(horizontalCellStyleStrategy)
                //添加头     *****************改动点******************
                .head(KeySupervisionVehicleExport.class)
                //派单中队下拉框数据校验处理器 *****************改动点******************
                .registerWriteHandler(new KeySupervisionVehicleSheetWriteHandler())
                .sheet("****导入模板表")
                .doWrite(keySupervisionVehicleExportList);
    } catch (IOException e) {
        throw new IllegalStateException("文件导出失败, 可能为磁盘空间不足", e);
    }
    return tempPath;
}

3.4 下拉框数据校验处理器KeySupervisionVehicleSheetWriteHandler

package com.safesoft.domain.keysupervisionvehicle.impl;


import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * [自定义的SheetWriteHandler实现类,用于在Excel中添加下拉框,并进行数据验证]
 *
 * @author Kevin.Wan
 * @date 2024/1/12
 **/
public class KeySupervisionVehicleSheetWriteHandler implements SheetWriteHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(KeySupervisionVehicleSheetWriteHandler.class);

    /**
     * 派单中队下拉框开始列的索引
     */
    private static final Integer DEPARTMENT_SELECT_FIRST_COL = 9;

    /**
     * 派单中队下拉框结束列的索引
     */
    private static final Integer DEPARTMENT_SELECT_LAST_COL = 9;

    /**
     * 重点监测车辆导入模板-派单中队下拉框(客户需求,只能是这四个大队)
     */
    private final String[] departmentIdOptions = {"一中队", "二中队", "三中队", "四中队"};

    /**
     * 车牌颜色的下拉框选项列表(客户需求,这个对应sys_parameter表的plate-color类型)
     */
    private final String[] plateColorOptions = {"黄牌", "蓝牌", "绿牌"};


    /**
     * 在创建Sheet后调用,用于设置下拉框和样式
     *
     * @param writeWorkbookHolder WriteWorkbookHolder
     * @param writeSheetHolder    WriteSheetHolder
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 获取当前Sheet
        final Sheet sheet = writeSheetHolder.getSheet();
        // 获取数据验证的帮助类
        final DataValidationHelper helper = sheet.getDataValidationHelper();

        LOGGER.info("当前派单中队的列为选择项,添加下拉框,设置数据有效性");
        // 设置下拉框范围,此例中是第10列(索引从0开始)的第1行到第10000行
        final CellRangeAddressList optionCellRange = new CellRangeAddressList(0, 9999, DEPARTMENT_SELECT_FIRST_COL, DEPARTMENT_SELECT_LAST_COL);

        // 创建数据验证约束,使用传入的选项列表
        final DataValidationConstraint optionConstraint =
                helper.createExplicitListConstraint(departmentIdOptions);

        // 创建数据验证对象,将约束应用于指定的单元格范围
        final DataValidation validation = helper.createValidation(optionConstraint, optionCellRange);
        // 设置验证失败时的错误提示框
        validation.createErrorBox("输入错误", "请选择下拉框之中内容");
        // 设置是否显示错误提示框
        validation.setShowErrorBox(true);
        // 将数据验证添加到Sheet中
        sheet.addValidationData(validation);

        LOGGER.info("当前车牌颜色的列为选择项,添加下拉框,设置数据有效性");
        for (int colIndex : new int[]{2, 4}) {
            // 设置第2列的车牌颜色下拉框范围
            final CellRangeAddressList plateColorOptionCellRange = new CellRangeAddressList(0, 9999, colIndex, colIndex);
            // 创建数据验证约束,使用车牌颜色选项列表
            final DataValidationConstraint plateColorOptionConstraint = helper.createExplicitListConstraint(plateColorOptions);
            // 创建数据验证对象,将约束应用于指定的单元格范围
            final DataValidation plateColorValidation = helper.createValidation(plateColorOptionConstraint, plateColorOptionCellRange);
            // 设置验证失败时的错误提示框
            plateColorValidation.createErrorBox("输入错误", "请选择正确的车牌颜色");
            // 设置是否显示错误提示框
            plateColorValidation.setShowErrorBox(true);
            // 将数据验证添加到Sheet中
            sheet.addValidationData(plateColorValidation);
        }
    }
}

3.5 效果图

![![外

文章来源:https://blog.csdn.net/weixin_45979122/article/details/135701194
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。