导出树形结构,excel

1实例

复制代码
HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("sheet");

        final HSSFCellStyle setBorder = workbook.createCellStyle();
        setBorder.setVerticalAlignment(VerticalAlignment.CENTER);
        setBorder.setAlignment(HorizontalAlignment.LEFT);
        sheet.autoSizeColumn(0);
        setBorder.setWrapText(true);
        //    1
        ListToCombineExcel process=createListToCombineExcel(workbook, sheet, setBorder);
        List<FileAndFolderVO> fileAndFolderVOS = FileAndFolderVO.createList(list);
        //    2    
        process.createSheetContent(fileAndFolderVOS);

        String fileName = URLEncoder.encode(DateUtils.parseDateToStr("yyyyMMddHHmm",new Date())+".xlsx", "utf-8");
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            // 代表的是Excel文件类型
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            workbook.write(out);
        } catch (IOException e) {
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
                workbook.close();
            } catch (IOException e) {
            }
        }

2 FileAndFolderVO类

复制代码
		@Data
public class FileAndFolderVO implements Serializable {
    private static final long serialVersionUID = 1L;

    private String id;

    private String name;


   private  FileAndFolderVO parentFileAndFolderVO;


    private static FileAndFolderVO createOrg(String id,String pId,String name)
    {
        FileAndFolderVO org=new FileAndFolderVO();
        org.setId(id);
        org.setName(name);
        if(!pId.equals("0")){
            FileAndFolderVO parent=new FileAndFolderVO();
            parent.setId(pId);
            org.setParentFileAndFolderVO(parent);
        }
        return org;
    }


    public static List<FileAndFolderVO> createList(List<FileAndFolder> fileAndFolderS)
    {
        List<FileAndFolderVO> list=new ArrayList();

        for (FileAndFolder fileAndFolder : fileAndFolderS) {
            list.add(createOrg(fileAndFolder.getId(),fileAndFolder.getParentId(),fileAndFolder.getName()));
        }
        return list;
    }


}

3 ListToCombineExcel

复制代码
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 把list转化成excel
 *
 */
public abstract class ListToCombineExcel extends ListToTree{
	 private Map<String,HSSFRow> rowCache=new HashMap<String, HSSFRow>();
	 private Map<String,HSSFCell> cellCache=new HashMap<String, HSSFCell>();
	 
	 private HSSFWorkbook workbook;
	 private HSSFSheet sheet;
	 
	 private List<Node> treeNodes=null;
     
	 public ListToCombineExcel(HSSFWorkbook workbook, HSSFSheet sheet)
	 {
		 this.workbook=workbook;
		 this.sheet=sheet;
	 }
	
	 /**
	  * 创建excel的node
	  */
	@Override
	protected Node createNode(Object target) {
		return new ExcelNode(target);
	}
	 
	 /**
	  * 创建sheet的內容
	  */
	 public void createSheetContent(List<? extends Object> list)
	 {
		 this.initTreeNodes(list);
		 
		 this.processTreeNodes(this.treeNodes);
		 
	 }
	 
	 private void processTreeNodes(List nodes)
	 {
		 for (int i = 0;nodes!=null&& i < nodes.size(); i++) {
			ExcelNode node=(ExcelNode) nodes.get(i);
			this.processTreeNode(node);
		 }
	 }
	 
	 private void processTreeNode(ExcelNode node)
	 {
		    //设置单元格内容
			this.setCellContent(workbook, sheet, this.getRow(node.getRowNumber()), this.getCell(node.getRowNumber(), node.getCellNumber()), node);
			//合并单元格
			this.combineByExcelNode(node);
			
			this.processTreeNodes(node.getChilds());
	 }

	 /**
	  * 把要处理的数据转成tree狀
	  * @param list
	  */
	 private void initTreeNodes(List<? extends Object> list)
	 {
		 this.treeNodes=this.process(list);
		  
		 for (int i = 0;treeNodes!=null &&i < treeNodes.size(); i++) {
			ExcelNode node=(ExcelNode) treeNodes.get(i);
			node.init(this.treeNodes);
		}
	 }
	 
	 /**
	  * 得到row
	  * @param rowNumber
	  * @return
	  */
	 protected HSSFRow getRow(int rowNumber)
	 {
		 HSSFRow row=this.rowCache.get(String.valueOf(rowNumber));
		 if(null==row)
		 {
			 row=this.sheet.createRow(rowNumber);
			 this.rowCache.put(String.valueOf(rowNumber), row);
		 }
		 return row;
	 }
	 
	 /**
	  * 得到cell
	  * @param rowNumber
	  * @param cellNumber
	  * @return
	  */
	 protected HSSFCell getCell(int rowNumber , int cellNumber )
	 {
		 String key=rowNumber+"_"+cellNumber;
		 HSSFCell cell=this.cellCache.get(key);
		 if(null==cell)
		 {
			 HSSFRow row=this.getRow(rowNumber);
			 cell=row.createCell(cellNumber);
			 this.cellCache.put(key, cell);
		 }
		 return cell;
	 }
	 
