当前位置:   article > 正文

EasyPoi实现动态列的导入导出(固定列+自定义列)-横向(动态行头)+纵向-java

poi实现动态列

导入jar包

		<!-- 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能 -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.3.0</version>
        </dependency>

        <!--耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能 -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>4.3.0</version>
        </dependency>

        <!-- 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理 -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>4.3.0</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

easyPoi开发文档: easyPoi开发文档

纵向导入导出

项目需要导入导出数据,包含基本信息和规格参数List信息,最初采用easyPoi的注解导出,实现效果如下:

其中基本信息固定, 但产品尺寸信息List根据所属平台不同数量及名称不定

注解纵向合并实现效果

实体类

TbInstallProductVo对象纵向合并所用实体类注解:

注解实现纵向合并-TbInstallProductVo对象
在这里插入图片描述

除了@Excel注解, 主要使用了@ExcelCollection来实现导出集合的效果, 具体实现方法可以去官网查看

在这里插入图片描述

导出

 				//设置导出参数,获得工作簿,response返回
        ExportParams exportParams = new ExportParams("完美安装产品信息", "产品信息");
        Workbook wb = ExcelExportUtil.exportExcel(exportParams, TbInstallProductVo.class, list);
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("导出完美安装产品信息" + System.currentTimeMillis(), "UTF-8"));
            wb.write(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        IOUtils.closeQuietly(wb);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

导入

public AjaxResult importData(MultipartFile file, Boolean updateSupport) {
		//设置导入参数,
        ImportParams importParams = new ImportParams();
        //表格标题行数,默认0
        importParams.setTitleRows(1);
        //表头行数,默认1
        importParams.setHeadRows(2);
        List<TbInstallProductVo> productVoList;
        try {
            productVoList = ExcelImportUtil.importExcel(file.getInputStream(), TbInstallProductVo.class, importParams);
        } catch (Exception e) {
            throw new RuntimeException("读取excel数据异常null");
        }
        if (StringUtils.isNotEmpty(productVoList)) {
            //导入信息
            return importProductInfoAndParamInfo(updateSupport, productVoList);
        } else {
            return AjaxResult.error("导入数据不能为空!");
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

横向动态列导入导出(行头动态生成)

现在需要按平台分类将产品规格信息的动态List的参数名称横置为列名,参数值为数据,形成不同导入导出模板,,必须采用动态列进行导入导出,实现效果如下:
在这里插入图片描述

解决方案

Java反射机制根据@Excel注解获取需要的参数+动态拼装ExcelExportEntity实现List动态行头

其中:基于List 的导出,ExcelExportEntity是注解经过处理翻译成的实体类,两者几乎是一对的,所以如果我们要动态自定义导出列,我们只要动态拼装ExcelExportEntity就可以实现不固定参数, 由于行头的名称也是数据库读取内容, 因此需要用java反射获取参数名称字段的内容作为行头

模板类对象
在这里插入图片描述

导出

    public void export(HttpServletResponse response, Long[] ids) {
        try {
        	//业务数据查询
            List<TbInstallProductVo> productVoList = tbInstallProductInfoService.selectTbInstallProductInfoListForExportV1(ids);
            List<Map<String, Object>> dataList = new ArrayList<>();
            //数据转为List<map>导出
            if (StringUtils.isNotEmpty(productVoList)) {
                for (TbInstallProductVo productVo : productVoList) {
                	//将相同模板的数据以<名称,数据>的格式转为map,以数据和行头匹配
                    dataList.add(getExportDataMap(productVo));
                }
            }
            //构建该模板导出的行头
            List<ExcelExportEntity> excelExportEntities = getExcelExportEntityList();
            //数据导出
            Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("产品信息列表", "用户导入"), excelExportEntities, dataList);
            downLoadExcel("导出完美安装产品信息" + System.currentTimeMillis(), response, workbook);
        } catch (Exception e) {
            throw new ServiceException("导出失败" + e);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

根据类中注解通过反射构建行头

    private List<ExcelExportEntity> getExcelExportEntityList() throws Exception {
        Class<TbInstallProductVo> templateClass = TbInstallProductVo.class;
        //获取所有Excel注解的字段
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(templateClass, Excel.class);
        //获取参数值字段的注解
        Field parmaFiled = TbInstallParamInfoVo.class.getDeclaredField("paramName");
        List<ExcelExportEntity> excelExportEntities = new ArrayList<>();

        //获取基本信息导出-基本信息以Excel注解值为行头
        //@ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
        ExcelTarget etarget = (ExcelTarget) templateClass.getAnnotation(ExcelTarget.class);
        String targetId = etarget == null ? null : etarget.value();
        if (StringUtils.isNotEmpty(fields)) {
        			//循环带Excel注解的字段,获取Excel注解的name作为行头----固定的基本信息用此方式获取行头名称
            for (Field field : fields) {
                if (field.getAnnotation(Excel.class) != null) {
                    Excel excel = (Excel) field.getAnnotation(Excel.class);
                    String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null);
                    if (StringUtils.isNotBlank(name)) {
                    	//构建ExcelExportEntity
                        ExcelExportEntity excelExportEntity = this.createExcelExportEntity(field, targetId, templateClass, null, (ExcelEntity) null);
                        excelExportEntity.setKey(name);
                        excelExportEntities.add(excelExportEntity);
                    }
                }
            }
        }

        //根据模板动态加入需要导出的字段---动态列,行头名为数据paramName值
        //获取该模板的数据(业务)
        TbInstallTemplateParamInfo temParamParmas = new TbInstallTemplateParamInfo();
        temParamParmas.setTemplateId(-1L);
        List<TbInstallTemplateParamInfo> templateParamInfoList = tbInstallTemplateParamInfoMapper.selectTbInstallTemplateParamInfoList(temParamParmas);
        if (StringUtils.isNotEmpty(templateParamInfoList)) {
        	//循环模板的参数
            for (int i = 0; i < templateParamInfoList.size(); i++) {
            //判断参数名称字段是否存在有效注解
                if (parmaFiled.getAnnotation(Excel.class) != null) {
                    Excel excel = (Excel) parmaFiled.getAnnotation(Excel.class);
                    String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null);
                    if (StringUtils.isNotBlank(name)) {
                    	//存在注解,设置行头名称为参数值,并设置导出排序
                        ExcelExportEntity excelExportEntity = this.createExcelExportEntity(parmaFiled, targetId, TbInstallParamInfoVo.class, null, (ExcelEntity) null);
                        excelExportEntity.setName(templateParamInfoList.get(i).getParamName());
                        excelExportEntity.setOrderNum(fields.size() + i);
                        excelExportEntity.setKey(templateParamInfoList.get(i).getParamName());
                        excelExportEntities.add(excelExportEntity);
                    }
                }
            }
        }
        //返回固定列+该模板动态列格式
        return excelExportEntities;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

业务数据转为List<map>

    private Map<String, Object> getExportDataMap(TbInstallProductVo productVo) throws Exception {
        Class<TbInstallProductVo> templateClass = TbInstallProductVo.class;
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(templateClass, Excel.class);
        //获取参数值字段的注解
        Field parmaFiled = TbInstallParamInfoVo.class.getDeclaredField("paramName");
        Map<String, Object> map = new HashMap<>();

        //获取基本信息的数据
        ExcelTarget etarget = (ExcelTarget) templateClass.getAnnotation(ExcelTarget.class);
        String targetId = etarget == null ? null : etarget.value();
        if (StringUtils.isNotEmpty(fields)) {
            for (Field field : fields) {
                if (field.getAnnotation(Excel.class) != null) {
                    Excel excel = (Excel) field.getAnnotation(Excel.class);
                    String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null);
                    if (StringUtils.isNotBlank(name)) {
                        field.setAccessible(true);
                        map.put(name, ObjectValueUtils.getValue(field.get(productVo), field.getType()));
                    }
                }
            }
        }
        //根据productVo生成参数数据存入map
        if (StringUtils.isNotEmpty(productVo.getParamInfoVoList())) {
            for (int i = 0; i < productVo.getParamInfoVoList().size(); i++) {
                if (parmaFiled.getAnnotation(Excel.class) != null) {
                    Excel excel = (Excel) parmaFiled.getAnnotation(Excel.class);
                    String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null);
                    if (StringUtils.isNotBlank(name)) {
                   	 	//<参数名称,参数值>
                        map.put(productVo.getParamInfoVoList().get(i).getParamName(), productVo.getParamInfoVoList().get(i).getParamValue());
                    }
                }
            }
        }
        return map;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

导入

    public AjaxResult importData(MultipartFile file, Boolean updateSupport) {

        Class<TbInstallProductVo> importClass = TbInstallProductVo.class;
        List<Map<String, Object>> mapList = null;
        List<TbInstallProductVo> productVoList = new ArrayList<>();
        try {
            ImportParams importParams = new ImportParams();
            importParams.setTitleRows(1);
            importParams.setHeadRows(1);
            //获取导入的数据,按<行头,内容>格式
            mapList = ExcelImportUtil.importExcel(file.getInputStream(), Map.class, importParams);
        } catch (Exception e) {
            throw new RuntimeException("读取excel数据异常" + e);
        }
        if (StringUtils.isEmpty(mapList)) {
            throw new ServiceException("导入产品数据为空!");
        }
        //获取固定参数
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(importClass, Excel.class);
        ExcelTarget etarget = (ExcelTarget) importClass.getAnnotation(ExcelTarget.class);
        String targetId = etarget == null ? null : etarget.value();
        //根据模板动态加入需要导出的字段
        TbInstallTemplateParamInfo temParamParmas = new TbInstallTemplateParamInfo();
        temParamParmas.setTemplateId(-1L);
        List<TbInstallTemplateParamInfo> templateParamInfoList = tbInstallTemplateParamInfoMapper.selectTbInstallTemplateParamInfoList(temParamParmas);
        try {
            for (Map<String, Object> map : mapList) {
                //构建导入数据List
                TbInstallProductVo productVo = importClass.newInstance();
                //构建固定字段-固定字段以注解为行头
                if (StringUtils.isNotEmpty(fields)) {
                    for (Field field : fields) {
                        if (field.getAnnotation(Excel.class) != null) {
                            Excel excel = (Excel) field.getAnnotation(Excel.class);
                            String excelName = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null);
                            if (StringUtils.isNotBlank(excelName)) {
                                //设置允许访问,并强制类型转换解决解析类型冲突
                                field.setAccessible(true);
                  				//设置参数值为导入的数据
                                field.set(productVo, ObjectValueUtils.getValue(map.get(excelName), field.getType()));
                            }
                        }
                    }
                }
                //构建不定产品参数
                if (StringUtils.isNotEmpty(templateParamInfoList)) {
                    List<TbInstallParamInfoVo> paramInfoVoList = new ArrayList<>();
                    for (TbInstallTemplateParamInfo tempParamInfo : templateParamInfoList) {
                    //设置参数对象以构建自定义参数List
                        TbInstallParamInfoVo paramInfoVo = new TbInstallParamInfoVo();
                        paramInfoVo.setParamName(tempParamInfo.getParamName());
                        paramInfoVo.setParamCode(tempParamInfo.getParamCode());
                        paramInfoVo.setParamValue(String.valueOf(map.get(tempParamInfo.getParamName())));
                        paramInfoVoList.add(paramInfoVo);
                    }
                    productVo.setParamInfoVoList(paramInfoVoList);
                }
                productVoList.add(productVo);
            }
            log.info("完美安装导入的数据=={}", productVoList);
        } catch (Exception e) {
            throw new RuntimeException("数据解析错误,请检查数据内容" + e);
        }
        //导入数据-业务逻辑
        return tbInstallProductInfoServiceImpl.importProductInfoAndParamInfo(updateSupport, productVoList);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

参考: EasyPoi导入与导出_easypoi map格式导出_阿里巴巴P8资深技术专家的博客-CSDN博客

补充ObjectValueUtils工具类

import java.text.ParseException;
import java.util.Date;

/**
 * @author Shenpeng
 * @Date 2023/11/27/16:21
 * @Description
 */
public class ObjectValueUtils {
    /**
     * description 根据类型class转换类型值
     *
     * @param value:
     * @param type:
     * @return :Object
     */
    public static Object getValue(Object value, Class type) throws ParseException {
        if (value != null) {

            if (type.isAssignableFrom(String.class))
                return toString(value);
            if (type.isAssignableFrom(Integer.class) || type.isAssignableFrom(int.class))
                return toInteger(value);
            if (type.isAssignableFrom(Long.class) || type.isAssignableFrom(long.class))
                return toLong(value);
            if (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class))
                return toBoolean(value);
            if (type.isAssignableFrom(Double.class) || type.isAssignableFrom(double.class))
                return toDouble(value);
            if (type.isAssignableFrom(Date.class))
                return toDate(value);
            if (type.isAssignableFrom(String[].class))
                return toStringArray(value);
            if (type.isAssignableFrom(Integer[].class))
                return toIntegerArray(value);
        }
        return value;
    }

    private static String[] toStringArray(Object value) {
        return value.toString().split(",");
    }

    private static Integer[] toIntegerArray(Object value) {
        String[] stringArray = toStringArray(value);
        Integer[] intArray = new Integer[stringArray.length];
        for (int i = 0; i < stringArray.length; i++) {
            intArray[i] = Integer.parseInt(stringArray[i]);
        }
        return intArray;
    }

    private static Integer toInteger(Object value) {
        return Integer.parseInt(value.toString());
    }

    private static Long toLong(Object value) {
        return Long.parseLong(value.toString());
    }

    private static Double toDouble(Object value) {
        return Double.parseDouble(value.toString());
    }

    private static String toString(Object value) {
        return value.toString();
    }

    private static Date toDate(Object value) throws ParseException {
        return DateUtils.parseDate(value.toString(), DateUtils.YYYY_MM_DD);
    }

    private static Boolean toBoolean(Object value) {
        return Boolean.parseBoolean(value.toString());
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/584403
推荐阅读
相关标签
  

闽ICP备14008679号