EasyExcel动态复杂表头导出方法

news2024/11/24 7:40:51

目录

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

需求分析

公司数据比较特殊有一部分数据需要动态修改导致信息导入时表头是不确定的,但其中又有一部分表头是固定的,如下图所示,如果表头全部是固定的话可以通过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;
    }

数据导入

参考文章:EasyExcel复杂表头数据导入

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

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

相关文章

Linux CentOS7.9安装OpenJDK17

Linux CentOS7.9安装OpenJDK17 一、OpenJDK下载 清华大学开源软件镜像站 国内的站点&#xff0c;下载速度贼快 二、上传解压 文件上传到服务器后&#xff0c;解压命令&#xff1a; tar -zxvf jdk-xxxx-linux-x64.tar.gz三、配置环境 export JAVA_HOME/home/local/java/j…

ffmpeg mp3截取命令,视频与mp3合成带音频视频命令

从00:00:03.500开始截取往后长度到结尾的mp3音频&#xff08;这个更有用&#xff0c;测试好用&#xff09; ffmpeg -i d:/c.mp3 -ss 00:00:03.500 d:/output.mp3 将两个音频合并成一个音频&#xff08;测试好用&#xff09; ffmpeg -i "concat:d:/c.mp3|d:/output.mp3&…

Linux C语言进阶-D10指针数组

指针变量构成的数组 理解下面printf中的a和p的表示&#xff0c;其中p[0]、p[1]、p[2]表示存储的a,a1和a2这几个地址&#xff0c;而再加个*&#xff0c;相当于对地址解引用&#xff0c;从而得到数组中的值。 如下图&#xff0c;要想得到a[0][1]的值可以直接打印a[0][1]&#xf…

使用pytorch处理自己的数据集

目录 1 返回本地文件中的数据集 2 根据当前已有的数据集创建每一个样本数据对应的标签 3 tensorboard的使用 4 transforms处理数据 tranfroms.Totensor的使用 transforms.Normalize的使用 transforms.Resize的使用 transforms.Compose使用 5 dataset_transforms使用 1 返回本地…

YOLOv5:修改backbone为SPPCSPC

YOLOv5&#xff1a;修改backbone为SPPCSPC 前言前提条件相关介绍SPPCSPCYOLOv5修改backbone为SPPCSPC修改common.py修改yolo.py修改yolov5.yaml配置 参考 前言 记录在YOLOv5修改backbone操作&#xff0c;方便自己查阅。由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬…

一文读懂最小相位滤波器和线性相位滤波器

一文读懂最小相位滤波器和线性相位滤波器 1. 举例说明2. 最小相位定义2.1 最小相位多项式2.2 最大相位滤波器2.3 最小相位意味最快的衰减2.4 最小相位/全通分解 3. 建立最小相位系统 前一篇博客 《一文读懂滤波器的线性相位&#xff0c;全通滤波器&#xff0c;群延迟》 详细解…

curl(二)HTTP协议和头

一 HTTP协议相关 ① 强制发出请求的http1.0 7.29 版本默认是http1.1 ② 查看当前curl版本是否支持http2 方式2: curl --version看Features 补充&#xff1a; 7.33.0 版本才引入 http2,才能使用curl发出http2.0版本的请求 ③ 强制发送http3 说明&#xff1a; 了解即可 二…

DevChat:超越编码的未来 - 优势、安装、使用、以及未来前景

目录 前言1 DevChat的优势1.1 精确的上下文控制1.2 灵活的提示管理1.3 上下文构建1.4 提前准备好的提示模板1.5 高级命令控制 2 安装DevChat插件3 使用DevChat插件3.1 代码生成3.2 文档撰写3.3 解释代码3.4 解决问题3.5 版本控制 4 DevChat的未来前景结语 前言 在软件开发领域…

Docker 多阶段构建的原理及构建过程展示

Docker多阶段构建是一个优秀的技术&#xff0c;可以显著减少 Docker 镜像的大小&#xff0c;从而加快镜像的构建速度&#xff0c;并减少镜像的传输时间和存储空间。本文将详细介绍 Docker 多阶段构建的原理、用途以及示例。 Docker 多阶段构建的原理 在传统的 Docker 镜像构建…

