语言 java

框架 ssm

需求 :看图  也是导出效果

数据库查询为(关系为一对多) 一个学生对应多个课程

实现步骤

1.实体类配置, 建议单独写个实体用来导出使用()

学生信息字段正常配置  , 课程表字段 使用  @ExcelProperty({"学生和选课中间表","学生编号"})

StudentExcel.java

package com.example.mybatisplus.pojo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import java.io.Serializable;
import java.util.Date; /**
* easy_excel导出
* @author three
* @date 2021/8/23 16:13
*/
@ApiModel("easy_excel导出实体类")
@Data
public class StudentExcel implements Serializable {
private static final long serialVersionUID = 1L; // ----学生信息表( 一 ) @ExcelProperty("学生姓名")
@ApiModelProperty("学生姓名")
private String sname; @ExcelProperty("性别")
@ApiModelProperty("性别")
private String sgender; @ExcelProperty("出生年月")
@ApiModelProperty("出生年月")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date sbirth; //----学生和选课中间表(多)---- @ExcelProperty({"学生和选课中间表","学生编号"})
@ApiModelProperty("学生编号")
private Integer sno; @ExcelProperty({"学生和选课中间表","课程编号"})
@ApiModelProperty("课程编号")
private String cno; @ExcelProperty({"学生和选课中间表","分数"})
@ApiModelProperty("分数")
private String score;
}

2.代码 工具类  ExcelFillCellMergeStrategy.java

package com.example.mybatisplus.utils;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress; import java.util.List; public class ExcelFillCellMergeStrategy implements CellWriteHandler { private int[] mergeColumnIndex;
private int mergeRowIndex; public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
} @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { } @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
int curRowIndex = cell.getRowIndex();
int curColIndex = cell.getColumnIndex();
if (curRowIndex > mergeRowIndex) {
for (int i = 0; i < mergeColumnIndex.length; i++) {
if (curColIndex == mergeColumnIndex[i]) {
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
break;
}
}
}
} /**
* 当前单元格向上合并
*
* @param writeSheetHolder
* @param cell 当前单元格
* @param curRowIndex 当前行
* @param curColIndex 当前列
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
// 将当前单元格数据与上一个单元格数据比较
Boolean dataBool = preData.equals(curData);
if (dataBool) {
Sheet sheet = writeSheetHolder.getSheet();
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
} }

3. EasyExcelController.java

3.1 int[] mergeColumeIndex = {0,1,2};  数据重复部分会合并成一个单元格,只需标出需要合并的列数

3.2  int mergeRowIndex = 0; 标出合并的开始列数 从0开始

package com.example.mybatisplus.controller;

import com.alibaba.excel.EasyExcel;
import com.example.mybatisplus.pojo.StudentExcel;
import com.example.mybatisplus.pojo.StudentinfoEntity;
import com.example.mybatisplus.service.StudentinfoService;
import com.example.mybatisplus.utils.ExcelFillCellMergeStrategy;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.*; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List; /**
* EasyExcel test
* 测试地址 http://localhost:8088/easy-excel/export
* 传输数据 [1,2,3]
* @author zou
* @date 2021/8/23 15:51
*/
@Api(tags = "easy-excel的使用")
@RestController
@RequestMapping("/easy-excel")
public class EasyExcelController { @Resource
private StudentinfoService studentinfoService; @PostMapping("/export")
@ApiOperation("导出excel(一对多关系)")
public void excel(HttpServletResponse response,@RequestBody Integer[] sno) throws IOException {
List<StudentExcel> studentinfoEntities = studentinfoService.studentToElectives(sno);
// 设置响应格式
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
//需要合并的列
int[] mergeColumeIndex = {0,1,2};
// 从那一列开始合并
int mergeRowIndex = 0;
String fileName = URLEncoder.encode("one-to-many", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), StudentExcel.class)
.sheet("one-to-many")
.registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex))
.doWrite(studentinfoEntities);
}
}

4.服务层,持久层略去一千行....

....

