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
    @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 wjl
 * @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复杂表头数据导入

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于复杂动态表头导出,你可以使用 EasyExcel 来实现。EasyExcel 是一个基于 Java 的 Excel 操作工具,可以用于读取、写入和操作 Excel 文件。 下面是一个示例代码,演示如何使用 EasyExcel 导出带有复杂动态表头的 Excel 文件: ```java // 创建 ExcelWriter 对象 ExcelWriter excelWriter = EasyExcel.write("output.xlsx").build(); // 定义表头数据 List<List<String>> header = new ArrayList<>(); header.add(Arrays.asList("姓名", "年龄", "性别")); header.add(Arrays.asList("科目", "语文", "数学", "英语")); // 导出数据 List<List<Object>> data = new ArrayList<>(); data.add(Arrays.asList("张三", 20, "男", 80, 90, 85)); data.add(Arrays.asList("李四", 22, "女", 75, 85, 90)); // 动态合并表头单元格 int firstRow = 0; int lastRow = firstRow + header.size() - 1; int firstCol = 0; int lastCol = firstCol + header.get(header.size() - 1).size() - 1; excelWriter.getOrCreateSheet("Sheet1") .head(header) .relativeMerge(firstRow, lastRow, firstCol, lastCol) .doWrite(data); // 关闭 ExcelWriter 对象 excelWriter.finish(); ``` 在上面的示例中,我们创建了一个 ExcelWriter 对象,并指定输出文件为 "output.xlsx"。然后,我们定义了表头数据和导出数据,并调用 EasyExcel 提供的方法动态合并表头单元格。最后,我们调用 `doWrite` 方法将数据写入到 Excel 文件中。 需要注意的是,上面的示例仅演示了如何导出简单的动态表头,如果你的表头更加复杂,你可能需要自行进行逻辑处理来生成动态表头数据。 希望这个示例能对你有所帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值