maven pom.xml下载poi包
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.17</version></dependency>
首先是实体类,也就是我们的数据集合
import java.util.List;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;import lombok.Data;
import lombok.experimental.Accessors;@Data
@Accessors(chain = true)
@TableName("test")
public class TestDomain {private String phone;private String parentPhone;@TableIdprivate String id;private String parentId;@TableField(exist = false)private List<TestDomain> children;/**列数*/@TableField(exist = false)private Integer colNumber;
}
再写个接口接收前端的导出请求,这里是使用的springboot 框架
@GetMapping("/test")public void test(HttpServletResponse response, HttpServletRequest request) throws IOException {// 查询数据库List<TestDomain> testDomains = testMapper.selectList(null);// 封装成树形结构TestTreeHandler testTreeHandler = new TestTreeHandler(testDomains);List<TestDomain> treeList = testTreeHandler.buildTree();//创建poi导出数据对象SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();//创建sheet页SXSSFSheet sheet = sxssfWorkbook.createSheet("sheet页名字");//创建表头SXSSFRow headRow = sheet.createRow(0);//设置表头信息headRow.createCell(0).setCellValue("父号码");headRow.createCell(1).setCellValue("子号码");// 遍历上面数据库查到的数据for (TestDomain testDomain : treeList) {//填充数据SXSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);//序号//看你实体类在进行填充dataRow.createCell(0).setCellValue(testDomain.getParentPhone());dataRow.createCell(1).setCellValue(testDomain.getPhone());testDomain.setColNumber(1);if(!CollectionUtils.isEmpty(testDomain.getChildren())) {child(testDomain.getChildren(), sheet,testDomain,dataRow);}}// 下载导出String filename = "导出excel表格名字";// 设置头信息response.setCharacterEncoding("UTF-8");response.setContentType("application/vnd.ms-excel");//一定要设置成xlsx格式response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename + ".xlsx", "UTF-8"));//创建一个输出流ServletOutputStream outputStream = response.getOutputStream();//写入数据sxssfWorkbook.write(outputStream);// 关闭outputStream.close();sxssfWorkbook.close();return null;}
递归子节点,往文件中逐级写入数据
/*** * @Title: child * @Description: 填充子节点数据 * @param childList 子节点数据* @param sheet 表格对象* @param parentDomain 父节点数据* @param parentRow 父节点行对象* void * @throws * @Author XX*/public static void child(List<TestDomain> childList,SXSSFSheet sheet,TestDomain parentDomain,SXSSFRow parentRow) {for (TestDomain testDomain : childList) {// 获取sheet的最后一行SXSSFRow childRow = sheet.createRow(sheet.getLastRowNum()+1);// 合并单元格sheet.addMergedRegion(new CellRangeAddress(childRow.getRowNum(), childRow.getRowNum(), 0, parentDomain.getColNumber()));// 设置子节点表头 parentDomain.getColNumber()+1 和 parentDomain.getColNumber()+2 表示根据父节点最大列数往后挪移1-2列,如果是10个字段就往后挪移1-10列parentRow.createCell(parentDomain.getColNumber()+1).setCellValue("父号码");parentRow.createCell(parentDomain.getColNumber()+2).setCellValue("子号码");// 填充数据childRow.createCell(parentDomain.getColNumber()+1).setCellValue(testDomain.getParentPhone());childRow.createCell(parentDomain.getColNumber()+2).setCellValue(testDomain.getPhone());testDomain.setColNumber(parentDomain.getColNumber()+2);if(!CollectionUtils.isEmpty(testDomain.getChildren())) {child(testDomain.getChildren(), sheet,testDomain,childRow);}}}
将LIST装换成树形结构的处理类
import java.util.ArrayList;
import java.util.List;import com.dadi01.scrm.service.mot.provider.domain.TestDomain;public class TestTreeHandler {/*** 递归封装树形菜单*/List<TestDomain> nodes = new ArrayList<TestDomain>();public TestTreeHandler(List<TestDomain> nodes) {super();this.nodes = nodes;}/*** * @Title: buildTree * @Description: 构建树形结构 * @return * List<TestDomain> * @throws * @Author XX*/public List<TestDomain> buildTree() {List<TestDomain> TestDomains = new ArrayList<TestDomain>();List<TestDomain> rootNodes = getRootNodes();for (TestDomain rootNode : rootNodes) {buildChildNodes(rootNode);TestDomains.add(rootNode);}return TestDomains;}/*** * @Title: buildChildNodes * @Description: 递归子节点 找出父节点下所有的层级 * @param node 上级节点 * void * @throws * @Author XX*/public void buildChildNodes(TestDomain node) {List<TestDomain> children = getChildNodes(node);if (!children.isEmpty()) {for (TestDomain child : children) {buildChildNodes(child);}node.setChildren(children);}}/*** * @Title: getChildNodes * @Description: 获取父节点下所有的子节点 * @param pnode 父节点* @return * List<TestDomain> * @throws * @Author XX*/public List<TestDomain> getChildNodes(TestDomain pnode) {List<TestDomain> childNodes = new ArrayList<TestDomain>();for (TestDomain n : nodes) {if (pnode.getId().equals(n.getParentId())) {childNodes.add(n);}}return childNodes;}/*** * @Title: rootNode * @Description: 判断是否为根节点 * @param node 当前节点* @return * boolean * @throws * @Author XX*/public boolean rootNode(TestDomain node) {return "0".equals(node.getParentId());}/*** * @Title: getRootNodes * @Description: 获取集合中所有的根节点 * @return * List<TestDomain> * @throws * @Author XX*/public List<TestDomain> getRootNodes() {List<TestDomain> rootNodes = new ArrayList<TestDomain>();for (TestDomain n : nodes) {if (rootNode(n)) {rootNodes.add(n);}}return rootNodes;}
}
浏览器敲地址访问就行了
http://localhost:8182/v1/excel/test
导出的文件内容 0为根节点