springboot+easypoi 动态导出excel表,动态定义表头

1:相关maven 依赖

easypoi 官方传送门http://easypoi.mydoc.io/#text_186900
springboot 相关依赖省略
easypoi 相关依赖


			cn.afterturn
			easypoi-base
			3.0.3
		
		
			cn.afterturn
			easypoi-web
			3.0.3
		
		
			cn.afterturn
			easypoi-annotation
			3.0.3

2:自己封装的工具类(关键 请看方法上带有注释的;不带注释的直接调用的是easypoi 的封装好的方法 )

package com.clouderwork.common.excel;


import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.clouderwork.contant.GlobalConstant;
import com.clouderwork.enums.YESNOEnum;
import com.clouderwork.params.order.ExportField;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author : heyanfeng
 * create at:  2019-05-27  19:11
 * @description: excel
 */
@Slf4j
public class ExcelUtils {
    public static void exportExcel(List list, String title, String sheetName, Class pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response){
        ExportParams exportParams = new ExportParams(title, sheetName);
        exportParams.setCreateHeadRows(isCreateHeader);
        defaultExport(list, pojoClass, fileName, response, exportParams);

    }
    public static void  exportExcel(List list, String title, String sheetName, Class pojoClass,String fileName, HttpServletResponse response){
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
    }
    public static void exportExcel(List> list, String fileName, HttpServletResponse response){
        defaultExport(list, fileName, response);
    }
    public static void exportExcel(String fileName,ExportParams exportParams, List entities,List> list,HttpServletResponse response){
        defaultExport(fileName,exportParams,entities,list,response);
    }

    private  static void defaultExport(String fileName,ExportParams exportParams, List entities,List> list,HttpServletResponse response ){
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, list);
        if (workbook != null);
        downLoadExcel(fileName, response, workbook);
    }

    private static void defaultExport(List list, Class pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams,pojoClass,list);
        if (workbook != null);
        downLoadExcel(fileName, response, workbook);
    }

    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("excel异常:{}",e.getMessage());
        }
    }
    private static void defaultExport(List> list, String fileName, HttpServletResponse response) {
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        if (workbook != null);
        downLoadExcel(fileName, response, workbook);
    }
    public static  List importExcel(String filePath, Integer titleRows, Integer headerRows, Class pojoClass){
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List list = null;
        try {
            File file = new File(filePath);
            list = ExcelImportUtil.importExcel(file, pojoClass, params);
        }catch (NoSuchElementException e){
            throw new IllegalArgumentException("模板不能为空");
        } catch (Exception e) {
            log.error("excel异常:{}",e.getMessage());
        }
        return list;
    }

    public static  List importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, Class pojoClass){
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List list = null;
        try {
            list = ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        }catch (NoSuchElementException e){
            throw new IllegalArgumentException("模板不能为空");
        } catch (Exception e) {
            log.error("excel异常:{}",e.getMessage());
        }
        return list;
    }
    public static  List importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class pojoClass){
        if (file == null){
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
        }catch (NoSuchElementException e){
            throw new IllegalArgumentException("excel文件不能为空");
        } catch (Exception e) {
            log.error("excel异常:{}",e.getMessage());
        }
        return list;
    }


    /**
     * description: 动态生成excel 列
     * create by heyanfeng at 2019-05-29 18:02
     * @param ef
     * @param entities
     */
    public static void dynamicNewAddExcel(List ef, List entities) {
        //单元格的excel 表头
        ef.forEach(item -> {
            //需要合并单元格的表头
            List children = item.getChildren();
            if(!CollectionUtils.isEmpty(children)){
                ExcelExportEntity parent = new ExcelExportEntity(item.getFiledChineseName(), item.getEntityAttrName());
                List entitiesChildren = Lists.newArrayList();
                children.forEach(e -> {
                    entitiesChildren.add(new ExcelExportEntity(e.getFiledChineseName(),e.getEntityAttrName(),30));
                });
                parent.setNeedMerge(true);
                parent.setList(entitiesChildren);
                entities.add(parent);
            }else{
                entities.add(new ExcelExportEntity(item.getFiledChineseName(),item.getEntityAttrName(),30));
            }
        });
    }


    /**
     * description: 根据属性名称 获取属性的值
     * create by heyanfeng at 2019-05-29 19:26
     * @return Object
     * @param fieldName
     * @param o
     */
     public static  Object getFieldValueByName(String fieldName,Object o){
        try{
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[]{});
            return  value;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
    }

    /**
     * description: 组装excel 数据
     * create by heyanfeng at 2019-05-29 20:30
     * @return  List>
     * @param ef
     * @param statisData
     */
    public static List> dynamicListDataByKey(List ef, List statisData) {
        //最终的数据
        List> datas = new ArrayList<>();
        Map map;
        for (Object t : statisData) {
            map = new HashMap();
            for (int j = 0; j < ef.size(); j++) {
                List children = ef.get(j).getChildren();
                if(!CollectionUtils.isEmpty(children)){
                   //遍历需要合并单元格的子列
                    traversechildren(map, t, children,ef.get(j).getEntityAttrName());
                }else if(StringUtils.isNotBlank(ef.get(j).getEntityAttrName())){
                    map.put(ef.get(j).getEntityAttrName(),getFieldValueByName(ef.get(j).getEntityAttrName(),t));
                }
            }
            datas.add(map);
        }
        return datas;
    }

    /**
    * description: 遍历需要合并单元格的子列
    * create by heyanfeng at 2019-05-31 14:19
    */
    private static void traversechildren(Map map, Object t, List children,String entityAttrName) {
        ArrayList> childrenMaps = Lists.newArrayList();
        Map childrenMap= new HashMap();
        for (int k = 0; k < children.size(); k++) {
            if(StringUtils.isNotBlank(children.get(k).getEntityAttrName())){
                childrenMap.put(children.get(k).getEntityAttrName(),getFieldValueByName(children.get(k).getEntityAttrName(),t));
            }
        }
        childrenMaps.add(childrenMap);
        map.put(entityAttrName,childrenMaps);
    }


    /**
    * description: 组装sql 查询条件
    * create by heyanfeng at 2019-05-30 10:09
    */
    public static String getExcelSql(List exportField) {
        String fileds;
        StringBuilder stringBuilder = new StringBuilder();
        exportField.forEach(item -> {
            //如果存在需要合并表头的列 则遍历
            List children = item.getChildren();
            if(!CollectionUtils.isEmpty(children)){
                children.forEach(e -> {
                    if(StringUtils.isNotBlank(e.getFiled())){
                        stringBuilder.append(e.getFiled() + GlobalConstant.PIC_SPLIT);
                    }
                });
            }else if(StringUtils.isNotBlank(item.getFiled())){
                stringBuilder.append(item.getFiled() + GlobalConstant.PIC_SPLIT);
            }
        });
        stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(GlobalConstant.PIC_SPLIT));
        fileds = stringBuilder.toString();
        return fileds;
    }

    /**
     * description: 组装sql 查询条件
     * create by heyanfeng at 2019-05-30 10:09
     */
    public static String getGroupBySql(List exportField) {
        String fileds;
        //是否加入 group by
        Boolean[] flag = {false};
        StringBuilder stringBuilder = new StringBuilder();
        exportField.forEach(item -> {
            if(item.getGroupBy() == null && StringUtils.isNotBlank(item.getFiled())){
                stringBuilder.append(item.getFiled() + GlobalConstant.PIC_SPLIT);
            }else if(item.getGroupBy() != null  && item.getGroupBy() == YESNOEnum.YES.getValue()){
                flag[0] = true;
            }
        });
        stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(GlobalConstant.PIC_SPLIT));
        fileds =  stringBuilder.toString();
        if (flag[0]){
            fileds =   " group by " + fileds;
            return  fileds;
        }
        return "";
    }


    /**
    * description: 检查导出字段是否为空
    * create by heyanfeng at 2019-05-30 10:10
    */
    public  static void checkExportField( List exportField) {
        if(CollectionUtils.isEmpty(exportField)){
            throw new IllegalArgumentException("导出的字段不能为空");
        }
    }

    /**
    * description: 动态导出生成excel
    * create by heyanfeng at 2019-05-30 10:37
    */
    public static void DynamicExcel(String fileName, String title,String sheet,List exportField, HttpServletResponse response, List list) {
        //生成动态列
        List entities = Lists.newArrayList();
        ExcelUtils.dynamicNewAddExcel(exportField, entities);
        //组装数据entities
        List> maps = ExcelUtils.dynamicListDataByKey(exportField, list);
        ExcelUtils.exportExcel(fileName,new ExportParams(title, sheet),entities,maps,response);
    }
}

