EasyExcel下载带下拉框和批注模板

本文介绍了如何通过EasyExcel框架在Java中创建一个带有下拉框和批注功能的Excel模板下载服务,包括控制器实现、实体对象定义以及自定义拦截器的使用。
摘要由CSDN通过智能技术生成

EasyExcel下载带下拉框和批注模板

一、 代码实现

  1. controller下载入口
/**
     *下载excel模板
     * @author youlu
     * @date 2023/8/14 17:31
     * @param response
     * @param request
     * @return void
     */
    @PostMapping("/downloadTemplate")
    public void downloadExcel(HttpServletResponse response, HttpServletRequest request) throws IOException {
    	//查询字典数据,用于模板下拉框和批注说明使用
        Map<String, List<SysDictData>> dictDataMap = dictDataService.selectDictDataMapByDictTypeAndStatus("worksheet", "0");
        //获取供应商类型,不同供应商类型展示的下拉框和批注会有不一样
        Boolean supplier = getSupplierBoolean();
        ParamThreadLocal.setParam(supplier);
        try {
            long currentTimeMillis = System.currentTimeMillis();
            String name = "工单模板_" + currentTimeMillis;
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(name, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), TWorkSheetReadVO.class).inMemory(true)
                    .registerWriteHandler(new CommentWriteHandler(dictDataMap)) //加下拉框的拦截器
                    .registerWriteHandler(new CustomSheetWriteHandler(dictDataMap)) //加批注的拦截器
                    .build();
            WriteSheet writeSheet = EasyExcel.writerSheet("工单模板").build();
            excelWriter.write(Lists.newArrayList(), writeSheet);
            excelWriter.finish();
        } finally {
            ParamThreadLocal.clearParam();
        }
    }
  1. 实体对象
package com.smy.ows.project.worksheet.domain.vo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.converters.date.DateStringConverter;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.smy.framework.base.DesensitizationAnnotation;
import com.smy.ows.project.worksheet.enums.SheetLevelEnums;
import com.smy.ows.project.worksheet.enums.WorkSheetStatus;
import com.smy.ows.util.*;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 客诉工单对象 t_work_sheet
 *
 * @author youlu
 * @date 2023-01-11
 */
@Data
public class TWorkSheetReadVO implements Serializable {
    private static final long serialVersionUID = 5924360788178861972L;

    /**
     * 客诉标题
     */
    @ExcelProperty(value = "客诉标题", index = 0)
    @ColumnWidth(20)
    private String complaintHeadline;
    /**
     * @see SheetLevelEnums
     */
    @ExcelProperty(value = "优先级", index = 1, converter = PriorityIntegerStringConverter.class)
    @ColumnWidth(10)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private Integer priority;

    @ExcelProperty(value = "客户姓名", index = 2)
    @ColumnWidth(20)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private String custName;

    /**
     * 客户号
     */
    @ExcelProperty(value = "客户号", index = 3)
    @ColumnWidth(20)
    private String custNo;

    @DesensitizationAnnotation
    @ExcelProperty(value = "客户手机号", index = 4)
    @ColumnWidth(20)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private String custMobile;

    @DesensitizationAnnotation
    @ExcelProperty(value = "客户身份证", index = 5)
    @ColumnWidth(30)
    private String custIdNo;

    /**
     * 投诉时间
     */
    @ExcelProperty(value = "投诉时间(yyyy-MM-dd HH:mm:ss)", index = 6, converter = DateStringConverter.class)
    @ColumnWidth(40)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date complaintTime;
    //反馈渠道
    @ExcelProperty(value = "反馈渠道", index = 7, converter = ChannelStringStringConverter.class)
    @ColumnWidth(15)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private String feedbackChannel;


    @ExcelProperty(value = "工单类型", index = 8, converter = TypeIntegerStringConverter.class)
    @ColumnWidth(15)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private Integer type;

    @ExcelProperty(value = "业务类型", index = 9, converter = BizTypeIntegerStringConverter.class)
    @ColumnWidth(15)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private Integer bizType;

    @DesensitizationAnnotation
    @ExcelProperty(value = "客户联系方式", index = 10)
    @ColumnWidth(15)
    private String custContactMobile;

    /**
     * 所属资方
     */
    @ExcelProperty(value = "所属资方", index = 11)
    @ColumnWidth(15)
    private String capital;

    @ExcelProperty(value = "投诉内容", index = 12)
    @ColumnWidth(30)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    private String content;

    /**
     * @see WorkSheetStatus
     */
    @ExcelProperty(value = "工单状态", index = 13, converter = StatusIntegerStringConverter.class)
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    @ColumnWidth(15)
    private Integer status;

