Java导出Excel模板,导出数据到指定模板,通过模板导入数据(二)

Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)已经讲述了一般Excel的导入导出,此处就不在额外讲述了。这篇来讲述合并操作,仅以列合并示例。

1. 导出模板

这个和Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)的讲述的导出模板是一样的

2. 导出数据到模板中

2.1 首先自己制造一个导出的excel模板,模板和Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)讲述的模板一样,而合并单元格是通过代码实现的。

2.2  导出数据接口编写

/**
     * 导出数据
     *
     * @param excelParam 导出入参
     * @param response   HttpServletResponse对象
     * @throws Exception 导出异常
     */
    @PostMapping(value = "/export", produces = "application/octet-stream")
    public void export(@RequestBody @Validated TeamsExcelParam excelParam, HttpServletResponse response) throws Exception {
        List<Teams> resultList = teamsService.list(excelParam);

        String title = "班组";
        Map<String, Object> outerMap = new HashMap<>(2);
        outerMap.put("title", title);

        List<TeamsPersonnel> children = new ArrayList();
        if (resultList.size() > 0) {
            List<String> dataIds = resultList.stream().map(Teams::getDataId).collect(Collectors.toList());
            //查询所有的子
            children = teamsPersonnelService.listByTeamsIds(dataIds);
        }

        List<Map<String, Object>> innerMapList = new ArrayList<>();
        Teams item;
        for (int i = 0; i < resultList.size(); ++i) {
            item = resultList.get(i);
            Map<String, Object> innerMap;
            for (TeamsPersonnel child : children) {
                if (item.getDataId().equals(child.getTeamsId())) {
                    innerMap = new HashMap<>(16);
                    innerMap.put("index", i + 1);
                    innerMap.put("teamsName", item.getTeamsName());
                    innerMap.put("unitName", item.getUnitName());
                    innerMap.put("departmentName", item.getDepartmentName());
                    innerMap.put("teamsDescriptionName", child.getTeamsDescriptionName());
                    innerMap.put("fullName", child.getFullName());
                    innerMapList.add(innerMap);
                }
            }
        }

        int mergeRowIndex = 2;
        int[] mergeColumnIndex = {0, 1, 2, 3};
        ExcelFillCellMergeStrategyUtils excelFillCellMergeStrategyUtils = new ExcelFillCellMergeStrategyUtils(mergeRowIndex, mergeColumnIndex);

        ExcelUtils.exportToTemplate(response, "excel/班组管理导出模板.xlsx", title, outerMap, innerMapList, null, excelFillCellMergeStrategyUtils);
    }

说明:

for循环中进行数据处理,子不同,父可能会有很多相同的。

mergeRowIndex = 2 是指行的下标(下标从0开始)。从第二行开始对相同数据进行合并操作。

 mergeColumnIndex = {0, 1, 2, 3} 是指要合并的列的下标(下标从0开始)。

 具体列的合并逻辑见Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)中的工具类 ExcelFillCellMergeStrategyUtils.java 中的mergeWithPrevRow方法。

3. 数据导入

3.1 创建数据导入模板

导入模板的下载见 Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)

3.2 创建数据导入监听类

数据的校验全部放在监听类中进行处理,如需要用的其他业务参数,直接通过在controller中实例化该监听类时传递到构造方法中。

