安装依赖
<!--通过注解的方式导出excel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.1</version>
</dependency>
注意踩坑:easyexcel会和poi的依赖冲突poi必须升级 4.0以上版本都可以不然 填充模版的时候会报错
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!--导出文件到Excel里面-->
<!--Apache POI是一个开源的Java库,用于处理Microsoft Office文件格式,包括.doc、.docx、.xls、.xlsx等。
poi-ooxml是这个库的一部分,专门用于处理Office Open XML格式的文件,如.docx和.xlsx。-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
Student实体类加Excel注解
package com.sky.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
//@ContentRowHeight //内容的行高
//@HeadRowHeight //表头的行高
@ExcelIgnoreUnannotated //没有注解的忽略不导出
public class Student {
@ExcelProperty("ID") //简单的头信息
@ExcelIgnore //不参与
private String id;
// @ExcelProperty(value={"学员信息表","学生姓名"}) //复杂的头信息
@ExcelProperty("学生姓名")
@ColumnWidth(20) //列宽
private String name;
// @ExcelProperty(value={"学员信息表","学生性别"}) //复杂的头信息
@ExcelProperty("学生性别")
private String gender;
// @ExcelProperty(value={"学员信息表","出生日期"}) //复杂的头信息 学员信息表第一个都是相同 会自动合并表头信息
@ExcelProperty("出生日期") //名称必须和Excel的文件表头一样 不然读取不到信息
@ColumnWidth(20) //列宽
@DateTimeFormat("yyyy-MM-dd")
private String birthday;
}
创建一个读取Student类的读取文档的监听器类StudentListener 继承AnalysisEventListener 重写方法
package com.sky.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.sky.entity.Student;
import com.sky.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
/*
* 读取文档的监听器类
* @Component 是Spring框架中的一个核心注解,它表示一个组件,可以是一个普通的Java类。
* 当你在一个类上使用 @Component 注解时,Spring会将其视为一个Spring组件,并将其自动注册为一个Spring bean。
* 就可以自动导入其他类使用
* */
@Component
@Scope("prototype") //多列 就可以交个容器 不需要new了
public class StudentListener extends AnalysisEventListener<Student> {
@Autowired
StudentService studentService;
ArrayList<Student> students=new ArrayList<>();
/*
* 每读一行内容,都会调用一次该对象的invoke,在invoke可以操作使用读取到的数据
* student 每次读取到的封装对象
* */
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
//如果这里读取不到数据,看看Student类里面是否设置了复杂的头 信息
//System.out.println("student="+student);
students.add(student); //这里是一条一条的读取数据 添加到集合里面去
//TODO 每读取5行数据 这里有个问题 少于5行的不读了 后续需要解决一下
if(students.size() % 5 == 0){ //满足5条才执行
studentService.readExcel(students);
students.clear(); //清空集合
}
}
/*
* 读取完整个文档之后调用的方法
* */
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("==============读取完之后掉用一次============");
if (students.size() > 0) {
studentService.readExcel(students);
students.clear(); // 清空集合
}
}
}
创建web接口上传和下载Excel文件
package com.sky.controller.admin;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.sky.entity.FillData;
import com.sky.entity.Student;
import com.sky.listener.StudentListener;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
@RestController
@RequestMapping("/admin/student")
@Api(tags = "学生类接口")
@Slf4j
public class StudentController {
@Autowired
StudentListener studentListener;
@GetMapping("/list")
@ApiOperation("学生导入列表")
public Result list(){
/**
* pathName 要读的文件的路径
* head 文件中每一行数据要存储到的实体类型的class
* readListener 读取监听器,每读一行内容,都会调用一次该对象的invoke,在invoke可以操作使用读取到的数据
* */
/*获得一个工作簿对象*/
ExcelReaderBuilder readWorkBook= EasyExcel.read("sky-server/src/main/resources/template/学生信息表.xlsx", Student.class,studentListener);
/*获得一个工作表对象 默认读取第一个工作表对象*/
ExcelReaderSheetBuilder sheet=readWorkBook.sheet();
/*读取工作表中内容*/
sheet.doRead();
return Result.success();
}
@GetMapping("/list1")
@ApiOperation("学生导出列表")
public Result list1(){
/**
* pathName 要写的文件的路径
* head 封装写入数据的实体类型
* 写的工作簿对象
* */
/*获得一个工作簿对象*/
ExcelWriterBuilder writeWorkBook= EasyExcel.write("sky-server/src/main/resources/template/学生信息表-writer.xlsx", Student.class);
/*获得一个工作表对象*/
ExcelWriterSheetBuilder sheet=writeWorkBook.sheet();
/*
* 准备数据
* */
List<Student> students=initData();
/*写*/
sheet.doWrite(students);
return Result.success();
}
/*
* 生成数据
*/
private static List<Student> initData(){
ArrayList<Student> students=new ArrayList<>();
Student data=new Student();
for (int i = 0; i <10 ; i++) {
data.setName("学生编号010"+i);
data.setBirthday("2012-03-04 12:12:12");
data.setGender("女");
data.setId("1");
students.add(data);
}
return students;
}
/*
* 生成数据
*/
private static List<FillData> initFillData(){
ArrayList<FillData> fillDatas=new ArrayList<FillData>();
for (int i = 0; i <10 ; i++) {
FillData fillData=new FillData();
fillData.setName("学生编号10"+i);
fillData.setAge(23);
fillDatas.add(fillData);
}
return fillDatas;
}
/*
* 上传的Excel文件 读取里面的内容存储到数据库
* */
@PostMapping("/list2")
@ApiOperation("上传Excel")
public Result uplond(MultipartFile uploadExcel) {
log.info("文件上传:{}", uploadExcel);
try {
/*获得一个工作簿对象*/
ExcelReaderBuilder readWorkBook= EasyExcel.read(uploadExcel.getInputStream(),Student.class,studentListener);
/*获得一个工作表对象 默认读取第一个工作表对象*/
ExcelReaderSheetBuilder sheet=readWorkBook.sheet();
/*读取工作表中内容*/
sheet.doRead();
return Result.success();
} catch (IOException e) {
e.printStackTrace();
}
return Result.error("上传错误");
}
/*
* 下载数据
* */
@GetMapping("/list3")
@ApiOperation("下载Excel")
public void uplonddowond(HttpServletResponse response) {
try {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 防止中文乱码
String fileName = URLEncoder.encode("测试","UTF-8");
response.setHeader("Content-Disposition","attachment; filename*=UTF-8''"+ fileName +".xlsx");
//3. 通过输出流将Excel文件下载到客户端浏览器
ServletOutputStream outputStream = response.getOutputStream();
/**
* pathName 要写的文件的路径
* head 封装写入数据的实体类型
* 写的工作簿对象
* */
/*获得一个工作簿对象*/
ExcelWriterBuilder writeWorkBook= EasyExcel.write(outputStream, Student.class);
/*获得一个工作表对象*/
ExcelWriterSheetBuilder sheet=writeWorkBook.sheet();
/*
* 准备数据
* */
List<Student> students=initData();
/*写*/
sheet.doWrite(students);
//关闭资源
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 按照规定的模块导入数据
* 单组数据按照模版填充
* */
@GetMapping("/list4")
@ApiOperation("单组数据按照模版填充")
public Result filldatalist() {
// 确定存储目录
String projectDir = System.getProperty("user.dir"); //获取当前项目的根目录
System.out.println(projectDir);
//准备模版
String templateName="sky-server/src/main/resources/template/templatedome1.xlsx";
String fileName ="sky-server/src/main/resources/template/success-单组数据.xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
// FillData fillData = new FillData();
// fillData.setName("张三");
// fillData.setAge(5);
//准备map数据
Map<String,String> map = new HashMap<String, String>();
map.put("name", "李四");
map.put("age", "55");
EasyExcel.write(fileName).withTemplate(templateName).sheet().doFill(map);
return Result.success();
}
/**
* 按照规定的模块导入数据
* 多组数据按照模版填充
* */
@GetMapping("/list5")
@ApiOperation("单组数据按照模版填充")
public Result filldatalist5() {
// 确定存储目录
String projectDir = System.getProperty("user.dir"); //获取当前项目的根目录
System.out.println(projectDir);
//准备模版
String templateName="sky-server/src/main/resources/template/templatedome2.xlsx";
String fileName ="sky-server/src/main/resources/template/success-多组数据.xlsx";
//准备数据
List<FillData> fillDataList=initFillData();
//填充数据,doXXX会在读写结束后自动关闭流
EasyExcel.write(fileName).withTemplate(templateName).sheet().doFill(fillDataList);
return Result.success();
}
/**
* 按照规定的模块导入数据
* 组合按照模版填充
* */
@GetMapping("/list6")
@ApiOperation("单组数据按照模版填充")
public Result filldatalist6() {
// 确定存储目录
String projectDir = System.getProperty("user.dir"); //获取当前项目的根目录
System.out.println(projectDir);
//准备模版
String templateName="sky-server/src/main/resources/template/templatedome3.xlsx";
String fileName ="sky-server/src/main/resources/template/success-组合数据.xlsx";
//准备数据
List<FillData> fillDataList=initFillData();
//创建一个手动关闭流 build()
ExcelWriter workBook=EasyExcel.write(fileName,FillData.class).withTemplate(templateName).build();
//创建工作表对象
WriteSheet sheet=EasyExcel.writerSheet().build();
//换行,不然组合的会覆盖
FillConfig fillConfig=FillConfig.builder().forceNewRow(true).build();
HashMap<String,String> dateAndTotal=new HashMap<>();
dateAndTotal.put("date","2023-12-12");
dateAndTotal.put("total","20000");
//多组填充
workBook.fill(fillDataList,fillConfig,sheet);
//单组填充
workBook.fill(dateAndTotal,sheet);
//关闭流
workBook.finish();
return Result.success();
}
/**
* 按照规定的模块导入数据
* 水平填充
* */
@GetMapping("/list7")
@ApiOperation("单组数据按照模版填充")
public Result filldatalist7() {
// 确定存储目录
String projectDir = System.getProperty("user.dir"); //获取当前项目的根目录
System.out.println(projectDir);
//准备模版
String templateName="sky-server/src/main/resources/template/templatedome4.xlsx";
String fileName ="sky-server/src/main/resources/template/success-水平填充.xlsx";
//准备数据
List<FillData> fillDataList=initFillData();
//创建一个手动关闭流 build()
ExcelWriter workBook=EasyExcel.write(fileName,FillData.class).withTemplate(templateName).build();
//创建工作表对象
WriteSheet sheet=EasyExcel.writerSheet().build();
//换行,不然组合的会覆盖
FillConfig fillConfig=FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
//多组填充
workBook.fill(fillDataList,fillConfig,sheet);
//关闭流
workBook.finish();
return Result.success();
}
/**
* 按照规定的模块导入数据
* 报表导出
* */
@GetMapping("/list8")
@ApiOperation("报表导出")
public Result filldatalist8() {
// 确定存储目录
String projectDir = System.getProperty("user.dir"); //获取当前项目的根目录
System.out.println(projectDir);
//准备模版
String templateName="sky-server/src/main/resources/template/运营数据统计.xlsx";
String fileName ="sky-server/src/main/resources/template/success-报表导出.xlsx";
//准备数据
List<Student> fillStudent=initData();
//创建一个手动关闭流 build()
ExcelWriter workBook=EasyExcel.write(fileName,Student.class).withTemplate(templateName).build();
//创建工作表对象
WriteSheet sheet=EasyExcel.writerSheet().build();
HashMap<String,String> dateAndTotal=new HashMap<>();
dateAndTotal.put("date","2023-12-12");
dateAndTotal.put("increaseCount","200");
dateAndTotal.put("totalCount","2000");
dateAndTotal.put("increaseCountWeek","20000");
dateAndTotal.put("increaseCountMonth","30000");
//单组填充
workBook.fill(dateAndTotal,sheet);
//多组填充
workBook.fill(fillStudent,sheet);
//关闭流
workBook.finish();
return Result.success();
}
}
模版1 templatedome1
模版2 templatedome2
模版3 templatedome3
模版4 templatedome4
报表模版