	 /**
	  * 根据node合并单元格
	  * @param node
	  */
	 protected void combineByExcelNode(ExcelNode node)

	 {
         int rowFrom = node.getRowFrom();
         int rowTo = node.getRowTo();
         //增加判断
         if ((rowFrom!=rowTo)){
             CellRangeAddress addressEpisodeProject = new CellRangeAddress( node.getRowFrom(), node.getRowTo(), node.getCellFrom(),node.getCellTo());
             sheet.addMergedRegion(addressEpisodeProject);
         }
	 }
	 
	 /**
	  * 设置单元格内容
	  * @param workbook
	  * @param sheet
	  * @param row
	  * @param cell
	  * @param node
	  */
	 public abstract void setCellContent(HSSFWorkbook workbook, HSSFSheet sheet, HSSFRow row, HSSFCell cell, ExcelNode node);



	 
	 
}

4 ListToTree

复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public abstract class ListToTree {
	public List<Node> process(List<? extends Object> list) {
		List<Node> nodes = new ArrayList<Node>();
		for (int i = 0; list != null && i < list.size(); i++) {
			Node node = this.createNode(list.get(i));
			this.process(nodes, node);
		}
		return nodes;
	}

	/**
	 * 开始处理每一页
	 * 
	 * @param nodes
	 * @param currentNode
	 */
	private void process(List<Node> nodes, Node currentNode) {
		currentNodeAddChild(currentNode, nodes);// 
		
		currentNodeAddToParentDelegate(currentNode, nodes);
	}

	/**
	 * 在nodes中找到自己的子节点加入
	 * 
	 * @param currentNode
	 * @param nodes
	 */
	private void currentNodeAddChild(Node currentNode, List<Node> nodes) {
		if (nodes.size() < 1) {
			return;
		}
		Iterator<Node> iter = nodes.iterator();
		while (iter.hasNext()) {
			Node item = iter.next();
			if (this.isParent(currentNode, item)) {
				currentNode.addChild(item);
				iter.remove();
			}
		}
	}
	
	/**
	 * 在nodes中找到自己的父亲节点加入  如果沒有加入就把自己加入到nodes
	 * 
	 * @param currentNode
	 * @param nodes
	 */
	private void currentNodeAddToParentDelegate(Node currentNode, List<Node> nodes)
	{
		
		if(!currentNodeAddToParent(currentNode, nodes))//如果沒有找到父亲节点自己加入nodes
		{
			nodes.add(currentNode);
		}
	}
	
	/**
	 * 在nodes中找到自己的父亲节点加入
	 * 
	 * @param currentNode
	 * @param nodes
	 */
	private boolean currentNodeAddToParent(Node currentNode, List<Node> nodes) {
		for (int i = 0; nodes != null && i < nodes.size(); i++) {
           Node parentNode=nodes.get(i);
           if(this.isParent(parentNode, currentNode))
           {
        	   parentNode.addChild(currentNode);
        	   return true;
           }else
           {
        	   if(currentNodeAddToParent(currentNode, parentNode.getChilds()))
        	   {
        		   //成功加入
        		   return true;
        	   }
           }
		}
		return false;
	}

	protected Node createNode(Object target) {
		return new Node(target);
	}

	/**
	 * childNode 是不是parentNode的子节点
	 * 
	 * @param parentNode
	 * @param childNode
	 * @return
	 */
	protected boolean isParent(Node parentNode, Node childNode) {
		String id = this.getId(parentNode.getTarget());
		return id != null && id.trim().length() > 0 && id.equals(this.getParentId(childNode.getTarget()));
	}

	/**
	 * 得到id
	 * 
	 * @param obj
	 * @return
	 */
	protected abstract String getId(Object obj);

	/**
	 * 得到父亲id
	 * 
	 * @param obj
	 * @return
	 */
	protected abstract String getParentId(Object obj);
}

5 node

复制代码
import java.util.ArrayList;
import java.util.List;

/**
 *
 *
 */
public  class Node {
	protected Object targetObj;

	protected int level;// 层级
	protected int countLeaf;// 所以叶子个数

	protected Node parentNode;
	protected List<Node> childs = new ArrayList<Node>();

	public Node()
	{
		this(null);
	}
	
	public Node(Object target)
	{
		this.targetObj=target;
	}
	
	public void addChild(Node node) {
		this.childs.add(node);
		
		//设置层级
		node.level=this.level+1;
		//设置父亲节点
		node.parentNode=this;
	}

	public List<Node> getChilds() {
		return this.childs;
	}

	/**
	 * 得到所有葉子節點
	 * 
	 * @return
	 */
	public int getCountLeaf() {
		if (this.countLeaf == 0) {
			this.initCountLeaf();
		}
		return this.countLeaf;
	}

	/**
	 * 初始化所有叶子节点
	 */
	public void initCountLeaf() {
		this.countLeaf=0;
		if (this.isLeaf()) {
			this.countLeaf = 1;
		} else {
			for (Node node : this.childs) {
				this.countLeaf += node.getCountLeaf();
			}
		}
	}

	public int getLevel() {
		return level;
	}

