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


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

    下图是导入Excel的数据结构

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

    1. @Override
    2. public KnowledgeBaseDictImportRespVO importKnowledgeBaseDict(MultipartFile file) throws IOException {
    3. KnowledgeBaseDictImportRespVO kbdir = KnowledgeBaseDictImportRespVO.builder().build(); // 该对象是方法返回的结果对象
    4. Map res = new ConcurrentHashMap<>();
    5. List createProblemsList = new ArrayList<>();
    6. String fileName = file.getOriginalFilename();
    7. String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
    8. if(fileType.equals(".xls") || fileType.equals(".xlsx")) {
    9. AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getData();
    10. //poi解析excel
    11. InputStream inputStream = file.getInputStream();
    12. // 读取工作薄 .xls 与 .xlsx 需要创建不通的工作簿 采用工作簿工厂类创建对应的工作簿类
    13. Workbook workbook = WorkbookFactory.create(inputStream);
    14. Sheet sheet = workbook.getSheetAt(0);
    15. //获取系统名称
    16. Row row0 = sheet.getRow(0); // 第一行的表头
    17. Cell cell0 = row0.getCell(0); // 第一列
    18. String belongSystem = cell0.getStringCellValue().trim().replace("系统功能树","");
    19. if (StringUtils.isEmpty(belongSystem)) {
    20. res.put(StrUtils.getRandomString(6),"归属系统不能为空!");
    21. kbdir.setFailureProblems(res);
    22. return kbdir;
    23. }
    24. KnowledgeBaseDictDO kbdictdo = knowledgeBaseDictMapper.getKnowledgeBaseDictByParenetIdAndMenuName(0L,belongSystem);
    25. //定义一个cellId,此为每一次循环前一列的id
    26. long cellId = 0;
    27. String cellName = null; // 记录父级名称
    28. String firstMenuName = null; // 因为合并单元格只有第一个有值,需要记录该值。
    29. int count = 0;
    30. if (ObjectUtils.isEmpty(kbdictdo)) {
    31. kbdictdo = new KnowledgeBaseDictDO();
    32. kbdictdo.setSort(0);
    33. kbdictdo.setParentId(0L);
    34. kbdictdo.setMenuLevel(0);
    35. kbdictdo.setMenuName(belongSystem);
    36. kbdictdo.setBelongingSystem(belongSystem);
    37. kbdictdo.setCreator(adminUserRespDTO.getNickname());
    38. int rs = knowledgeBaseDictMapper.insert(kbdictdo);
    39. if (rs > 0) {
    40. count += rs;
    41. createProblemsList.add(belongSystem);
    42. cellId = kbdictdo.getId();
    43. cellName = kbdictdo.getMenuName();
    44. }
    45. }
    46. int rows = sheet.getPhysicalNumberOfRows();
    47. if (rows > 2) {
    48. //按照行进行循环,读取当前行的列
    49. for (int i = 0,j = 2; j < rows; j++,i++) {
    50. // 读取行
    51. Row row = sheet.getRow(j);
    52. //查询当前行有多少列
    53. int physical = sheet.getRow(j).getPhysicalNumberOfCells();
    54. if (row != null) {
    55. //获取第一列的单元格
    56. Cell cell = row.getCell(0);
    57. //判断单元格是否为空
    58. if (!(cell == null || "".equals(cell.toString().trim()))) {
    59. firstMenuName = cell.getStringCellValue().trim();
    60. //根据单元格的数据查询数据库是否存在记录
    61. KnowledgeBaseDictDO kbddoFirst = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(firstMenuName,1,belongSystem);
    62. //数据库不存在,添加记录
    63. if (ObjectUtils.isEmpty(kbddoFirst)) {
    64. kbddoFirst = new KnowledgeBaseDictDO();
    65. kbddoFirst.setSort(i);
    66. kbddoFirst.setParentId(cellId);
    67. kbddoFirst.setBelongingSystem(belongSystem);
    68. kbddoFirst.setParentMenuName(cellName);
    69. kbddoFirst.setMenuName(cell.getStringCellValue().trim());
    70. kbddoFirst.setMenuLevel(1);
    71. kbddoFirst.setCreator(adminUserRespDTO.getNickname());
    72. int rs = knowledgeBaseDictMapper.insert(kbddoFirst);
    73. if (rs > 0) {
    74. count += rs;
    75. createProblemsList.add(cell.getStringCellValue().trim());
    76. // 记录父级id 与 名称
    77. cellId = kbddoFirst.getId();
    78. cellName = kbddoFirst.getMenuName();
    79. }
    80. } else {
    81. //数据库存在记录,将这条记录的id作为父id
    82. cellId = kbddoFirst.getId();
    83. cellName = kbddoFirst.getMenuName();
    84. }
    85. } else { // 表示循环到合并单元格的地方,查询数据库记录父级信息
    86. if (StringUtils.isNotEmpty(firstMenuName)) {
    87. KnowledgeBaseDictDO kbddoFirst = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(firstMenuName,1,belongSystem);
    88. cellId = kbddoFirst.getId();
    89. cellName = kbddoFirst.getMenuName();
    90. }
    91. }
    92. }
    93. // 从第二列单元格开始
    94. for (int k = 1,l = 0; k < physical; k++,l++) {
    95. //取单元格
    96. Cell cell = row.getCell(k);
    97. //判断单元格是否为空
    98. if (!(cell == null || "".equals(cell.toString().trim()))) {
    99. //查询数据库有无此记录
    100. KnowledgeBaseDictDO kbddoSecond = knowledgeBaseDictMapper.getKnowledgeBaseDictByMenuNameAndMenuLevelAndbls(cell.getStringCellValue().trim(),k + 1,belongSystem);
    101. if (ObjectUtils.isEmpty(kbddoSecond)) {
    102. kbddoSecond = new KnowledgeBaseDictDO();
    103. kbddoSecond.setSort(l);
    104. kbddoSecond.setParentId(cellId);
    105. kbddoSecond.setBelongingSystem(belongSystem);
    106. kbddoSecond.setParentMenuName(cellName);
    107. kbddoSecond.setMenuName(cell.getStringCellValue().trim());
    108. kbddoSecond.setMenuLevel(k+1);
    109. kbddoSecond.setCreator(adminUserRespDTO.getNickname());
    110. int rs = knowledgeBaseDictMapper.insert(kbddoSecond);
    111. if (rs > 0) {
    112. count += rs;
    113. createProblemsList.add(cell.getStringCellValue().trim());
    114. // 记录父级id 与 名称
    115. cellId = kbddoSecond.getId();
    116. cellName = kbddoSecond.getMenuName();
    117. }
    118. } else {
    119. cellId = kbddoSecond.getId();
    120. cellName = kbddoSecond.getMenuName();
    121. }
    122. if (k == physical - 1) {
    123. // 内层循环结束,表示一行的一级菜单结束,需要指定一级菜单的父级
    124. cellId = kbdictdo.getId();
    125. cellName = kbdictdo.getMenuName();
    126. }
    127. } else { // 如果为空,需要记录父级id与名称
    128. cellId = kbdictdo.getId();
    129. cellName = kbdictdo.getMenuName();
    130. }
    131. }
    132. }
    133. } else {
    134. res.put(StrUtils.getRandomString(6),"导入的数据不能为空!");
    135. kbdir.setFailureProblems(res);
    136. return kbdir;
    137. }
    138. kbdir.setCreateProblems(createProblemsList);
    139. kbdir.setFailureProblems(res);
    140. }
    141. return kbdir;
    142. }

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

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

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

  • 相关阅读:
    使用matlab制作声音采样率转换、播放以及显示的界面
    Memcached 的安装与使用;SpringBoot 整合 Memcached 代码详解
    Vue.js核心技术解析与uni-app跨平台实战开发学习笔记 第7章 Vue.js高级进阶 7.2 vue-cli目录结构
    CentOS7和CentOS8 Asterisk 20.0.0 简单图形化界面8--PJSIP的环境NAT设置
    学习 Tensorflow 的困境与解药
    巨好看的登录注册界面源码
    leetcode 468 验证IP地址是否有效(竟然花费了两个小时)
    【深度学习实验】注意力机制(四):点积注意力与缩放点积注意力之比较
    一文带你了解全覆盖路径规划算法(CCPP)
    灵活的IP网络测试工具——— X-Launch
  • 原文地址:https://blog.csdn.net/qq_31674229/article/details/139813924