EasyExcel动态复杂表头导出方法

目录

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

需求分析

公司数据比较特殊有一部分数据需要动态修改导致信息导入时表头是不确定的,但其中又有一部分表头是固定的,如下图所示,如果表头全部是固定的话可以通过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@ExcelIgnoreprivate Long id;/*** 域动态信息,用于导入时集合所有的动态表头的信息,导入时使用*/@TableField(typeHandler = JacksonTypeHandler.class , value = "dynamic_information")@ExcelIgnoreprivate 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")@ExcelIgnoreprivate Date createTime;@ExcelIgnoreprivate 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 {@Resourceprivate DomainMapper domainMapper;@Resourceprivate 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;}//物料信息转换为Listprivate 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对应表头数据并转换为listList<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.hqwc.cn/news/158275.html

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

相关文章

生产环境使用boost::fiber

简介 boost::fiber是一类用户级线程&#xff0c;也就是纤程。其提供的例子与实际生产环境相距较远&#xff0c;本文将对其进行一定的改造&#xff0c;将其能够投入到生产环境。 同时由于纤程是具有传染性的&#xff0c;使用纤程的代码里也全部要用纤程封装&#xff0c;本文将对…

数据库深入浅出,数据库介绍,SQL介绍,DDL、DML、DQL、TCL介绍

一、基础知识&#xff1a; 1.数据库基础知识 数据(Data)&#xff1a;文本信息(字母、数字、符号等)、音频、视频、图片等&#xff1b; 数据库(DataBase)&#xff1a;存储数据的仓库&#xff0c;本质文件&#xff0c;以文件的形式将数据保存到电脑磁盘中 数据库管理系统(DBMS)&…

postgresql 触发器如何生成递增序列号,从1开始,并且每天重置

大家好&#xff0c;我是三叔&#xff0c;许久不见&#xff0c;这期给大家介绍一下笔者在开发中遇到的业务处理&#xff1a;pgsql 创建触发器生成每日递增序列&#xff0c;并且第二天重置&#xff0c;根据不同的用户进行不同的控制。 1.创建生成递增序列的 table 表 -- 创建us…

springboot之拦截器、servlet过滤器

一 使用maven新建Spring Boot项目 1. File --> New --> Project... --> Maven &#xff0c;如下图所示 Project SDK下拉列表框中选择前面安装的 Java1.8&#xff0c;如果下拉列表框中不存在Java 1.8&#xff0c;可以单击New按钮&#xff0c;找到安装Java的位置&…

第02章-变量与运算符

1 关键字 关键字&#xff1a;被Java语言赋予了特殊含义&#xff0c;用作专门用途的字符串&#xff08;或单词&#xff09;。如class、public、static、void等&#xff0c;这些单词都被Java定义好了&#xff0c;称为关键字。 特点&#xff1a;关键字都是小写字母&#xff1b;官…

CSS与基本选择器

<div class"c1" id"d1"></div> CSS基本知识 什么是css&#xff1a;CSS&#xff08;Cascading Style Sheet&#xff0c;层叠样式表)定义如何显示HTML元素。 当浏览器读到一个样式表&#xff0c;他就会按照这个样式l来进行渲染。其实就是让HT…

Langchain-Chatchat项目:4.1-P-Tuning v2实现过程

常见参数高效微调方法(Parameter-Efficient Fine-Tuning&#xff0c;PEFT)有哪些呢&#xff1f;主要是Prompt系列和LoRA系列。本文主要介绍P-Tuning v2微调方法。如下所示&#xff1a; Prompt系列比如&#xff0c;Prefix Tuning(2021.01-Stanford)、Prompt Tuning(2021.09-Goo…

音视频rtsp rtmp gb28181在浏览器上的按需拉流

按需拉流是从客户视角来看待音视频的产品功能&#xff0c;直观&#xff0c;好用&#xff0c;为啥hls flv大行其道也是这个原因&#xff0c;不过上述存在的问题是延迟没法降到实时毫秒级延迟&#xff0c;也不能随心所欲的控制。通过一段时间的努力&#xff0c;结合自己闭环技术栈…

基于Java(SpringBoot框架)毕业设计作品成品(35)AI人工智能毕业设计AI图像卡通动漫化图像风格迁移系统设计与实现

博主介绍&#xff1a;《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff0c;免费 项…

Rust 语言常见的一些概念(下)

目录 1、函数 参数 语句和表达式 具有返回值的函数 2、注释 文档注释 多行注释 3、控制流 3.1 if 表达式 3.2 使用esle if 处理多重条件 3.3 在 let 语句中使用 if 3.4 使用循环重复执行 使用 loop 重复执行代码 从循环中返回值 循环标签&#xff1a;在多个循环…

【PyQt学习篇 · ⑨】:QWidget -控件交互

文章目录 是否可用是否显示/隐藏是否编辑是否为活跃窗口关闭综合案例信息提示状态提示工具提示“这是什么”提示 焦点控制单个控件角度父控件角度 是否可用 setEnabled(bool)&#xff1a;该函数用于设置QWidget控件的可用性&#xff0c;参数bool为True表示该控件为可用状态&…

08-Docker-网络管理

Docker 在网络管理这块提供了多种的网络选择方式&#xff0c;他们分别是桥接网络、主机网络、覆盖网络、MACLAN 网络、无桥接网络、自定义网络。 1-无桥接网络&#xff08;None Network&#xff09; 当使用无桥接网络时&#xff0c;容器不会分配 IP 地址&#xff0c;也不会连…