You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:36