Java树形结构数据生成导出excel文件方法记录
作者:早晨阳光一般暖 发布时间:2021-08-20 05:19:18
标签:java,树形结构,生成
目录
什么是树形结构数据
效果
用法
源码
总结
什么是树形结构数据
效果
用法
String jsonStr = "{\"name\":\"aaa\",\"children\":[{\"name\":\"bbb\",\"children\":[{\"name\":\"eee\"},{\"name\":\"fff\",\"children\":[{\"name\":\"iii\"},{\"name\":\"jjj\",\"children\":[{\"name\":\"qqq\"},{\"name\":\"ttt\"}]}]},{\"name\":\"www\"}]},{\"name\":\"ccc\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\",\"children\":[{\"name\":\"ttt\"},{\"name\":\"mmm\"}]},{\"name\":\"uuu\"}]},{\"name\":\"ooo\"}]},{\"name\":\"ddd\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\"},{\"name\":\"uuu\"}]}]}]}";
Map tree = JSONObject.parseObject(jsonStr, Map.class);
tree2Excel(tree, "E:\\" + System.currentTimeMillis() + ".xls", "name", "children");
源码
package pers.xxx.demo.tree2excel;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* 树形结构数据导出excel工具
* <p>
* Created by lzy on 2021/2/24 14:09
*/
@SuppressWarnings("ALL")
public class Tree2ExcelUtil {
/**
* 树形结构数据生成excel文件
*
* @param tree 树形数据
* @param filePath 文件路径
* @return
*/
public static boolean tree2Excel(Map tree, String filePath) {
return tree2Excel(tree, filePath, null, null);
}
/**
* 树形结构数据生成excel文件
*
* @param tree 树形数据
* @param filePath 文件路径
* @param lableName 标签Key名称
* @param childrenName 子节点Key名称
* @return
*/
public static boolean tree2Excel(Map tree, String filePath, String lableName, String childrenName) {
if (isBlank(filePath)) {
System.err.println("文件名称不能为空");
return false;
}
try {
doSame(tree, lableName, childrenName);
createExcel(filePath, tree);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 树形结构数据生成Workbook对象
*
* @param tree 树形数据
* @param fileSuf 文件后缀,xls/xlsx
* @return
*/
public static Workbook tree2Worbook(Map tree, String fileSuf) {
return tree2Worbook(tree, fileSuf, null, null);
}
/**
* 树形结构数据生成Workbook对象
*
* @param tree 树形数据
* @param fileSuf 文件后缀,xls/xlsx
* @param lableName 标签Key名称
* @param childrenName 子节点Key名称
* @return
*/
public static Workbook tree2Worbook(Map tree, String fileSuf, String lableName, String childrenName) {
if (isBlank(fileSuf)) {
System.err.println("必须指定文件后缀");
return null;
}
try {
doSame(tree, lableName, childrenName);
return procesData(tree, fileSuf);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//具体实现
/**
* 标识最大列
*/
private static int maxCol = 0;
private static String lableName = "lable";
private static String childrenName = "children";
private static final String COL = "col";
private static final String ROW = "row";
private static final String ROW_OFT = "rowOft";
private static final String ROW_SIZE = "rowSize";
private static void doSame(Map tree, String lableName, String childrenName) {
if (!isBlank(lableName)) {
Tree2ExcelUtil.lableName = lableName;
}
if (!isBlank(childrenName)) {
Tree2ExcelUtil.childrenName = childrenName;
}
coreAlgoCol(tree, 1);
coreAlgoRow(tree);
}
/**
* 主要算法,计算列的坐标,计算每个节点所占行
*
* @param tree 数据
* @param col 递增的列
* @param trees 把高级别向下传递计算递增的行高
*/
private static void coreAlgoCol(Map tree, int col, Map... trees) {
tree.put(COL, col);
Object childrenObj = tree.get(childrenName);
if (childrenObj != null) {
List<Map> children = (List<Map>) childrenObj;
if (children.size() > 0) {
int size = children.size() * 2 - 1;
tree.put(ROW_SIZE, size);
int len = trees != null ? trees.length + 1 : 1;
Map[] arrData = new Map[len];
if (trees != null && trees.length > 0) {
for (int i = 0; i < trees.length; i++) {
Map tree1 = trees[i];
tree1.put(ROW_SIZE, toInt(tree1.get(ROW_SIZE), 1) + size - 1);
arrData[i] = tree1;
}
}
arrData[len - 1] = tree;
for (Map tree1 : children) {
int newCol = col + 1;
if (newCol > maxCol) {
maxCol = newCol;
}
coreAlgoCol(tree1, newCol, arrData);
}
}
}
}
/**
* 主要算法,计算行的坐标
*
* @param tree
*/
private static void coreAlgoRow(Map tree) {
if (toInt(tree.get(ROW)) == 0) {
tree.put(ROW, Math.round(toInt(tree.get(ROW_SIZE), 1) / 2.0f));
}
Object childrenObj = tree.get(childrenName);
if (childrenObj != null) {
List<Map> children = (List<Map>) childrenObj;
if (children.size() > 0) {
int tempOft = toInt(tree.get(ROW_OFT));
for (Map tree1 : children) {
int rowSize = toInt(tree1.get(ROW_SIZE), 1);
tree1.put(ROW_OFT, tempOft);
tree1.put(ROW, tempOft + Math.round(rowSize / 2.0f));
tempOft += rowSize + 1;
coreAlgoRow(tree1);
}
}
}
}
/**
* 创建excel文件
*
* @param filePath 文件路径,具体路径到文件名
* @param tree 数据
* @throws IOException
*/
private static void createExcel(String filePath, Map tree) throws IOException {
File file = new File(filePath);
boolean bfile = file.createNewFile();
// 复制模板到新文件
if (bfile) {
Workbook wk = procesData(tree, filePath);
if (wk != null) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
wk.write(fos);
fos.flush();
} finally {
closeStream(fos);
wk.close();
}
}
}
}
/**
* 处理excel数据
*
* @param tree 数据
* @return 工作表对象
*/
private static Workbook procesData(Map tree, String fileName) {
Workbook wk = null;
if (fileName.endsWith("xls")) {
wk = new HSSFWorkbook();
}
if (fileName.endsWith("xlsx")) {
wk = new XSSFWorkbook();
}
if (wk == null) {
System.err.println("文件名称不正确");
return null;
}
//创建一个sheet页
Sheet sheet = wk.createSheet("Sheet1");
int colSize = maxCol * 2 + 2;
int rowSize = toInt(tree.get(ROW_SIZE), 1);
for (int i = 0; i <= rowSize; i++) {
Row row = sheet.createRow(i);
for (int j = 0; j <= colSize; j++) {
row.createCell(j);
}
}
//配置单元格背景色
CellStyle style1 = wk.createCellStyle();
style1.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
style1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
CellStyle style2 = wk.createCellStyle();
style2.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
dealCell(sheet, tree, style1, style2);
return wk;
}
/**
* 根据计算好的坐标填充每一个单元格
*
* @param sheet #
* @param tree 数据
* @param style1 单元格格式
* @param style2 单元格格式
*/
private static void dealCell(Sheet sheet, Map tree, CellStyle style1, CellStyle style2) {
Row row = sheet.getRow(toInt(tree.get(ROW)));
int oftCol = (toInt(tree.get(COL)) - 1) * 2 + 1;
Cell cell = row.getCell(oftCol);
cell.setCellStyle(style1);
cell.setCellValue(String.valueOf(tree.get(lableName)));
sheet.setColumnWidth(oftCol, 256 * 20);
Object childrenObj = tree.get(childrenName);
if (childrenObj != null) {
List<Map> children = (List<Map>) childrenObj;
if (children.size() > 0) {
int size = children.size();
int startRow = toInt(children.get(0).get(ROW));
int endRow = toInt(children.get(size - 1).get(ROW));
int col = oftCol + 1;
sheet.setColumnWidth(col, 256);
for (; startRow <= endRow; startRow++) {
sheet.getRow(startRow).getCell(col).setCellStyle(style2);
}
for (Map child : children) {
dealCell(sheet, child, style1, style2);
}
}
}
}
private static int toInt(Object val) {
return toInt(val, 0);
}
private static int toInt(Object val, Integer defVal) {
try {
return Integer.parseInt(String.valueOf(val));
} catch (NumberFormatException ignored) {
}
return defVal;
}
private static boolean isBlank(String str) {
return str == null || str.trim().length() == 0;
}
/**
* 关闭流
*
* @param closeables 不定长数组 流对象
*/
public static void closeStream(Closeable... closeables) {
for (Closeable closeable : closeables) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
来源:https://blog.csdn.net/LZY_1993/article/details/114083456


猜你喜欢
- 通过View提供的方法获取高度方式有两种:1, 当前显示的view中直接获取当前view高宽2, 通过Activity的getWindow(
- 基本哪些属于引用类型类(object,string),接口、数组、委托引用类型分配在哪里引用类型变量位于线程栈。引用类型实例分配在托管堆上。
- xml里面配置标签:<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc./
- import java.util.List;/*** * 基本接口 * * @author xyq 
- 我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态;或者你的程序需要访问一些
- 利用mybtis插件打印完整的sql,将占位符?替换成实际值import org.apache.ibatis.cache.CacheKey;
- 0.写在前面2020-5-18更新这个东西已经是两年前的了,现在问我具体细节我也不是很清楚了,而且现在review两年前的代码感觉写的好烂。
- 面对一个项目,对于Android应用开发框架的选择,我想过三种方案:1.使用Loader + HttpClient + GreenDao +
- 1、servlet层package com.ycz.controller;import com.alibaba.fastjson.JSON;
- hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们
- 在idea中将创建的java web项目部署到Tomcat中采用的工具idea 2018.3.6 Tomcat71.先创建第一个新项目sec
- 前言:在本文中,我们将介绍Valhalla项目——它的历史原因、当前的开发状态,以及它发布后为日常J
- 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1)
- 一、同步问题提出线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。例如:两个线程ThreadA、ThreadB都操作同一个对
- FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化
- 废话不多说了,下面代码给大家介绍下利用正则表达式判断字符的方法,具体代码如下所示:using System;using System.Tex
- 😜shape属性详解<?xml version="1.0" encoding="utf-8"?
- 一、介绍Properties文件在Java中主要为配置文件,文件类型为:.properties,格式为文本文件,内容格式为"键=值
- Java数字格式类以下两个类可用于格式化和解析数字:java.text.NumberFormatjava.text.DecimalForma
- 本文实例讲述了Android编程设计模式之备忘录模式。分享给大家供大家参考,具体如下:一、介绍备忘录模式是一种行为模式,该模式用于保存对象当