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

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;}@Overridepublic 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;}@Overridepublic 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自定义拦截器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/256097.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux笔记之xhost +和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解

Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解 ——2024-02-11 code review! 文章目录 Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解xhost 的作用xhost 与 Docker 的关系 -e GDK_SCALE 和 -e GDK_DPI_SCALE详解GDK_SCALEGDK_DPI_SC…

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

华为 huawei 交换机 接口 MAC 地址学习限制接入用户数量 配置示例

目录 组网需求: 配置思路&#xff1a; 操作步骤&#xff1a; 配置文件&#xff1a; 组网需求: 如 图 2-14 所示&#xff0c;用户网络 1 和用户网络 2 通过 LSW 与 Switch 相连&#xff0c; Switch 连接 LSW 的接口为GE0/0/1 。用户网络 1 和用户网络 2 分别属于 VLAN10 和 V…

幻兽帕鲁PalWorld服务器2024年配置选择

幻兽帕鲁PalWorld是一款备受期待的虚拟游戏&#xff0c;其独特的幻兽系统和丰富的世界观吸引了大量玩家。然而&#xff0c;随着游戏日益受到关注&#xff0c;服务器的配置选择成为了关键问题。2024年&#xff0c;随着技术不断发展&#xff0c;玩家对于游戏体验的需求也在不断提…

Quartus工程的qsf配置约束文件介绍

一、qsf文件概述 qsf&#xff1a;Quartus Setting File&#xff0c;是Quartus工程的配置文件&#xff1b; 包含一个Quartus工程的所有约束&#xff0c;包括工程的软件版本信息、FPGA器件信息、引脚约分配、引脚电平分配&#xff0c;编译约束和用于Classic TimingAnalyzer的时…

通过QT制作一个模仿微信主界面的界面(不要求实现具体通信功能)

main.cpp #include "widget.h" #include "second.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();//实例化第二个界面Second s;QObject::connect(&w, &Widget::my_jump, &…

微信,支付宝在线换钱平台系统源码

探索全新、全开源的在线换钱系统源码&#xff0c;它将以前所未有的方式改变您的支付体验。我们为您精心打造了一个集简单易用与安全高效于一身的优质产品&#xff0c;它采用最新的技术开发&#xff0c;为您带来前所未有的便捷与安心。 这款在线换钱系统源码设计直观&#xff0…

netty-websocket扩展协议及token鉴权补充

文章源码&#xff1a;gitee 源码部分可以看上一篇文章中的源码分析netty-websocket 鉴权token及统一请求和响应头&#xff08;鉴权控制器&#xff09; 最近刚好没事&#xff0c;看到有朋友说自定义协议好搞&#xff0c;我就想了想&#xff0c;发现上面那种方式实现确实麻烦&…

分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目MySQL数据库版)

1首先介绍下若依项目&#xff1a; 若依是一个基于Spring Boot和Spring Cloud技术栈开发的多租户权限管理系统。该开源项目提供了一套完整的权限管理解决方案&#xff0c;包括用户管理、角色管理、菜单管理、部门管理、岗位管理等功能。 若依项目采用前后端分离的架构&#xf…

Python中使用opencv-python进行人脸检测

Python中使用opencv-python进行人脸检测 之前写过一篇VC中使用OpenCV进行人脸检测的博客。以数字图像处理中经常使用的lena图像为例&#xff0c;如下图所示&#xff1a; 使用OpenCV进行人脸检测十分简单&#xff0c;OpenCV官网给了一个Python人脸检测的示例程序&#xff0c;…

Stable Diffusion 模型下载:RealCartoon-Pixar - V8

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十

泽攸科技ZEM系列台扫助力环境科研创新:可见光催化抗生素降解的探索

环境污染和能源短缺是当今人类社会面临的最严重威胁之一。为了克服这些问题&#xff0c;特别是在污水处理过程中&#xff0c;寻找新的技术来实现清洁、高效、经济的发展显得尤为重要。在各种工业废水中&#xff0c;抗生素的过量排放引起了广泛关注。抗生素的残留会污染土壤、水…

【MATLAB源码-第137期】基于matlab的NOMA系统和OFDMA系统对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 NOMA&#xff08;非正交多址&#xff09;和OFDMA&#xff08;正交频分多址&#xff09;是两种流行的无线通信技术&#xff0c;广泛应用于现代移动通信系统中&#xff0c;如4G、5G和未来的6G网络。它们的设计目标是提高频谱效…

视觉SLAM十四讲学习笔记(二)三维空间刚体

哔哩哔哩课程连接&#xff1a;视觉SLAM十四讲ch3_哔哩哔哩_bilibili​ 目录 一、旋转矩阵 1 点、向量、坐标系 2 坐标系间的欧氏变换 3 变换矩阵与齐次坐标 二、实践&#xff1a;Eigen&#xff08;1&#xff09; 运行报错记录与解决 三、旋转向量和欧拉角 1 旋转向量 …

【数据库】索引的使用

【数据库】索引的使用 前言出发示例创建表Explain 查看sql执行计划where 查询解析无索引有索引 where oderBy 查询解析无索引有索引 总结 前言 在数据库设计过程中&#xff0c;常需要考虑性能&#xff0c;好的设计可以大大提高sql 语句的增删改查速度。在表的创建过程中&…

【EEG信号处理】对信号进行模拟生成

生成信号的目的还是主要是为了学习和探究后面的分析方法&#xff1b;本文主要是对方法进行整理 瞬态 transient 瞬态信号是指的是一瞬间信号上去了&#xff0c;这种情况我们可以用在时域上高斯模拟 peaktime 1; % seconds width .12; ampl 9; gaus ampl * exp( -(EEG.tim…

电脑服务器离线安装.net framework 3.5解决方案(错误:0x8024402c )(如何确定当前系统是否安装NET Framework 3.5)

问题环境&#xff1a; 日常服务的搭建或多或少都会有需要到NET Framework 3.5的微软程序运行框架&#xff0c;本次介绍几种不同的安装方式主要解决运行在Windows 2012 以上的操作系统的服务。 NET Framework 3.5 是什么&#xff1f; .NET Framework是微软公司推出的程序运行框架…

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(二)

gnome-builder创建的程序&#xff0c;在工程树中有三个重要程序&#xff1a;main主程序、application应用程序和window主窗口程序。main整个程序的起始&#xff0c;它会操作application生产应用环境&#xff0c;application会操作window生成主窗口&#xff0c;于是就有了 appli…

【北邮鲁鹏老师计算机视觉课程笔记】01 introduction

1 生活中的计算机视觉 生活中的各种计算机视觉识别系统已经广泛地应用起来了。 2 计算机视觉与其他学科的关系 认知科学和神经科学是研究人类视觉系统的&#xff0c;如果能把人类视觉系统学习得更好&#xff0c;可以迁移到计算机视觉。是计算机视觉的理论基础。 算法、系统、框…