如何在Java中解析Excel文件中的树形结构(附Section实体类)
搞定Excel树形结构解析的方案
嘿,我来帮你把Excel里的层级文本转换成Section组成的树形结构!先理清楚思路,一步步来实现。
1. 先完善你的Section实体类
你给的代码有点不完整,我帮你补全了,还加了必要的导入:
import lombok.Getter; import lombok.Setter; import java.util.ArrayList; import java.util.List; @Getter @Setter public class Section { private int depth; private String text; private int parentLevel; private List<Section> children; public Section(String text, int depth) { this.text = text; this.depth = depth; this.children = new ArrayList<>(); this.parentLevel = 0; } public Section(String text, int depth, int parentLevel) { this.text = text; this.depth = depth; this.children = new ArrayList<>(); this.parentLevel = parentLevel; } }
小提示:如果后续操作树形结构需要直接访问父节点,可以把parentLevel改成Section parent,这样会更灵活哦
2. 核心解析逻辑:用栈维护层级路径
树形结构的关键是找到每个节点的父节点,用栈跟踪当前层级链是最方便的方案。我用Apache POI来读取Excel(这是Java处理Excel最常用的库),直接上完整代码:
第一步:引入POI依赖(Maven为例)
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency>
第二步:解析Excel并生成树形结构的代码
import org.apache.poi.ss.usermodel.*; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayDeque; import java.util.Deque; public class ExcelTreeParser { // 主方法:把Excel文件转换成Section树形结构 public static Section parseExcelToTree(String filePath) throws IOException { Section rootNode = null; // 栈用来跟踪当前层级的节点,栈顶就是当前节点的最近父节点 Deque<Section> sectionStack = new ArrayDeque<>(); try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = WorkbookFactory.create(fis)) { Sheet targetSheet = workbook.getSheetAt(0); // 假设树形结构在第一个工作表 for (Row row : targetSheet) { Cell textCell = row.getCell(0); // 假设所有树形文本都在第一列 if (textCell == null || textCell.getCellType() == CellType.BLANK) { continue; // 跳过空行 } String nodeText = textCell.getStringCellValue().trim(); if (nodeText.isEmpty()) { continue; } // 计算当前节点的深度,这里提供两种常见场景的实现,按需选择: // 场景1:用文本缩进(比如每4个空格算1层) int nodeDepth = calculateDepthByIndent(nodeText); // 场景2:用列位置(A列=深度1,B列=深度2,找第一个非空单元格的列) // int nodeDepth = calculateDepthByColumn(row); Section currentSection = new Section(nodeText, nodeDepth); if (sectionStack.isEmpty()) { // 第一个节点直接作为根节点 rootNode = currentSection; sectionStack.push(currentSection); } else { // 弹出栈中深度>=当前节点的元素,找到真正的父节点 while (!sectionStack.isEmpty() && sectionStack.peek().getDepth() >= nodeDepth) { sectionStack.pop(); } if (!sectionStack.isEmpty()) { Section parentSection = sectionStack.peek(); parentSection.getChildren().add(currentSection); currentSection.setParentLevel(parentSection.getDepth()); } else { // 极端情况:栈空了,当前节点作为新根(一般树形结构只有一个根) rootNode = currentSection; } // 把当前节点压入栈,作为后续节点的父节点候选 sectionStack.push(currentSection); } } } return rootNode; } // 辅助方法:按文本缩进计算深度(每4个空格=1层,深度从1开始) private static int calculateDepthByIndent(String text) { int leadingSpaceCount = 0; while (leadingSpaceCount < text.length() && text.charAt(leadingSpaceCount) == ' ') { leadingSpaceCount++; } return leadingSpaceCount / 4 + 1; } // 辅助方法:按列位置计算深度(第一个非空单元格的列号+1作为深度) private static int calculateDepthByColumn(Row row) { for (int colIndex = 0; colIndex < row.getLastCellNum(); colIndex++) { Cell cell = row.getCell(colIndex); if (cell != null && cell.getCellType() != CellType.BLANK && !cell.getStringCellValue().trim().isEmpty()) { return colIndex + 1; } } return 1; // 默认深度1 } // 测试用:打印树形结构,验证结果 public static void printTree(Section section, String indent) { System.out.println(indent + "[深度" + section.getDepth() + "] " + section.getText()); for (Section child : section.getChildren()) { printTree(child, indent + " "); } } // 测试入口 public static void main(String[] args) throws IOException { Section treeRoot = parseExcelToTree("你的Excel文件路径.xlsx"); printTree(treeRoot, ""); } }
3. 关键逻辑说明
- 栈的作用:遍历节点时,栈保存着从根到当前层级的路径。如果当前节点深度比栈顶小,说明回到了上一级,弹出栈顶直到找到深度更小的父节点。
- 深度计算:根据你的Excel实际结构选对应的方法——文本缩进区分层级用
calculateDepthByIndent,列位置区分层级用calculateDepthByColumn。 - 空行处理:跳过空行和空白文本,避免生成无效节点。
内容的提问来源于stack exchange,提问作者Kirrya
相关产品推荐
相关产品推荐

