Java 读取Excel导入数据库,形成树状结构

最近开发过程中遇到一个Excel的导入的功能,因为导入的数据结构具有层次结构,经过一番研究,最终得以实现,所有写下该文章,记录过程,供以后参考。

下图是导入Excel的数据结构:

使用POI解析Excel,数据封装然后进行入库。下面是核心代码。

java 复制代码
@Override
    public KnowledgeBaseDictImportRespVO importKnowledgeBaseDict(MultipartFile file) throws IOException {
        KnowledgeBaseDictImportRespVO kbdir = KnowledgeBaseDictImportRespVO.builder().build(); // 该对象是方法返回的结果对象
        Map<String,String> res = new ConcurrentHashMap<>();
        List<String> createProblemsList = new ArrayList<>();
        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        if(fileType.equals(".xls") || fileType.equals(".xlsx")) {
            AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getData();
            //poi解析excel
            InputStream inputStream = file.getInputStream();
            // 读取工作薄 .xls 与 .xlsx 需要创建不通的工作簿 采用工作簿工厂类创建对应的工作簿类
            Workbook workbook = WorkbookFactory.create(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            //获取系统名称
            Row row0 = sheet.getRow(0); // 第一行的表头
            Cell cell0 = row0.getCell(0); // 第一列
            String belongSystem = cell0.getStringCellValue().trim().replace("系统功能树","");
            if (StringUtils.isEmpty(belongSystem)) {
                res.put(StrUtils.getRandomString(6),"归属系统不能为空!");
                kbdir.setFailureProblems(res);
                return kbdir;
            }
            KnowledgeBaseDictDO kbdictdo = knowledgeBaseDictMapper.getKnowledgeBaseDictByParenetIdAndMenuName(0L,belongSystem);
            //定义一个cellId,此为每一次循环前一列的id
            long cellId = 0;
            String cellName = null; // 记录父级名称
            String firstMenuName = null; // 因为合并单元格只有第一个有值,需要记录该值。
            int count = 0;
            if (ObjectUtils.isEmpty(kbdictdo)) {
                kbdictdo = new KnowledgeBaseDictDO();
                kbdictdo.setSort(0);
                kbdictdo.setParentId(0L);
                kbdictdo.setMenuLevel(0);
                kbdictdo.setMenuName(belongSystem);
                kbdictdo.setBelongingSystem(belongSystem);
                kbdictdo.setCreator(adminUserRespDTO.getNickname());

                int rs = knowledgeBaseDictMapper.insert(kbdictdo);
                if (rs > 0) {
                    count += rs;
                    createProblemsList.add(belongSystem);
                    cellId = kbdictdo.getId();
                    cellName = kbdictdo.getMenuName();
                }
            }
            int rows = sheet.getPhysicalNumberOfRows();
            if (rows > 2) {
                //按照行进行循环,读取当前行的列
                for (int i = 0,j = 2; j < rows; j++,i++) {
                    // 读取行
                    Row row = sheet.getRow(j);
                    //查询当前行有多少列
                    int physical = sheet.getRow(j).getPhysicalNumberOfCells();
                    if (row != null) {
                        //获取第一列的单元格
                        Cell cell = row.getCell(0);
                        //判断单元格是否为空
                        if (!(cell == null || "".equals(cell.toString().trim()))) {
                            firstMenuName = cell.getStringCellValue().trim();
                            //根据单元格的数据查询数据库是否存在记录
                            KnowledgeBaseDictDO kbddoFirst = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(firstMenuName,1,belongSystem);
                            //数据库不存在,添加记录
                            if (ObjectUtils.isEmpty(kbddoFirst)) {
                                kbddoFirst = new KnowledgeBaseDictDO();
                                kbddoFirst.setSort(i);
                                kbddoFirst.setParentId(cellId);
                                kbddoFirst.setBelongingSystem(belongSystem);
                                kbddoFirst.setParentMenuName(cellName);
                                kbddoFirst.setMenuName(cell.getStringCellValue().trim());
                                kbddoFirst.setMenuLevel(1);
                                kbddoFirst.setCreator(adminUserRespDTO.getNickname());

                                int rs = knowledgeBaseDictMapper.insert(kbddoFirst);
                                if (rs > 0) {
                                    count += rs;
                                    createProblemsList.add(cell.getStringCellValue().trim());
                                    // 记录父级id 与 名称
                                    cellId = kbddoFirst.getId();
                                    cellName = kbddoFirst.getMenuName();
                                }
                            } else {
                                //数据库存在记录,将这条记录的id作为父id
                                cellId = kbddoFirst.getId();
                                cellName = kbddoFirst.getMenuName();
                            }
                        } else { // 表示循环到合并单元格的地方,查询数据库记录父级信息
                            if (StringUtils.isNotEmpty(firstMenuName)) {
                                KnowledgeBaseDictDO kbddoFirst = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(firstMenuName,1,belongSystem);
                                cellId = kbddoFirst.getId();
                                cellName = kbddoFirst.getMenuName();
                            }
                        }
                    }
                    // 从第二列单元格开始
                    for (int k = 1,l = 0; k < physical; k++,l++) {
                        //取单元格
                        Cell cell = row.getCell(k);
                        //判断单元格是否为空
                        if (!(cell == null || "".equals(cell.toString().trim()))) {
                            //查询数据库有无此记录
                            KnowledgeBaseDictDO kbddoSecond = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(cell.getStringCellValue().trim(),k + 1,belongSystem);
                            if (ObjectUtils.isEmpty(kbddoSecond)) {
                                kbddoSecond = new KnowledgeBaseDictDO();
                                kbddoSecond.setSort(l);
                                kbddoSecond.setParentId(cellId);
                                kbddoSecond.setBelongingSystem(belongSystem);
                                kbddoSecond.setParentMenuName(cellName);
                                kbddoSecond.setMenuName(cell.getStringCellValue().trim());
                                kbddoSecond.setMenuLevel(k+1);
                                kbddoSecond.setCreator(adminUserRespDTO.getNickname());

                                int rs = knowledgeBaseDictMapper.insert(kbddoSecond);
                                if (rs > 0) {
                                    count += rs;
                                    createProblemsList.add(cell.getStringCellValue().trim());
                                    // 记录父级id 与 名称
                                    cellId = kbddoSecond.getId();
                                    cellName = kbddoSecond.getMenuName();
                                }
                            } else {
                                cellId = kbddoSecond.getId();
                                cellName = kbddoSecond.getMenuName();
                            }
                            if (k == physical - 1) {
                                // 内层循环结束,表示一行的一级菜单结束,需要指定一级菜单的父级
                                cellId = kbdictdo.getId();
                                cellName = kbdictdo.getMenuName();
                            }
                        } else { // 如果为空,需要记录父级id与名称
                            cellId = kbdictdo.getId();
                            cellName = kbdictdo.getMenuName();
                        }
                    }
                }
            } else {
                res.put(StrUtils.getRandomString(6),"导入的数据不能为空!");
                kbdir.setFailureProblems(res);
                return kbdir;
            }
            kbdir.setCreateProblems(createProblemsList);
            kbdir.setFailureProblems(res);
        }
        return kbdir;
    }

该方法也适用于下面的Excel数据结构导入(未进行列合并单元格的数据结构):

树形结构数据如何高效封装,通过接口返回前端展示,请看我的另一篇文章。

Java 树形结构数据如何高效返回给前端进行展示?-CSDN博客

相关推荐
程序员小白条20 分钟前
你面试时吹过最大的牛是什么?
java·开发语言·数据库·阿里云·面试·职场和发展·毕设
折翅嘀皇虫28 分钟前
fastdds.type_propagation 详解
java·服务器·前端
小年糕是糕手31 分钟前
【C++】类和对象(二) -- 构造函数、析构函数
java·c语言·开发语言·数据结构·c++·算法·leetcode
豐儀麟阁贵33 分钟前
8.2异常的抛出与捕捉
java·开发语言·python
老华带你飞35 分钟前
社区养老保障|智慧养老|基于springboot+小程序社区养老保障系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序·毕设·社区养老保障
码龄3年 审核中35 分钟前
Linux record 03
java·linux·运维
q***876038 分钟前
springboot下使用druid-spring-boot-starter
java·spring boot·后端
程序员西西39 分钟前
SpringBoot无感刷新Token实战指南
java·开发语言·前端·后端·计算机·程序员
东南门吹雪40 分钟前
Spring的Bean相关
java·spring·bean·aop
q***697740 分钟前
Y20030018基于Java+Springboot+mysql+jsp+layui的家政服务系统的设计与实现 源代码 文档
java·spring boot·mysql