EasyExcel动态复杂表头导出设置方法

news2025/7/24 2:29:42

目录

    • 需求分析
    • 解决方案
    • 数据问题

需求分析

公司数据比较特殊有一部分数据需要动态修改导致信息导入时表头是不确定的,但其中又有一部分表头是固定的,如下图所示,如果表头全部是固定的话可以通过EasyExcel实体类的注解很轻松的解决,但由于部分数据动态改变,所以无法完全依靠注解实现。

在这里插入图片描述

解决方案

自定义方法通过反射获取实体类@ExcelProperty注解的值,同时在方法中获取动态表头信息共同组合成表头List数据。

	//模板下载接口实现
    public void downloadExcelTemplate(HttpServletResponse response) throws IOException {
        String filename = URLEncoder.encode("物料信息导入模板"+System.currentTimeMillis(),"utf-8");
        //设置响应头信息:将响应内容类型设置为 Excel 文件,并指定文件名和编码方式
        response.setHeader("Content-Disposition","attachment;filename=" + filename + ".xlsx");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        //获取响应的输出流,用于将数据写入响应。
        OutputStream outputStream = response.getOutputStream();
        //创建一个 ExcelWriter 对象,用于写入 Excel 文件。
        ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
        //gaugeOutfit.getItemHead()返回了表头List数据,也是动态表头的核心
        WriteSheet sheet = EasyExcel.writerSheet("sheet1").head(gaugeOutfit.getItemHead()).build();
        //向数据表中写入空数据
        excelWriter.write((Collection<?>) null, sheet);
        excelWriter.finish();
    }
//实体类
@TableName(value = "import_item",autoResultMap = true)
@Data
public class ImportItem implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId
    @ExcelIgnore
    private Long id;
    
    /**
     * 域动态信息,用于导入时集合所有的动态表头的信息,导入时使用
     */
    @TableField(typeHandler = JacksonTypeHandler.class , value = "dynamic_information")
    @ExcelIgnore
    private JSONObject dynamicInformation;
   
    @TableField("code")
    @ExcelProperty("物料编码")
    private String code;

    @TableField("name")
    @ExcelProperty("产品名称")
    @NotBlank(message = "产品名称字段不能为空")
    private String name;
  
    @TableField("category")
    @ExcelProperty("产品分类")
    private String category;
 
    @TableField("format")
    @ExcelProperty("产品规格")
    private String format;
    
    @TableField("life_cycle")
    @ExcelProperty("生命周期")
    private Integer lifeCycle;

    @TableField("brand")
    @ExcelProperty("品牌")
    private String brand;
   
    @TableField("sort")
    @ExcelProperty("排序")
    private Integer sort;
    
    @TableField("price_cost")
    @ExcelProperty("成本价")
    private BigDecimal priceCost;
  
    @TableField("price_line")
    @ExcelProperty("划线价")
    private BigDecimal priceLine;
    
    @TableField("length")
    @ExcelProperty("长度")
    private BigDecimal length;
    
    @TableField("width")
    @ExcelProperty("宽度")
    private BigDecimal width;
  
    @TableField("height")
    @ExcelProperty("高度")
    private BigDecimal height;
    
    @TableField("create_time")
    @ExcelIgnore
    private Date createTime;
    
    @ExcelIgnore
    private Date updateTime;
}

package com.ruoyi.plm.util;

import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.plm.mapper.AttributeKeyMapper;
import com.ruoyi.plm.mapper.DomainMapper;
import com.ruoyi.plm.model.entity.AttributeKey;
import com.ruoyi.plm.model.entity.Domain;
import com.ruoyi.plm.model.entity.ImportItem;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @Author weijunliang
 * @CreateTime 2023/10/16 8:43
 * @Description TODO
 */
@Component
public class ExportExcelGaugeOutfit {
    @Resource
    private DomainMapper domainMapper;

    @Resource
    private AttributeKeyMapper keyMapper;

    public List<List<String>> getItemHead(){
        List<List<String>> list = new ArrayList<>();
        //反射获取@ExcelProperty注解字段
        Class<ImportItem> importItemClass = ImportItem.class;
        Field[] fields = importItemClass.getDeclaredFields();
        for(Field field :fields){
            if(field.isAnnotationPresent(ExcelProperty.class)){
                ExcelProperty fieldAnnotation = field.getAnnotation(ExcelProperty.class);
                String headName = Arrays.toString(fieldAnnotation.value()).replace("[", "").replace("]", "");
                List<String> head0 = new ArrayList<String>();
                //之所以加固定数据是为了后续导出数据时方便
                head0.add("固定数据");
                head0.add(headName);
                list.add(head0);
            }
        }
        //动态数据
        List<Domain> domainList = domainMapper.selectList(null);
        for (Domain domain : domainList){
            String domainName = domain.getName();
            QueryWrapper<AttributeKey> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("domain_id",domain.getId());
            List<AttributeKey> keyList = keyMapper.selectList(queryWrapper);
            for (AttributeKey key : keyList){
                ArrayList<String> head1 = new ArrayList<>();
                head1.add(domainName);
                head1.add(key.getName());
                list.add(head1);
            }
        }
        return list;
    }
}