阿里面试:让代码不腐烂,DDD是怎么做的?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的高并发落地经验&#xff1f; 谈谈你对DDD的理解&#xf…

CIM与MES

CIM系统&#xff0c;全称计算机集成制造系统&#xff08;Computer-Integrated Manufacturing&#xff09;&#xff0c;是一种集成了计算机技术、网络通讯技术和软件系统的制造自动化框架。CIM的主要目标是整合制造过程中的所有活动&#xff0c;包括生产管理、设备管理和品质管理…

物流小程序制作教程:从零到有,详细解析

随着互联网的快速发展&#xff0c;物流行业也逐渐实现了数字化转型。为了满足消费者对更加便捷、高效的服务需求&#xff0c;许多物流企业选择制作自己的小程序。本文将通过乔拓云网后台&#xff0c;带你轻松搭建物流小程序&#xff0c;主要分为以下几个部分&#xff1a; 一、进…

设置echarts折线图虚线

itemStyle:{normal: {lineStyle: { type: solid}}}itemStyle:{normal: {lineStyle: { type: dashed}}}放到每个红框里面

梯度消失和梯度爆炸的原因

梯度消失和梯度爆炸 梯度爆炸和梯度消失本质上是因为梯度反向传播中的连乘效应。 梯度下降算法 举一个简单的例子,函数表达式为loss 2w^2 4w,如下图 ​​​​​​​ ​​​​​​​ 为了求得w的最优值,使得loss最小,从上图很容易看出来当w -1时,loss最小…

ER图设计神器,帮你省时省力,高效完成工作!

ER图&#xff08;Entity-Relationship Diagram&#xff09;工具用于设计数据库模型&#xff0c;通常用于表示数据实体、关系和属性之间的关系。以下是10个好用的ER图工具。 一、Lucidchart Lucidchart 是一款基于云的协作式图表设计工具&#xff0c;它允许用户创建、编辑和共享…

SAP发票及复制控制

一、概述 众所周知&#xff0c;SAP为业财一体化的ERP管理系统&#xff0c;因此财务发票必不可少&#xff0c;很多外贸企业还会用到形式发票。 发票相关的配置主要包含&#xff1a;发票类型、复制控制、发票定价以及自动过账的配置。 二、系统配置 1. 发票类型 1.1 概述 发…

Latex安装使用教程

在论文投稿时有些期刊要求使用Latex格式&#xff0c;比如博主现在就遇到了这个问题&#xff0c;木有办法&#xff0c;老老实实的学呗。大家可以去官网下载&#xff0c;但官网的界面设计属实有些一言难尽&#xff0c;因此我们可以使用国内的镜像。 LaTeX 基于 TeX&#xff0c;主…

2023年双十一第2波红包活动淘宝天猫京东双11红包领取优惠券跨店满多少减多少规则?

本文为大家提供众多福利&#xff1a; 2023年淘宝/天猫双十一红包第2波活动时间与领取入口&#xff0c;最高23888超级红包 2023年京东双十一红包第2波活动时间与领取入口&#xff0c;最高11111京享红包 草柴APP领淘宝/天猫、京东大额内部隐藏优惠券&#xff0c;拿购物返利 美…

Content-Type 值有哪些?

1、application/x-www-form-urlencoded 最常见 POST 提交数据的方式。 浏览器的原生 form 表单&#xff0c;如果不设置 enctype 属性&#xff0c;那么最终就会以 application/x-www-form-urlencoded 方式提交数据。 <form action"http://www.haha/ads/sds?name小草莓…

根据Aurora发送时序,造Aurora 发送数据包

首先Aurora采用AXIS接口 由于后续需要进行AXIS接口 不同时钟域的数据位宽转换&#xff08;64bit和256bit之间的转换&#xff09;&#xff0c;因此分两次走。 第一种方法&#xff1a;采用AXIS数据位宽转换IP AXIS跨时钟域IP 第二种方法&#xff1a;逻辑完成 下面记录逻辑…