    @ExcelProperty(value = "处理结果", index = 14, converter = ResultIntegerStringConverter.class)
    @ColumnWidth(15)
    private Integer result;
    /**
     * 处理情况
     */
    @ExcelProperty(value = "处理情况", index = 15)
    @ColumnWidth(15)
    private String handingInfo;

}
  1. 下拉框拦截器
package com.smy.ows.util;

import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import com.smy.ows.common.core.domain.entity.SysDictData;
import com.smy.ows.common.utils.ParamThreadLocal;
import com.smy.ows.project.worksheet.constant.WorksheetDictTypeConstant;
import com.smy.ows.project.worksheet.enums.WorkSheetStatus;
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.util.CellRangeAddressList;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义拦截器.
 *
 * @author youlu
 */
public class CustomSheetWriteHandler implements SheetWriteHandler {

    private  Map<String, List<SysDictData>> notationMap;

    public CustomSheetWriteHandler(Map<String, List<SysDictData>> notationMap) {
        this.notationMap = notationMap;
    }

    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context) {
        DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();
        Map<Integer, String[]> mapDropDown = this.getIntegerMap();
        for (Integer integer : mapDropDown.keySet()) {
        	//起始行,结束行,元素位置(ExcelProperty中的value值)
            CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 65535, integer, integer);
            String[] strings = mapDropDown.get(integer);
            DataValidationConstraint constraint = helper.createExplicitListConstraint(strings);
            DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
            context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
        }
    }

    private Map<Integer, String[]> getIntegerMap() {
     	//map中key对应,ExcelProperty中的value值。map中value对应下拉框的值
        Map<Integer, String[]> mapDropDown = new HashMap<>();
        for (String key : notationMap.keySet()) {
            String[] strings = notationMap.get(key).stream().map(k -> k.getDictLabel()).toArray(String[]::new);
            if (WorksheetDictTypeConstant.WORKSHEET_RESULT.equals(key)) {
                mapDropDown.put(14, strings);
            } else if (WorksheetDictTypeConstant.WORKSHEET_TYPE.equals(key)) {
                mapDropDown.put(8, strings);
            } else if (WorksheetDictTypeConstant.WORKSHEET_BIZ_TYPE.equals(key)) {
                mapDropDown.put(9, strings);
            } else if (WorksheetDictTypeConstant.WORKSHEET_PRIORITY.equals(key)) {
                mapDropDown.put(1, strings);
            } else if (WorksheetDictTypeConstant.WORKSHEET_FEEDBACK_CHANNEL.equals(key)) {
                mapDropDown.put(7, strings);
            }
        }
        Boolean supplier = (Boolean) ParamThreadLocal.getParam();
        if (supplier) {
            //供应商 和 资方的,工单状态只能选择【待分配】
            mapDropDown.put(13, new String[]{WorkSheetStatus.PENDING.getDesc()});
            //其他的工单状态只能选择【待分配】和 【已处理】
        } else {
            mapDropDown.put(13, new String[]{WorkSheetStatus.PENDING.getDesc(), WorkSheetStatus.FINISHED.getDesc()});
        }
        return mapDropDown;
    }
}
  1. 批注拦截器
package com.smy.ows.util;

import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import com.google.common.collect.Lists;
import com.smy.ows.common.core.domain.entity.SysDictData;
import com.smy.ows.project.worksheet.constant.WorksheetDictTypeConstant;
import com.smy.ows.project.worksheet.enums.WorkSheetStatus;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 自定义拦截器.新增注释,第一行头加批注
 *
 * @author Jiaju Zhuang
 */
public class CommentWriteHandler implements RowWriteHandler {

    private final Map<String, List<SysDictData>> notationMap;

    public CommentWriteHandler(Map<String, List<SysDictData>> notationMap) {
        this.notationMap = notationMap;
    }