数据问题

虽然上述方法解决了动态表头的问题,但当需要导出数据时把动态数据对应到表中的动态表头也需要把所有数据转换为相同List才行,这也就使得导出数据时需要手动进行处理而无法完全依靠EasyExcel的注解实现,颇费一番手脚。

	//获取所有数据
    private ArrayList<List<Object>> getAllData() throws IllegalAccessException {
        List<Item> items = itemMapper.selectList(null);
        ArrayList<List<Object>> importItemArrayList = new ArrayList<>();
        importItemArrayList.addAll(itemTransferList(items));
        return importItemArrayList;
    }
    //物料信息转换为List
    private List<List<Object>> itemTransferList(List<Item> itemList) throws IllegalAccessException {
        ArrayList<List<Object>> lists = new ArrayList<>();
        for (Item item : itemList){
            ImportItem importItem = new ImportItem();
            BeanUtils.copyProperties(item,importItem);
            //处理其它数据
            //通过反射在hashMap中添加固定字段信息
            HashMap<String, Object> hashMap = new HashMap<>();
            Class<ImportItem> importItemClass = ImportItem.class;
            Field[] fields = importItemClass.getDeclaredFields();
            for(Field field :fields){
                if(field.isAnnotationPresent(ExcelProperty.class)){
                    field.setAccessible(true);
                    ExcelProperty fieldAnnotation = field.getAnnotation(ExcelProperty.class);
                    String headName = Arrays.toString(fieldAnnotation.value()).replace("[", "").replace("]", "");
                    hashMap.put(headName, field.get(importItem));
                }
            }
            //hashMap添加动态字段信息,根据自己的业务逻辑修改
            List<Domain> domainList = domainMapper.selectList(null);
            for (Domain domain : domainList){
                /**
                ******
                **/
                hashMap.put(headName,headValue);
            }
            //hashMap对应表头数据并转换为list
            List<List<String>> itemHead = gaugeOutfit.getItemHead();
            ArrayList<Object> list = new ArrayList<>();
            for (List<String> head : itemHead){
                Object o = hashMap.get(head.get(1));
                list.add(o);
            }
            lists.add(list);
        }
        return lists;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决CSS中height:100%失效的问题

出现BUG的场景&#xff0c;点击退出到登录页面&#xff0c;发现高度不对 上面出现了一种只是占了内容的高度&#xff0c;没有占满100%&#xff0c;为什么会出现这种情况呐&#xff1f; 让div的height"100%"&#xff0c;执行网页时&#xff0c;css先执行到&#xff0…

力扣刷题 day61:10-31

1.单词规律 给定一种规律 pattern 和一个字符串 s &#xff0c;判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配&#xff0c;例如&#xff0c; pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 方法一&#xff1a;双哈希表 #方法一&…

“碳”索未来,“汇”聚双碳

10月28日在广东省惠州市由汇林盛源低碳科技&#xff08;广东&#xff09;有限公司开办的2023汇林绿碳经济发展专题交流会取得圆满成功。 本次交流会基于我国在2030年达到碳达峰&#xff0c;2060年达到碳中和的目标&#xff0c;提出了汇林盛源公司在绿碳经济领域特有的优势与思考…

jeecg-uniapp 杂七杂八数据

uniapp 点击事件 tap: 单击事件 confirm: 回车事件 blur:失去焦点事件 touchstart: 触摸开始事件 touchmove: 触摸移动事件。 touchend: 触摸结束事件。 longpress: 长按事件。 input: 输入框内容变化事件。 change: 表单元素值变化事件。 submit: 表单提交事件。 scroll: 滚动…

Servlet的继承树,生命周期和线程不安全

1、Servlet 继承树 3)Servlet的继承树 - Servlet接口public interface Servlet{public void init(config);public void service(request,response);public void destroy();} - GenericServlet抽象类public abstract class GenericServlet implements Servlet{实现了init方法和d…

LiveMedia视频管理平台如何接入海康大华前端设备

LiveMedia视频管理平台支持对局域网内海康、大华、ONVIF设备及已经注册的GB28181前端&#xff0c;进行自动搜索&#xff0c;添加&#xff0c;简化添加流程。 接入海康大华设备示例 登陆视频中间件进入平台配置页面 点击上图设备管理&#xff0c;进入设备管理界面 点击设备发现…

J2EE项目部署与发布(Linux版本)

目录 一.jdk&tomcat安装 1.jdk的安装 1.2解压对应的安装包 1.3配置环境变量 2.tomcat的安装 二.mysql的安装 三.后端接口部署 后端部署 导入war包 修改端口 开启访问 一.jdk&tomcat安装 1.jdk的安装 登录VMware Workstation Pro 然后连接MobaXterm 将 jd…

ctfhub技能树web题目全解

Rce 文件包含 靶场环境 重点是这个代码&#xff0c;strpos&#xff0c;格式是这样的strpoc&#xff08;1&#xff0c;2&#xff0c;3&#xff09; 1是要搜索的字符串&#xff0c;必须有&#xff1b;2是要查询的字符串&#xff0c;必须有&#xff1b;3是在何处开始查询&#…

精明玩家的防骗攻略!绝地求生作图工具推荐!

亲爱的游戏玩家们&#xff0c;大家好&#xff01;在这个充满欢乐的游戏世界中&#xff0c;我们总是不可避免地会面临一些骗局和风险。为了保护自己的权益和游戏账号的安全&#xff0c;我们需要一些实用的方法和工具来帮助我们游戏更放心。 首先&#xff0c;防止被骗游戏账号黑名…

SpringBoot的核心配置:YAML概述、基础语法;JSR303数据校验;多环境切换

SpringBoot核心配置 SpringBoot配置文件分类 SpringBoot是基于约定的&#xff0c;所以很多配置都有默认值&#xff0c;但如果想使用自己的配置替换默认配置的话&#xff0c;就可以使用 application.properties或者application.yml&#xff08;application.yaml&#xff09;进…

“VVIC API:一键获取海量商品列表,根据关键词精准匹配,助力商家抢占市场先机!“

VVIC API接口可以根据关键词获取商品列表。以下是使用VVIC API接口获取商品列表的步骤&#xff1a; 确认VVIC API接口的请求地址和所需参数。根据接口文档中的说明设置请求参数&#xff0c;包括关键词和其他筛选条件。发送HTTP GET请求到API地址&#xff0c;即可得到对应的调用…

错误: 找不到或无法加载主类 回归java运行的本质

错误: 找不到或无法加载主类 回归java运行的本质 一&#xff0c;背景 当有了idea这种工具后&#xff0c;java的mian方法执行起来是如此简单&#xff0c;很少有人再手动编辑并通过命令行执行了。 同时&#xff0c;在当今Spring Boot盛行的今天&#xff0c;恐怕很少再有人执行j…

cmake多目录构建初步成功

目录和代码和 首次cmake 多目录构建失败 此文一样&#xff1b; 只有一个CMakeLists.txt&#xff1b; cmake_minimum_required(VERSION 3.10) project(mytest3 VERSION 1.0) include_directories("${PROJECT_SOURCE_DIR}/include") add_executable(mytest3 src/main…

二叉树问题——前/中/后/层遍历问题(递归与栈)

摘要 博文主要介绍二叉树的前/中/后/层遍历(递归与栈)方法 一、前/中/后/层遍历问题 144. 二叉树的前序遍历 145. 二叉树的后序遍历 94. 二叉树的中序遍历 102. 二叉树的层序遍历 103. 二叉树的锯齿形层序遍历 二、二叉树遍历递归解析 // 前序遍历递归LC144_二叉树的前…

[PHP]DBErp进销存系统 v1.1 RC 221101

DBErp系统&#xff0c;是北京珑大钜商科技有限公司 基于 Laminas doctrine 2 开发的一套进销存系统。 本系统运行环境要求&#xff1a; 服务器系统&#xff1a;Linux&#xff08;推荐&#xff09;、Unix、Windows Web服务软件&#xff1a;Apache&#xff08;推荐&#xff09;…

PO-sxmb_moni错误消息提示“在qRFC队列**中执行消息时出现短存储***

问题描述&#xff1a; 原因分析&#xff1a; 一般是abap dump或者标准错误、弹窗这类挂起操作导致接口代理程序执行不下去“存储”导致 解决方案&#xff1a; 1.SMQ1 SMQ2找到错误的队列&#xff0c;查看执行日志&#xff08;意义不大&#xff09;&#xff0c;点击解锁看看是…

NLP 快速入门

文章目录 前言NLP 历史回顾NLP任务语料的标注AI语料标注师岗位职责 TransformersHugging Face模型中文文本分类使用 NLTK 进行文本分类 参考链接开源NLP 前言 学习NLP&#xff0c;解决两个问题&#xff1a; 如何使用别人训练好的模型&#xff1f;如何基于别人的模型&#xff…

SpringMVC Day 09 : 异常处理

前言 在Web应用程序开发中&#xff0c;我们经常会遇到各种各样的错误和异常情况。那么如何有效地捕获和处理这些异常呢&#xff1f;本文将介绍Spring MVC中的异常处理机制&#xff0c;帮助您构建更稳定、可靠的Web应用程序。 一、前期准备 1、新建项目&#xff0c;结构如下 2…

【问题解决】 avue dicUrl 动态参数加载字典数据(已解决)

事情是这样的&#xff0c;用了avue-crud组件&#xff0c;配置了一个option。     现在有一列source属性要展示为 多选的下拉框 &#xff0c;当然问题不在这而在于&#xff0c;选项是需要根据同级别属性id去拿的。也就是option.column.source 的配置中 需要该行的option.col…

V90PN总线伺服梯形加减速速度控制(标准报文1应用)

V90 PN总线伺服速度控制应用可以利用标准报文1和SinaSpeed功能块实现,具体代码介绍请查看下面相关文章链接,这里不再赘述。 速度随动控制 V90伺服PN总线速度随动控制(手摇轮功能)-CSDN博客文章浏览阅读40次。V90PN总线控制相关内容,请参考下面文章链接:博途1200/1500PLC …