TeamsReadExcelListener.java
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Cell;
import com.lonzh.util.excel.ExcelUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 班组数据导入监听
 *
 * @author DaiHaijiao
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class TeamsReadExcelListener extends AnalysisEventListener {

    /**
     * 解析的数据集合
     */
    List<Teams> dataList = new ArrayList();

    /**
     * 班组职位字典数据
     */
    static List<DictData> dictDataList;

    /**
     * 部门及人员信息
     */
    static List<DepartmentWithUserDTO> departmentUserList;

    public static TeamsReadExcelListener newBean(List<DictData> dictDatas, List<DepartmentWithUserDTO> deptUserList) {
        departmentUserList = deptUserList;
        dictDataList = dictDatas;
        return new TeamsReadExcelListener();
    }

    /**
     * 读取excel每一行都会触发本方法
     *
     * @param data    行数据
     * @param context AnalysisContext
     */
    @SneakyThrows
    @Override
    public void invoke(Object data, AnalysisContext context) {
        Teams excelData = new Teams();
        // 当前数据行号,从0开始
        Integer rowIndex = context.readRowHolder().getRowIndex();
        // 获取行中每一列数据
        Map<Integer, Cell> cellMap = context.readRowHolder().getCellMap();

        String rowNo = cellMap.get(0) + "";
        boolean ifNeedCheckParent = true;
        if (dataList.size() > 0) {
            Teams excelDataTemp = dataList.get(dataList.size() - 1);
            //rowNo是临时添加的字段仅用户导入时的业务判断处理(数据库并没有此字段)
            if (rowNo.equalsIgnoreCase(excelDataTemp.getRowNo()) || "null".equalsIgnoreCase(rowNo)) {
                //当前添加的是子
                ifNeedCheckParent = false;
                excelData = dataList.get(dataList.size() - 1);
            }
        }

        LinkedHashMap dataTemp = (LinkedHashMap) data;
        for (int i = 0; i < dataTemp.size(); i++) {
            this.parseColumnData(rowIndex, i, dataTemp.get(i), excelData, ifNeedCheckParent);
        }

        if (ifNeedCheckParent) {
            // 解析完一行数据后,添加到集合中
            dataList.add(excelData);
        }
    }

    /**
     * 解析列值
     *
     * @param rowIndex          行号
     * @param columnIndex       列号
     * @param columnData        列值,object类型
     * @param excelData         实例对象
     * @param ifNeedCheckParent 是否需要校验父属性
     * @throws Exception 逻辑异常
     */
    private void parseColumnData(Integer rowIndex, Integer columnIndex, Object columnData, Teams excelData, boolean ifNeedCheckParent) throws Exception {
        // 逐列判断并使用正确的类型接收value,列号从0开始
        if (columnIndex == 0 && ifNeedCheckParent) {
            //rowNo是临时添加的字段仅用户导入时的业务判断处理(数据库并没有此字段)
            excelData.setRowNo(ExcelUtils.getStringValue(columnData));
        } else if (columnIndex == 1 && ifNeedCheckParent) {
            //班组名称
            excelData.setTeamsName(ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组名称", 64, null));
        } else if (columnIndex == 2 && ifNeedCheckParent) {
            //所属部门
            String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "所属部门", null, null);
            DepartmentWithUserDTO departmentWithUser = departmentUserList.stream().filter(item -> value.equals(item.getDepartmentName())).findFirst().orElse(null);
            if (null == departmentWithUser) {
                throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,所属部门[" + value + "]有误(该部门不属于当前登录用户所属公司)");
            }
            excelData.setDepartment(departmentWithUser.getDataId());
            excelData.setDepartmentName(departmentWithUser.getDepartmentName());
            excelData.setUnitId(departmentWithUser.getParentId());
        } else if (columnIndex == 3 && ifNeedCheckParent) {
            //班组职责描述
            excelData.setTeamsDescription(ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组职责描述", 1024, null));
        } else {
            List<TeamsPersonnel> children = excelData.getDetailList();
            if (null == children) {
                children = new ArrayList<>();
            }
            //子的数据
            if (columnIndex == 4) {
                //班组职位
                String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组职位", null, null);
                DictData dictData = dictDataList.stream().filter(item -> value.equals(item.getDictLabel())).findFirst().orElse(null);
                if (null == dictData) {
                    throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,班组职位[" + value + "]有误");
                }
                TeamsPersonnel child = new TeamsPersonnel();
                child.setTeamsDescription(dictData.getDataId());
                children.add(child);
            } else if (columnIndex == 5) {
                //人员姓名
                String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "工号", 30, null);
                List<UserSelect> userList = new ArrayList();
                departmentUserList.forEach(item -> {
                    if (Arrays.asList(3, 4, 5).contains(item.getDepartmentType())) {
                        userList.addAll(item.getUserList());
                    }
                });
                UserSelect user = userList.stream().filter(item -> value.equals(item.getFullname())).findFirst().orElse(null);
                if (null == user) {
                    throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列人员姓名[" + value + "]有误(该姓名不属于该部门)");
                }
                TeamsPersonnel child = children.get(children.size() - 1);
                child.setEmployeeId(user.getDataId());
            }
            excelData.setDetailList(children);
        }
    }

    /**
     * excel解析后置处理器,在excel解析完成后执行一次
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("excel解析后置处理器");
    }
}

3.3 数据导入接口编写

/**
     * 导入数据
     *
     * @param file excel文件
     * @return 是否成功
     */
    @PostMapping("/import")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Object importExcel(@RequestParam("file") @NotNull MultipartFile file) {
        Map<String, String> map = new HashMap<>(8);
        //班组职位字典数据
        List<DictData> dictDataList = dictDataService.queryDataByType("TEAM_POSITIONS");
        //获取当前公司id
        String departmentId = departmentService.getNowUserDepartmentsId();
        //查询部门及相关下的人
        List<DepartmentWithUserDTO> departmentUserList = departmentService.listDeptWithUsers(departmentId);
        TeamsReadExcelListener excelListener = TeamsReadExcelListener.newBean(dictDataList, departmentUserList);
        try {
            EasyExcel.read(file.getInputStream()).sheet(0).headRowNumber(1).registerReadListener(excelListener).doRead();
        } catch (Exception e) {
            e.printStackTrace();
            map.put("code", "100");
            map.put("msg", "请求失败");
            return map;
        }
        List<Teams> dataList = excelListener.getDataList();
        if (dataList.size() == 0) {
            map.put("code", "500");
            map.put("msg", "导入数据不能为空");
            return map;
        }

        boolean result = true;
        int baseY = 100;
        int y = dataList.size() / baseY + 1;
        int z = dataList.size() % 100;
        for (int i = 0; i < y; i++) {
            if (i != y - 1) {
                result = teamsService.insertMore(dataList.subList(i * baseY, (i + 1) * baseY));
            } else {
                result = dataList.subList(i * baseY, i * baseY + z).size() == 0 ? true : teamsService.insertMore(dataList.subList(i * baseY, i * baseY + z));
            }
            if (!result) {
                map.put("code", "500");
                map.put("msg", "数据导入失败");
                return map;
            }
        }

        List<TeamsPersonnel> itemList = new ArrayList();
        for (Teams item : dataList) {
            item.getDetailList().forEach(personnel -> {
                personnel.setTeamsId(item.getDataId());
            });
            itemList.addAll(item.getDetailList());
        }
        y = itemList.size() / baseY + 1;
        z = itemList.size() % 100;
        for (int i = 0; i < y; i++) {
            if (i != y - 1) {
                result = teamsPersonnelService.insertMore(itemList.subList(i * baseY, (i + 1) * baseY));
            } else {
                result = itemList.subList(i * baseY, i * baseY + z).size() == 0 ? true : teamsPersonnelService.insertMore(itemList.subList(i * baseY, i * baseY + z));
            }
            if (!result) {
                map.put("code", "500");
                map.put("msg", "数据导入失败");
                return map;
            }
        }
        map.put("code", "200");
        map.put("msg", "请求成功");
        return map;
    }

列合并操作的简单使用大致如上,可以参考学习使用。

猜你喜欢

转载自blog.csdn.net/Dai_Haijiao/article/details/128930155