用EasyExcel动态导出列

最近要实现一个导出Excel,实现动态列导出,记录一下

数据的大概结构如下

用EasyExcel动态导出列_第1张图片

要实现如果总分数大于0 那么要把原因下的具体原因 作为表头 ,值则是原因下的分数,有多个原因就加入多少个,最终结果如下

首先把当前所有数据的全部的原因加入到set中去重,再转为List

Set set = new HashSet<>();
        for (VO vo : VOS) {
            for (GroupVo groupVo : vo.getGroupVos()) {
                //把具体原因名称放到set内去重
                if (groupVo.getGroupName()!=null) {
                    set.add(groupVo.getGroupName());
                }
            }
        }
 List strings = new ArrayList<>(set);

再把去重后的具体原因存到List

@Data
@Builder
public class HeadVO implements Comparable{
    /**
     * 列头名
     */
    private List headTitle;
    /**
     * 字段名
     */
    private String key;
    /**
     * 主排序
     */
    private int index;
   

    @Override
    public int compareTo(HeadVO o) {
        return this.index - o.getIndex(); 
    }
}
List headVOS = new ArrayList<>();
        int j = 0;
        for ( ;j < strings.size(); j++) {
            headVOS.add(HeadVO.builder().headTitle(Arrays.asList("具体原因",strings.get(j))).index(3+j+1).key(strings.get(j)).build());
//index是3加一的原因是我前面还有四个字段
        }
        headVOS.add(HeadVO.builder().headTitle(Arrays.asList("总分","总分")).index(4+j+2).key("score").build());

excelHelper(response,VO.class,headVOS,keysAndValues);

最终导出

/**
     * 动态导出列
     * @param entityClass 实体类的class对象
     * @param customizeHeads 要动态生成的表头
     * @param list  查出的数据
     * @author furao
     */
    public void excelHelper(HttpServletResponse response,Class entityClass, List customizeHeads, List> list,int moum, int year ){
        //获取声明字段
        Field[] fields = entityClass.getDeclaredFields();
        // 获取类的注解

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            ReflectionUtils.makeAccessible(field);// 设置些属性是可以访问的
            //判断当前字段注解是否ExcelProperty
            boolean annotationPresent = field.isAnnotationPresent(ExcelProperty.class);
            if (annotationPresent) {
                //获取注解
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                //获取注解内的值变为表头
                List head = Arrays.asList(excelProperty.value());
                //获取第几个下标
                int index = excelProperty.index();
                //添加 表头  下标   字段名称
                HeadVO headVO = HeadVO.builder().headTitle(head).index(index).key(field.getName()).build();
                //添加到集合内
                customizeHeads.add(headVO);
            }
        }
        //按照下标排序
        Collections.sort(customizeHeads);
        //定义一个list 存放所有表头
        List> heads = new ArrayList<>();
        //存放字段名
        List keys = new ArrayList<>();
        //一共有多少个表头循环多少次
        for (int i = 0; i <= customizeHeads.size() - 1; i++) {
            //获取每一个表头的名称
            heads.add(customizeHeads.get(i).getHeadTitle());
            //获取每一个表头的字段名
            keys.add(customizeHeads.get(i).getKey());
        }
        //存放所有导出的数据
        List> objs = new ArrayList<>();
        //循环数据
        list.forEach(e -> {
            //
            List obj = new ArrayList<>();
            //把每个数据内的groupVos数组取出来
            List groupVos= (List) e.get("groupVos");
            List> keysAndValues = getKeysAndValues(acpRuleGroupVos); 
  //List转为List>
            //循环每个字段
            for (int i = 0; i < keys.size(); i++) {
                //在数据集合中找到每个字段相对应的值并添加 一一对应
                Object o = e.get(keys.get(i));
                //数据为null,当前keys.get(i)可能是具体原因
                if (o==null){
                    boolean add=false;
                    //循环当前数据下的GroupVos数组
                    for (int j = 0; j < keysAndValues.size(); j++) {
                        Map map = keysAndValues.get(j);
                        //把具体原因取出来
                        Object GroupName= map.get("GroupName");
                        //判断GroupName值(具体原因)是否跟当前key相等
                        if (GroupName.equals(keys.get(i))){
                            //相等置为true
                            add=true;
                            //相等把得分获取到 直接返回
                            Object score = map.get("score");
                            obj.add(score);
                            break;
                        }
                    }
                    //GroupVos数组循环结束还未添加数据表示此数据内不存在当前的原因补0
                    if (!add) {
                        obj.add(0);
                    }
                }else {
                    obj.add(o);
                }
            }
            //添加数据到集合中
            objs.add(obj);
        });

        try {
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            //设置下载信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            //这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName =  "分数明细.xlsx";
            String encode = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + encode + ".xlsx");

            //设置头字体
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 13);
            headWriteFont.setBold(true);
            headWriteCellStyle.setWriteFont(headWriteFont);
            //设置头居中
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

            //内容策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            //设置 水平居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);


            EasyExcel.write(response.getOutputStream())
                    .head(heads)
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .sheet("明细")
                    .doWrite(objs);
        } catch (IOException e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map map = new HashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            log.info("导出文件失败");
            try {
                response.getWriter().println(JSON.toJSONString(map));
            } catch (IOException ioException) {
                log.info("IO异常");
            }
        }
    }

由于我们查询到的数据大部分都是List,但是这个方法需要的结果数据是List>

在提供一份List转List>

 /**
     * List转为List
     * @param object
     * @return
     * @author furao
     */
    public static List> getKeysAndValues(List object) {
        List> list = new ArrayList>();
        for (Object obj : object) {
            Class userCla;
            // 得到类对象
            userCla = obj.getClass();
            /* 得到类中的所有属性集合 */
            Field[] fs = userCla.getDeclaredFields();
            Map listChild = new HashMap();
            for (int i = 0; i < fs.length; i++) {
                Field f = fs[i];
                ReflectionUtils.makeAccessible(f);// 设置些属性是可以访问的
                Object val = new Object();
                try {
                    val = f.get(obj);
                    // 得到此属性的值
                    listChild.put(f.getName(), val);// 设置键值
                } catch (IllegalArgumentException e) {
                    log.info("非法参数异常");
                } catch (IllegalAccessException e) {
                    log.info("非法访问异常");
                }
            }
            list.add(listChild);// 将map加入到list集合中
        }
        log.info("多个(列表)对象的所有键值====" + list.toString());
        return list;
    }

你可能感兴趣的:(java,excel)