    @Override
    public void afterRowDispose(RowWriteHandlerContext context) {
        if (BooleanUtils.isTrue(context.getHead())) {
            Sheet sheet = context.getWriteSheetHolder().getSheet();
            Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
            // 在第一行 第二列创建一个批注

            String priorityDesc = Optional.ofNullable(notationMap.get(WorksheetDictTypeConstant.WORKSHEET_PRIORITY)).orElse(Lists.newArrayList()).stream()
                    .map(k -> k.getDictValue() + ":" + k.getDictLabel()).collect(Collectors.joining("\r\n"));
             //对应要加批注的元素的ExcelProperty中的value值       
            Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)1, 0, (short)2, 1));
            comment.setString(new XSSFRichTextString(priorityDesc));
            // 将批注添加到单元格对象中
            sheet.getRow(0).getCell(1).setCellComment(comment);
			//对应要加批注的元素的ExcelProperty中的value值
            Comment comment6 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)6, 0, (short)2, 1));
            comment6.setString(new XSSFRichTextString("yyyy-MM-dd HH:mm:ss"));
            sheet.getRow(0).getCell(6).setCellComment(comment6);

            String channelDesc = Optional.ofNullable(notationMap.get(WorksheetDictTypeConstant.WORKSHEET_FEEDBACK_CHANNEL)).orElse(Lists.newArrayList()).stream()
                    .map(k -> k.getDictValue() + ":" + k.getDictLabel()).collect(Collectors.joining("\r\n"));
            Comment comment7 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 7, 0, (short) 2, 1));
            comment7.setString(new XSSFRichTextString(channelDesc));
            sheet.getRow(0).getCell(7).setCellComment(comment7);

            String typeDesc = Optional.ofNullable(notationMap.get(WorksheetDictTypeConstant.WORKSHEET_TYPE)).orElse(Lists.newArrayList()).stream()
                    .map(k -> k.getDictValue() + ":" + k.getDictLabel()).collect(Collectors.joining("\r\n"));
            Comment comment8 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 8, 0, (short) 2, 1));
            comment8.setString(new XSSFRichTextString(typeDesc));
            sheet.getRow(0).getCell(8).setCellComment(comment8);

            String bizDesc = Optional.ofNullable(notationMap.get(WorksheetDictTypeConstant.WORKSHEET_BIZ_TYPE)).orElse(Lists.newArrayList()).stream()
                    .map(k -> k.getDictValue() + ":" + k.getDictLabel()).collect(Collectors.joining("\r\n"));
            Comment comment9 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 9, 0, (short) 2, 1));
            comment9.setString(new XSSFRichTextString(bizDesc));
            sheet.getRow(0).getCell(9).setCellComment(comment9);


            String statusDesc = Arrays.stream(WorkSheetStatus.values()).map(k -> k.getCode() + ":" + k.getDesc()).collect(Collectors.joining("\r\n"));
            Comment comment13 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 13, 0, (short) 2, 1));
            comment13.setString(new XSSFRichTextString(statusDesc));
            sheet.getRow(0).getCell(13).setCellComment(comment13);

            String resultDesc = Optional.ofNullable(notationMap.get(WorksheetDictTypeConstant.WORKSHEET_RESULT)).orElse(Lists.newArrayList()).stream()
                    .map(k -> k.getDictValue() + ":" + k.getDictLabel()).collect(Collectors.joining("\r\n"));
            Comment comment14 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 14, 0, (short) 2, 1));
            comment14.setString(new XSSFRichTextString(resultDesc));
            sheet.getRow(0).getCell(14).setCellComment(comment14);

        }
    }
}

二、实现效果

  1. 批注效果
    在这里插入图片描述
  2. 下拉框效果
    在这里插入图片描述

三、参考文档

easyExcel自定义拦截器

使用 EasyExcel 实现 Spring Boot 中的 Excel 模板下载可以分为以下几个步骤: 1. 引入 EasyExcel 依赖 在 pom.xml 文件中引入 EasyExcel 的依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.3.0</version> </dependency> ``` 2. 创建 Excel 模板Excel 中创建好要导出的数据模板,如下图所示: ![excel模板示例](https://img-blog.csdn.net/20181207142243532?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3p6dXhpYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/75) 注意:模板中的内容可以是静态的,也可以是动态的,如日期等。 3. 编写 Controller 方法 编写 Controller 中的方法,将 Excel 模板下载到客户端。代码如下: ```java @RestController @RequestMapping("/excel") public class ExcelController { @GetMapping("/downloadTemplate") public void downloadTemplate(HttpServletResponse response) throws IOException { // 获取模板文件路径 String templateFileName = "xxxx.xlsx"; String path = this.getClass().getClassLoader().getResource("").getPath(); String templatePath = path + templateFileName; // 设置响应头 response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(templateFileName, "UTF-8")); // 写出文件 OutputStream outputStream = response.getOutputStream(); InputStream inputStream = new FileInputStream(templatePath); byte[] buffer = new byte[1024]; int read = 0; while ((read = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, read); } inputStream.close(); outputStream.flush(); outputStream.close(); } } ``` 4. 测试 启动 Spring Boot 应用,访问 http://localhost:8080/excel/downloadTemplate 即可下载 Excel 模板。 注意:模板文件需要放在 resources 目录下,此处的文件名为 xxxx.xlsx。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值