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

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

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

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

@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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/725605.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

理解 ICMP 报文:网络故障排查的重要工具

文章目录 什么是 ICMP&#xff1f;ICMP 报文类型ICMP “Destination Unreachable” 报文实例解析&#xff1a;端口不可达ICMP 报文的生成和处理解决方案结语 在网络通信中&#xff0c;ICMP&#xff08;Internet Control Message Protocol&#xff0c;互联网控制消息协议&#x…

支持向量机 (SVM) 算法详解

支持向量机 (SVM) 算法详解 支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种监督学习模型&#xff0c;广泛应用于分类和回归分析。SVM 特别适合高维数据&#xff0c;并且在处理复杂非线性数据时表现出色。本文将详细讲解 SVM 的原理、数学公式、应用场景…

安装cuda、cudnn、Pytorch(用cuda和cudnn加速计算)

写在前面 最近几个月都在忙着毕业的事&#xff0c;好一阵子没写代码了。今天准备跑个demo&#xff0c;发现报错 AssertionError: Torch not compiled with CUDA enabled 不知道啥情况&#xff0c;因为之前有cuda环境&#xff0c;能用gpu加速&#xff0c;看这个报错信息应该是P…

基于百度飞桨PaddleOCR应用开发实践银行卡卡面内容检测识别系统

OCR相关的内容我在之前的工作中虽有所涉及&#xff0c;但是还是比较少的&#xff0c;最近正好需要用到OCR的一些技术&#xff0c;查了一些资料&#xff0c;发现国内的话百度这块做的还是比较全面系统深入的&#xff0c;抱着闲来无事学习了解的心态&#xff0c;这里花了点时间基…

八大排序————C语言版实现

Hello&#xff0c;各位未来的高级程序员们&#xff0c;大家好&#xff0c;今天我就来为大家讲解一下有关排序的内容&#xff0c;我们常见的排序就是我们接下来要讲的这八个排序&#xff0c;我们平常所说的排序有十大排序&#xff0c;我们这里的八大排序是我们生活中最为常见的八…

h5兼容问题 复制粘贴移动端无法粘贴复制内容

const selectText (textbox, startIndex, stopIndex) > {if (textbox.createTextRange) {//ieconst range textbox.createTextRange();range.collapse(true);range.moveStart(character, startIndex);//起始光标range.moveEnd(character, stopIndex - startIndex);//结束光…

西门子PLC1200--与电脑连接的TCP通讯

本例演示将PLC作为服务器&#xff0c;电脑作为客户端&#xff0c;进行通讯。 反过来也是一回事&#xff0c;就不啰嗦了。 二者进行TCP通讯&#xff0c;是基于网线的&#xff0c;电脑上用的是网口&#xff0c;PLC上用的是Profinet接口&#xff0c;即PN口。 软件工具准备 西门子…

SQL注入-下篇

HTTP注入 一、Referer注入 概述 当你访问一个网站的时候&#xff0c;你的浏览器需要告诉服务器你是从哪个地方访问服务器的。如直接在浏览器器的URL栏输入网址访问网站是没有referer的&#xff0c;需要在一个打开的网站中&#xff0c;点击链接跳转到另一个页面。 Less-19 判…

【Java面试】二十一、JVM篇(中):垃圾回收相关

文章目录 1、类加载器1.1 什么是类加载器1.2 什么是双亲委派机制 2、类装载的执行过程&#xff08;类的生命周期&#xff09;3、对象什么时候可以被垃圾回收器处理4、JVM垃圾回收算法4.1 标记清除算法4.2 标记整理算法4.3 复制算法 5、分代收集算法5.1 MinorGC、Mixed GC、Full…

java:动态代理和cglib代理的简单例子

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89457803 # 项目代码 【pom.xml】 <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version&…

ATA-2032高压放大器设计要求是什么内容

高压放大器是一种专门用于放大高电压信号的电子设备。它在许多领域都具有重要的应用&#xff0c;例如在医疗设备、科学研究、传感器驱动和测试测量等方面。设计一个高压放大器需要考虑多个因素&#xff0c;包括性能要求、安全性、稳定性和可靠性等方面。下面我们将详细讨论高压…

vxe-table 列表过滤踩坑_vxe-table筛选

但是这个过滤输入值必须是跟列表的值必须一致才能查到&#xff0c;没做到模糊查询的功能&#xff0c;根据关键字来过滤并没有实现。 下面提供一下具体实现方法&#xff1a;&#xff08;关键字来过滤&#xff09; filterNameMethod({ option, row }) {if (row.name.indexOf(op…

差分数组汇总

本文涉及知识点 算法与数据结构汇总 差分数组 令 a[i] ∑ j : 0 i v D i f f [ i ] \sum_{j:0}^{i}vDiff[i] ∑j:0i​vDiff[i] 如果 vDiff[i1]&#xff0c;则a[i1…]全部 如果vDiff[i2]–,则a[i2…]全部–。 令11 < i2 &#xff0c;则&#xff1a; { a [ i ] 不变&…

MySQL----undo log回滚日志原理、流程以及与redo log比较

回滚日志 回滚日志&#xff0c;保存了事务发生之前的数据的一个版本&#xff0c;用于事务执行时的回滚操作&#xff0c;同时也是实现多版本并发控制&#xff08;MVCC&#xff09;下读操作的关键技术。 如何理解Undo Log 事务需要保证原子性&#xff0c;也就是事务中的操作要…

【OpenHarmony开发】自定义系统应用之实践

前言 OpenHarmony系统应用是指预装在OpenHarmony操作系统中的应用程序&#xff0c;也称为系统应用。这些应用程序通常由操作系统开发者开发&#xff0c;包括系统设置、电话、短信、浏览器、相机、音乐、视频等常用应用程序。这些应用程序通常具有更高的权限和更深入的系统集成…

解决ERROR: Cannot uninstall ‘ipython-genutils‘.的方法

删除ipython-genutils-X-pyX.egg-info文件&#xff0c;X表示对应版本&#xff0c;问题解决。

昇思25天学习打卡营第1天|基本介绍及快速入门

1.第一天学习总体复盘 1&#xff09;成功注册昇思大模型平台&#xff0c;并成功申请算力&#xff1b; 2)在jupyter环境下学习初学入门/初学教程的内容&#xff1b; 在基本介绍部分&#xff0c;快速撸了一边内容&#xff0c;有了一个基本的了解&#xff08;没理解到位的计划采用…

Java | Leetcode Java题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; class Solution {public int[] twoSum(int[] numbers, int target) {int low 0, high numbers.length - 1;while (low < high) {int sum numbers[low] numbers[high];if (sum target) {return new int[]{low 1, high 1};} else i…

spark 整合 yarn

spark 整合 yarn 1、在master节点上停止spark集群 cd /usr/local/soft/spark-2.4.5/sbin ./stop-all.sh 2、spark整合yarn只需要在一个节点整合, 可以删除node1 和node2中所有的spark文件 分别在node1、node2 的/usr/local/soft目录运行 rm -rf spark-2.4.…

前端 CSS 经典:边框转圈动画效果

前言&#xff1a;首先我们要知道 css 动画只对数值类的 CSS 属性起作用。要实现边框转圈动画效果&#xff0c;实际就是渐变背景的旋转。但是在以前&#xff0c;渐变背景是不支持动画的。现在我们可以利用浏览器新出的 Houdini API 来实现这个动画效果。Houdini API 特别强大&am…