树形结构导出excel表格,父级节点跨行

该文章展示了一个Java程序,它利用ApachePOI库将树形数据结构转换并写入Excel工作表。代码创建了一个工作簿,设置了表头,并递归地将树节点及其子节点填入工作表中,形成层次结构。最后,程序将工作簿保存为exported_tree_with_header.xlsx文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果图

在这里插入图片描述

mavan依赖

   <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>

代码

package com.cd.test2;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TreeDataToExcel {

    public static class TreeNode {
        private String name;
        private List<TreeNode> children;

        public TreeNode(String name) {
            this.name = name;
            this.children = new ArrayList<>();
        }

        public void addChild(TreeNode child) {
            this.children.add(child);
        }
    }

    public static void main(String[] args) throws IOException {
        // 创建样本树形数据
        TreeNode rootNode = createSampleTreeData();

        // 使用 try-with-resources 创建一个新的 Excel 工作簿和文件输出流
        try (Workbook workbook = new XSSFWorkbook(); FileOutputStream fileOut = new FileOutputStream("exported_tree_with_header.xlsx")) {
            // 在工作簿中创建一个名为 "Tree Data" 的工作表
            Sheet sheet = workbook.createSheet("Tree Data");

            // 创建工作表的表头
            createHeader(sheet);

            // 将树形数据填充到工作表中,从第二行第一列(索引从0开始)开始填充
            fillTreeData(sheet, rootNode, 1, 0);

            // 将工作簿写入文件输出流,即保存为文件
            workbook.write(fileOut);
        }
    }

    private static void createHeader(Sheet sheet) {

        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < 3; i++) {
            Cell headerCell = headerRow.createCell(i);
            headerCell.setCellValue("表头");
        }
        sheet.autoSizeColumn(0);

    }

    private static TreeNode createSampleTreeData() {
        TreeNode rootNode = new TreeNode("Root");
        TreeNode child1 = new TreeNode("Child1");
        TreeNode child2 = new TreeNode("Child2");
        TreeNode subChild1 = new TreeNode("Subchild1");
        TreeNode subChild2 = new TreeNode("Subchild2");
        TreeNode subChild3 = new TreeNode("Subchild3");
        rootNode.addChild(child1);
        rootNode.addChild(child2);
        child1.addChild(subChild1);
        child2.addChild(subChild2);
        child2.addChild(subChild3);

        return rootNode;
    }

    private static int fillTreeData(Sheet sheet, TreeNode node, int rowStart, int colStart) {
        // 获取开始行,如果不存在则创建一行
        Row row = sheet.getRow(rowStart) == null ? sheet.createRow(rowStart) : sheet.getRow(rowStart);

        // 在开始列创建一个单元格
        Cell cell = row.createCell(colStart);

        // 设置单元格的值为节点名称
        cell.setCellValue(node.name);

        // 检查节点是否有子节点
        if (node.children.isEmpty()) {
            // 如果没有子节点,那么这个节点只占用一行
            return 1;
        } else {
            // 如果有子节点,则需要计算所有子节点占用的行数
            int totalRows = 0;
            int childrenColStart = colStart + 1;

            // 对每个子节点进行递归调用
            for (TreeNode child : node.children) {
                int childRows = fillTreeData(sheet, child, rowStart + totalRows, childrenColStart);
                // 将子节点占用的行数累加到总行数中
                totalRows += childRows;
            }

            // 如果子节点占用的行数大于1,则需要合并单元格
            if (totalRows > 1) {
                // 合并单元格
                sheet.addMergedRegion(new CellRangeAddress(rowStart, rowStart + totalRows - 1, colStart, colStart));
                // 设置单元格垂直居中对齐
                CellUtil.setVerticalAlignment(cell, VerticalAlignment.CENTER);
                // 设置单元格水平居中对齐
                CellUtil.setAlignment(cell, HorizontalAlignment.CENTER);
            }

            // 返回占用的总行数
            return totalRows;
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值