private void exportExcel(String versionId, String versionName, List<String> caseTypeVOS, HttpServletResponse response) {
ArchiveDirExcelExportDTO dirExcelExportDTO = new ArchiveDirExcelExportDTO();
dirExcelExportDTO.setVersionId(versionId);
List<List<String>> caseTypeCodes = TreeUtil.groupList(caseTypeVOS, 5);
try {
//新建ExcelWriter
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
int j = 0;
for (int i = 0; i < caseTypeCodes.size(); i++) {
dirExcelExportDTO.setCaseTypeCodes(caseTypeCodes.get(i));
List<ArchiveDirExcelExportVO> archiveDirExcelExportVOS = new ArrayList<>();
archiveDirExcelExportVOS.addAll(archiveDirectoryService.archiveDirectory(dirExcelExportDTO));
archiveDirExcelExportVOS.addAll(archiveDirMaterialRelationService.archiveDirMaterialRelation(dirExcelExportDTO));
//根据案件类型分组
Map<String, List<ArchiveDirExcelExportVO>> archiveDirExcelExportMap = archiveDirExcelExportVOS.stream().sorted(Comparator.comparing(ArchiveDirExcelExportVO::getDossierAttrCode, Comparator.nullsFirst(Integer::compareTo)).thenComparing(ArchiveDirExcelExportVO::getDirSequence, Comparator.nullsFirst(Long::compareTo)).reversed()).collect(Collectors.groupingBy(ArchiveDirExcelExportVO::getCaseTypeName));
//archiveDirExcelExportVOS.stream().sorted(Comparator.comparing(ArchiveDirExcelExportVO::getDossierAttrCode, Comparator.nullsFirst(Integer::compareTo)).reversed()).collect(Collectors.groupingBy(ArchiveDirExcelExportVO::getCaseTypeName));
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode(versionName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
for (String caseTypeName : archiveDirExcelExportMap.keySet()) {
//获取案件类型名称
List<ArchiveDirExcelExportVO> archiveDirExcelList = TreeUtil.wrapperTreeTest(archiveDirExcelExportMap.get(caseTypeName));
List<ArchiveDirExcelExportVO> archiveDirExcelExportList = TreeUtil.listAllPathByNotRecursion(archiveDirExcelList);
//获取sheet i对象
WriteSheet mainSheet = EasyExcel.writerSheet(j, caseTypeName).head(ArchiveDirExcelExportVO.class).build();
//获取模型信息,向sheet i 写入数据
excelWriter.write(archiveDirExcelExportList, mainSheet);
j++;
}
//关闭流
}
excelWriter.finish();
} catch (IOException e) {
log.error("导出异常{}", e.getMessage());
}
}
对于树的一些处理方法,工具类如下:
package cn.com.chnsys.util;
import cn.com.chnsys.enums.DirectoryTypeEnum;
import cn.com.chnsys.vo.ArchiveDirExcelExportVO;
import cn.com.chnsys.vo.directory.ArchiveDirectoryVO;
import cn.com.chnsys.vo.directory.ArchiveTreeCommonVO;
import cn.hutool.core.collection.CollectionUtil;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
/**
* @Description:
* @Author:
* @Datetime: 2022/11/20 16:01
* @Version: 1.0
*/
public class TreeUtil {
// class MultiTree{
// private ArchiveDirExcelExportVO root;
// }
/**
* 非递归方法输出所有路径
*/
public static List<ArchiveDirExcelExportVO> listAllPathByNotRecursion(List<ArchiveDirExcelExportVO> archiveDirectoryVOS) {
//清空路径容器
// this.pathList.clear();
List<String> pathList = new ArrayList<>();
List<ArchiveDirExcelExportVO> leafMaterial = new ArrayList<>();
//主栈,用于计算处理路径
Deque<ArchiveDirExcelExportVO> mainStack = new ArrayDeque();
//副栈,用于存储待处理节点
Deque<ArchiveDirExcelExportVO> minorStack = new ArrayDeque();
if (CollectionUtil.isNotEmpty(archiveDirectoryVOS)) {
minorStack.addLast(archiveDirectoryVOS.get(0));
} else {
return null;
}
//判断是不是所有的叶子节点遍历完毕
HashMap<String, Integer> popCount = new HashMap<>();
// String curString = "";
while (!minorStack.isEmpty()) {
//出副栈,入主栈
ArchiveDirExcelExportVO minLast = minorStack.pollLast();
mainStack.addLast(minLast);
// curString += minLast.getArchiveDirName() + "->";
//将该节点的子节点入副栈
if (CollectionUtil.isNotEmpty(minLast.getArchiveChilds())) {
List<ArchiveDirExcelExportVO> childs = minLast.getArchiveChilds();
Iterator<ArchiveDirExcelExportVO> iterator = childs.iterator();
while (iterator.hasNext()) {
ArchiveDirExcelExportVO s = iterator.next();
minorStack.addLast(s);
}
}
//出主栈
ArchiveDirExcelExportVO majLast = mainStack.peekLast();
//循环条件:栈顶为叶子节点 或 栈顶节点孩子节点遍历完了(需要注意空指针问题)
while (majLast != null && (CollectionUtil.isEmpty(majLast.getArchiveChilds()) ||
(popCount.get(majLast.getArchiveDirId()) != null &&
popCount.get(majLast.getArchiveDirId()).equals(majLast.getArchiveChilds().size())))) {
ArchiveDirExcelExportVO last = mainStack.pollLast();
majLast = mainStack.peekLast();
// if (majLast == null) { //此时主栈为空,运算完毕
// return pathList;
// }
if (majLast == null) { //此时主栈为空,运算完毕
return leafMaterial;
}
if (popCount.get(majLast.getArchiveDirId()) == null) {//第一次弹出孩子节点,弹出次数设为1
popCount.put(majLast.getArchiveDirId(), 1);
} else { //非第一次弹出孩子节点,在原有基础上加1
popCount.put(majLast.getArchiveDirId(), popCount.get(majLast.getArchiveDirId()) + 1);
}
// String lastContent = last == null ? "" : last.getArchiveDirName();
if (last != null && CollectionUtil.isEmpty(last.getArchiveChilds())) {//如果是叶子节点才将结果加入路径集中
// pathList.add(curString.substring(0, curString.length() - 2));
if (DirectoryTypeEnum.DIRECTORY_TYPE_ENUM_3.getValue().equals(last.getType())) {
last.setParentDirName(last.getArchiveDirName());
last.setArchiveDirName("");
}
leafMaterial.add(last);
}
//调整当前curString,减去2是减的“->”这个符号
// curString = curString.substring(0, curString.length() - lastContent.length() - 2);
}
}
return leafMaterial;
}
/**
* 先序遍历
*
* @param archiveList
* @param number
* @return
*/
public static List<ArchiveDirExcelExportVO> preorder(ArchiveDirExcelExportVO archiveList, Integer number) {
//结果集
List<ArchiveDirExcelExportVO> res = new ArrayList<>();
//节点为空
if (archiveList == null) {
return res;
}
//创建栈
Deque<ArchiveDirExcelExportVO> stack = new ArrayDeque<>();
//添加头节点,赋值id与父id
// archiveList.setDirNumberId(number);
// archiveList.setDirNumberPId(Integer.valueOf(DirectoryConstant.TOP_ID));
stack.add(archiveList);
//遍历
while (!stack.isEmpty()) {
//出栈
ArchiveDirExcelExportVO node = stack.pollLast();
//node.setDirNumberId(number);
//添加节点值
res.add(node);
number++;
//添加孩子节点到头部
if (CollectionUtil.isNotEmpty(node.getArchiveChilds())) {
for (int i = node.getArchiveChilds().size() - 1; i > -1; --i) {
//赋值父id
// node.getArchiveChilds().get(i).setDirNumberPId(node.getDirNumberId());
stack.addLast(node.getArchiveChilds().get(i));
}
}
}
return res;
}
/**
* 构建 树结构
*
* @param treeList
* @param topId
* @param <T>
* @return
*/
public static <T extends ArchiveTreeCommonVO<T>> List<T> buildTree(List<T> treeList, String topId) {
List<T> trees = new ArrayList<>();
for (T tree : treeList) {
if (topId.equals(tree.getParentDirId())) {
trees.add(buildChildren(tree, treeList));
}
}
return trees;
}
public static <T extends ArchiveTreeCommonVO<T>> T buildChildren(T tree, List<T> treeList) {
for (T node : treeList) {
if (tree.getArchiveDirId().equals(node.getParentDirId())) {
if (tree.getArchiveChilds() == null) {
tree.setArchiveChilds(new ArrayList<>());
}
tree.getArchiveChilds().add(buildChildren(node, treeList));
}
}
return tree;
}
/**
* 组装树
*/
public static <T extends ArchiveTreeCommonVO<T>> List<T> wrapperTreeTest(List<T> archiveDirectoryVOS) {
Map<String, T> treeVoMap = archiveDirectoryVOS.stream().collect(Collectors.toMap(ArchiveTreeCommonVO::getArchiveDirId, i -> i));
//获取顶级树节点
List<T> rootList = archiveDirectoryVOS.stream().filter(i -> !treeVoMap.containsKey(i.getParentDirId())).collect(toList());
for (T treeVo : archiveDirectoryVOS) {
if (treeVoMap.containsKey(treeVo.getParentDirId())) {
T parentTree = treeVoMap.get(treeVo.getParentDirId());
List<T> children = parentTree.getArchiveChilds();
children.add(treeVo);
}
}
return rootList;
}
/**
* 把树转为平级的list
*
* @param treeList
* @param archiveDirectorys
* @return
*/
public static List<ArchiveDirectoryVO> treeToLevelStructure(List<ArchiveDirectoryVO> treeList, List<ArchiveDirectoryVO> archiveDirectorys) {
if (CollectionUtil.isNotEmpty(treeList)) {
long number = 1;
for (ArchiveDirectoryVO archiveDirectoryVO : treeList) {
archiveDirectoryVO.setDirSequence(number);
archiveDirectorys.add(archiveDirectoryVO);
number++;
List<ArchiveDirectoryVO> childrenList = archiveDirectoryVO.getArchiveChilds();
if (CollectionUtil.isNotEmpty(childrenList)) {
treeToLevelStructure(childrenList, archiveDirectorys);
}
}
}
return treeList;
}
/**
* 集合拆分
*
* @param list 原集合
* @param pageSize 子集合长度
* @param <T>
* @return
*/
public static <T> List<List<T>> groupList(List<T> list, int pageSize) {
List<List<T>> listGroup = new ArrayList<List<T>>();
int listSize = list.size();
for (int i = 0; i < listSize; i += pageSize) {
if (i + pageSize > listSize) {
pageSize = listSize - i;
}
List<T> newList = list.subList(i, i + pageSize);
listGroup.add(newList);
}
return listGroup;
}
/**
* 组装树
*/
// public static List<ArchiveDirectoryVO> wrapperTreeTest(List<ArchiveDirectoryVO> archiveDirectoryVOS) {
//
// Map<String, ArchiveDirectoryVO> treeVoMap = archiveDirectoryVOS.stream().collect(Collectors.toMap(ArchiveTreeCommonVO::getArchiveDirId, i -> i));
// //获取顶级树节点
//
// List<ArchiveDirectoryVO> rootList = archiveDirectoryVOS.stream().filter(i -> !treeVoMap.containsKey(i.getParentDirId())).collect(toList());
// for (ArchiveDirectoryVO treeVo : archiveDirectoryVOS) {
// if (treeVoMap.containsKey(treeVo.getParentDirId())) {
// ArchiveDirectoryVO parentTree = treeVoMap.get(treeVo.getParentDirId());
// List<ArchiveDirectoryVO> children = parentTree.getArchiveChilds();
// children.add(treeVo);
// }
// }
//
// return rootList;
// }
// public static List<ArchiveDirectoryVO> genTree(List<ArchiveDirectoryVO> treeList, String topId) {
// List<ArchiveDirectoryVO> trees = new ArrayList<>();
// for (ArchiveDirectoryVO tree : treeList) {
// if (topId.equals(tree.getParentDirId())) {
// trees.add(findChildren(tree, treeList));
// }
// }
// return trees;
// }
//
// public static ArchiveDirectoryVO findChildren(ArchiveDirectoryVO tree, List<ArchiveDirectoryVO> treeList) {
// for (ArchiveDirectoryVO node : treeList) {
// if (tree.getArchiveDirId().equals(node.getParentDirId())) {
// if (tree.getArchiveChilds() == null) {
// tree.setArchiveChilds(new ArrayList<>());
// }
// tree.getArchiveChilds().add(findChildren(node, treeList));
// }
// }
// return tree;
// }
// public boolean isSameTree(List<ArchiveDirectoryVO> localTrees, List<ArchiveDirectoryVO> externalTrees) {
// if (localTrees == null && externalTrees == null) {
// return true;
// }
// if (localTrees == null || externalTrees == null) {
// return false;
// }
// List<String> trees = externalTrees.stream().map(ArchiveDirectoryVO::getArchiveDirName).collect(Collectors.toList());
// for (ArchiveDirectoryVO localTree : localTrees) {
// if (trees.contains(localTree.getArchiveDirName())) {
// for (ArchiveDirectoryVO externalTree : externalTrees) {
// if (localTree.getArchiveDirName().equals(externalTree.getArchiveDirName())) {
// isSameTree(localTree.getArchiveChilds(), externalTree.getArchiveChilds());
// break;
// }
else {
externalTree.setSign("2");
//getParentNode(localTrees,localTree,"2");
//getChildNode(localTrees,localTree,"2");
}
// }
// } else {
// localTree.setSign("1");
// //getParentNode(localTrees,localTree,"1");
// // getChildNode(localTrees,localTree,"1");
// }
// break;
//
// }
// return true;
// }
}