	/**
	 * 是不是叶子节点
	 * 
	 * @return
	 */
	public boolean isLeaf() {
		return this.childs == null || this.childs.size() < 1;
	}

	public Object getTarget() {
		return this.targetObj;
	}

	public void setTarget(Object target) {
		this.targetObj = target;
	}
	
	public String toString()
	{
		return this.targetObj.toString();
	}
	
}

6 ExcelNode

复制代码
package com.aips.ps.excel;


import java.util.List;

/**
 * 树形的excel节点实现
 *
 */
public class ExcelNode extends Node {
	protected static  int startRow=0;//从地几行开始
	protected static  int startCell=0;//从地几列开始
	
	private int rowNumber;
	private int cellNumber;
	
	private int rowFrom;
	private int rowTo;
	private int cellFrom;
	private int cellTo;
	
	public ExcelNode()
	{
		this(null);
	}
	
	public ExcelNode(Object target)
	{
		this.targetObj=target;
	}

	public void init(List<?> treeNodes)  {
        this.initCountLeaf();
        
        this.initOther(treeNodes);
  
        this.initChilds(treeNodes);
	}
	
	private void initChilds(List<?> treeNodes)
	{
		if(!this.isLeaf())
		{
			for (Node child : this.getChilds()) {
				((ExcelNode)child).init(treeNodes);
			}
		}
	}

	protected  void initOther(List<?> treeNodes) {
		this.cellNumber=this.startCell+this.level;
		this.rowNumber=this.parseRowNumber((List<Node>) treeNodes);
		
		this.cellFrom=this.cellNumber;
		this.cellTo=this.cellNumber;
		this.rowFrom=this.rowNumber;
		this.rowTo=this.rowNumber+this.getCountLeaf()-1;
		
	}
	
	/**
	 * 得到rowNumber
	 * @return
	 */
	private int parseRowNumber(List<Node> treeNodes) {
		ExcelNode beforeNode=this.getBeforeNode(treeNodes);
		if(null==beforeNode)
		{
			//沒有找到前面一个节点就是和父亲节点的开始行计算
			return  this.parentNode==null?this.startRow:((ExcelNode)this.parentNode).getRowFrom();
		}else
		{
			//找到了前面一个节点 就是利用前面一个节点的rowTo+1
			return beforeNode.getRowTo()+1;
		}
	}
	
	/**
	 * 得到我前面一个节点
	 * @return
	 */
	protected ExcelNode getBeforeNode(List<Node> treeNodes) {
		if(null==this.parentNode)
		{
			return getBeforeNodeDelegate(treeNodes);
		}else
		{
			List<Node> nodes=this.parentNode.getChilds();
			return getBeforeNodeDelegate(nodes);
		}
	}
	
	private ExcelNode getBeforeNodeDelegate(List<Node> nodes)
	{
		if(nodes.size()<=1)
		{
			return null;

		}
		
		//如果第一个就是自己就没有前面的
		if(this==nodes.get(0))
		{
			return null;
		}
		
		for (int i = 1; i < nodes.size(); i++) {
		   ExcelNode thisNode=(ExcelNode) nodes.get(i);
		   if(thisNode==this)
		   {
			   return (ExcelNode) nodes.get(i-1);
		   }
		}
		
		return null;
	}
	
	public int getRowFrom() {
		return rowFrom;
	}

	public void setRowFrom(int rowFrom) {
		this.rowFrom = rowFrom;
	}

	public int getRowTo() {
		return rowTo;
	}

	public void setRowTo(int rowTo) {
		this.rowTo = rowTo;
	}

	public int getCellFrom() {
		return cellFrom;
	}

	public void setCellFrom(int cellFrom) {
		this.cellFrom = cellFrom;
	}

	public int getCellTo() {
		return cellTo;
	}

	public void setCellTo(int cellTo) {
		this.cellTo = cellTo;
	}

	public int getRowNumber() {
		return rowNumber;
	}

	public void setRowNumber(int rowNumber) {
		this.rowNumber = rowNumber;
	}

	public int getCellNumber() {
		return cellNumber;
	}

	public void setCellNumber(int cellNumber) {
		this.cellNumber = cellNumber;
	}
	
	
}
相关推荐
invicinble2 小时前
对于认识技术栈的几个角度
java
li.wz2 小时前
JDK17 深度解析:从特性实现到生产实践
java·开发语言
毕设源码-钟学长2 小时前
【开题答辩全过程】以 基于SSM的考研信息共享平台为例,包含答辩的问题和答案
java·eclipse
残花月伴2 小时前
天机学堂-day4(高并发优化方案)
java·spring boot·后端
a努力。3 小时前
拼多多Java面试被问:Redis的持久化策略对比(RDBVS AOF)
java·redis·面试
charlie1145141913 小时前
如何把 Win32 窗口“置顶”(Windows + C++)
开发语言·c++·windows·笔记·学习·软件工程
码上研社3 小时前
Maven配置阿里云镜像
java·后端
cui_win3 小时前
Redis 连接池被占满(泄漏)问题排查
java·redis·连接泄露
Doris_LMS3 小时前
JDK11的安装教程
java·jdk