easyExcel合并数据导出(一对多)的更多相关文章

  1. 数据的动态合并和导出至EXCEL

    最近一段时间都在处理数据的动态合并和导出EXCEL的问题,写个demo记录下,希望和我碰到同样问题的博友可以顺利解决:后面会提供demo下载链接. (VS2012,ASP.NET) 一.主要解决以下问 ...

  2. php 数据导出到excel 2种带有合并单元格的导出

    具体业务层面 可能会有所不同.以下两种方式涉及的合并单元格地方有所不同,不过基本思路是一致的. 第一种是非插件版本.可能更容易理解点,基本思路就是 组装table 然后 读取 输出到excel上.缺点 ...

  3. 使用VUE+SpringBoot+EasyExcel 整合导入导出数据

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据 创建一个普通的maven项目即可 项目目录结构 1 前端 存放在resources/static 下 index.html &l ...

  4. EasyExcel实现文件导出

    官网:https://www.yuque.com/easyexcel/doc/easyexcel 导出 准备工作 引入依赖 <!--EasyExcel相关依赖--> <depende ...

  5. 百度地图里面搜索到的公司商家电话导出表格?怎样将把百度地图里面搜索到的公司 电话 地址 等数据导出excel里?

    好多人在问:如何将百度地图里面搜索到的公司商家电话导出表格?怎样将把百度地图里面搜索到的公司 电话 地址 等数据导出excel里? 现在,很多人都在网络上找商家,联系业务. 百度地图里有很多的商家联系 ...

  6. asp.net将数据导出到excel

    本次应用datatable导出,若用gridview(假设gridview设为了分页显示)会出现只导出当前页的情况. protected void btnPrn_Click(object sender ...

  7. Java使用POI实现数据导出excel报表

    Java使用POI实现数据导出excel报表 在上篇文章中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅 ...

  8. Delphi 数据导出到Excel

    好多办公软件特别是财务软件,都需要配备把数据导出到Excel,下面就来介绍两种数据导出方法 1.ADODB导出查询结果(此方法需要安装Excel) 2.二维表数据导出(根据Excel文件结构生成二进制 ...

  9. 树结构关系的数据导出为excel

    该文针对的是关于树结构的数据的导出,每一个节点都可以创建不定数的子节点,在选择好某个节点进行导出 时,会把该节点以及子节点的数据都导出来.导出后的excel的格式大概如下图的形式,这个是一个比较理想 ...

  10. java实现Excel数据导出

    java实现Excel数据导出: 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta POI和Java Excel Jakarta POI 是一套用于访问微软格式文档的Java ...

随机推荐

  1. 【Azure 事件中心】如何查看Event Hub的生产者或者是消费者端的IP地址呢?

    问题描述 哪些客户端 IP 正在向/从Azure Event Hub发送/接收事件?如何来查看Event Hub的生产者端,消费者端的IP地址呢? 问题解答 如果需要查看Event Hub 服务端的日 ...

  2. 【Azure 应用服务】如何从App Service for Linux 的环境中下载Container中非Home目录下的文件呢?

    问题描述 在App Service for Linux的环境中,我们能通过SSH进入到Container的环境中,并且可以通过在kudu站点的URL后面添加 /newui 打开一个适用于Linux环境 ...

  3. 答应我,在vue中不要滥用watch好吗?

    前言 上周五晚上8点,开开心心的等着产品验收完毕后就可以顺利上线.结果产品突然找到我说要加需求,并且维护这一块业务的同事已经下班走了,所以只有我来做.虽然内心一万头草泥马在狂奔,但是嘴里还是一口答应没 ...

  4. Java11改进的垃圾回收器

    传统的C/C++等编程语言,需要程序员负责回收已经分配的内存.显示进行垃圾回收是一件比较困难的事情,因为程序员并不总是知道内存应该何时被释放.如果一些分配出去的内存得不及时回收,就会引起系统运行速度下 ...

  5. C++ //STL---常用算法 //常用遍历 for_each //transform

    1 //STL---常用算法 2 //常用遍历 for_each 3 //transform 4 #include<iostream> 5 #include<string> 6 ...

  6. c语言四则运算小程序

    本文源程序代码来源于csdn一位博主: 文章链接:http://t.csdnimg.cn/L29fs 原程序简洁凝练,以简短的代码写出了一个加法运算器. 以下是运行结果(本文全程用visual stu ...

  7. Android系统瘦身

    文件格式: Windows常见的文件系统是FAT16.FAT32,NTFS,在Windows环境提供了分区格式转换工具,可以在DOC环境下 使用  Convert命令(Convert e:/fs:nt ...

  8. Python基础之程序与用户交互

    [一]Python基础之程序与用户交互 [一]程序如何与用户交互 用户通过input命令在窗口内与输入就可以让用户和窗口进行交流 input接受的所有数据类型都是 str 类型 username = ...

  9. Github无法读取远程仓库

    主页 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ Git无法访问 今早起来访问Github炸了,Git不能用了,提示: ...

  10. whale - awesome 关联单词

    whale - awesome 关联单词 whale 对应 awesome 里面的 awe 两个含义应该是一样的. whale wa哇-惊叹词-大型海洋生物-鲸鱼 来自古英语hwael,大型海洋生物, ...