3:动态表头相关的参数bean

package com.clouderwork.params.order;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

import java.util.List;

/**
 * @program family_dr_api
 * @description: 管理后台患者订单
 * @author: luqiang
 * @create: 2019/05/24 19:14
 */
@ApiModel(value = "管理后台患者订单")
@Data
public class BackPatientOrderParam {
    @ApiModelProperty("导出字段,逗号分割")
    private List exportField;
}

ExportField.class

package com.clouderwork.params.order;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * @author : heyanfeng
 * create at:  2019-05-27  22:00
 * @description:
 */
@ApiModel(value = "管理后台患者订单导出的字段")
@Data
public class ExportField {

    @ApiModelProperty("实体映射的字段")
    private String entityAttrName;

    @ApiModelProperty("导出字段,中文描述")
    private String filedChineseName;

    @ApiModelProperty("组装sql 字段")
    private String filed;

    @ApiModelProperty("sql-group-by去除字段:0 否 1是")
    private Integer groupBy;

    @ApiModelProperty("合并单元格")
    private List  children;
}

4:demo 演示

controller

    public void  serviceExport(@Valid @RequestBody BackPatientOrderParam backPatientOrderParam)  {
        serviceOrderService.serviceExport(backPatientOrderParam);
    }

service

 public void serviceExport(BackPatientOrderParam params) {
       //根据传递的sql 参数动态组装查询的字段
        String fileds = ExcelUtils.getExcelSql(params.getExportField());
        // 获取response 
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //数据请替换自己业务的数据
                  List list = serviceOrderMapperExt.serviceExport(startYear, endYear,
                params.getServiceName(), params.getDoctorName(),
                params.getDoctorGroupId(), params.getOrderStatus(),
                startPayTime, endPayTime, startCompleteTime, endCompleteTime,
                params.getProvinceCode(), params.getCityCode(),
                params.getCountyCode(), params.getRecommendUserName(), fileds);
        ExcelUtils.DynamicExcel("服务订单" + new DateTime().toString("yyyy-MM-dd") + ".xlsx", null,
                "sheet1", params.getExportField(), response, list);
    }

前端传过来的参数
说明(指定 children可以 合并单元格)多个字段驻向数组中追加

export const filedData = [{
    "entityAttrName": "orderNo",
    "value": "a.order_no",
    "filed": "a.order_no",
    "filedChineseName": "订单号码"
  },
  {
    "entityAttrName": "merge",
    "filed": "",
    "value": "",
    "filedChineseName": "基础服务费",
    "children": [{
        "entityAttrName": "basePrice",
        "filed": "d.base_price",
        "value": "d.base_price",
        "filedChineseName": "基础服务费"
      } ]
  }
]

你可能感兴趣的:(springboot+easypoi 动态导出excel表,动态定义表头)