java 中 excel 的写入和导出使用的是 阿里巴巴的 EasyExcel
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
生成Excel
首先根据要生成的表格的 字段创建相应的实体类
可以在 ExcelProperty 中设置value(表头字段名) index(这个是读取时使用的列的序号, 从0开始)
@DateTimeFormat() 用来设置表中的日期显示格式 @NumberFormat(“#.##%”) 用来设置数字的显示格式
package com.huang.testrenren.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import java.util.Date;
@Data
public class StudentMode {
@ExcelProperty(value = "学生id",index = 0)
private Integer id;
@ExcelProperty(value = "学生姓名",index = 1)
private String name;
@ExcelProperty(value = "学生性别",index = 2)
private String sex;
//这里是 alibaba 的 DateTimeFormat 生成表格时的日期格式
@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
@ExcelProperty(value = "创建日期",index = 3)
private Date createTime;
/**
* 我想写到excel 用百分比表示
@NumberFormat("#.##%")
@ExcelProperty(value = "数字标题")
private Double doubleData;
*/
}
创建一批数据, 后面的代码中就不写了
//创建一批数据
ArrayList<StudentMode> stu = new ArrayList<>();
for (int i=0;i<10;i++){
StudentMode studentMode = new StudentMode();
studentMode.setId(i);
studentMode.setName("huang"+i);
studentMode.setSex("女"+i);
studentMode.setCreateTime(new Date());
stu.add(studentMode);
}
方法一 (这种方法适合数据量不大, 可以一次性写入数据的情况)
String path = "D:/myWrite1.xlsx"; //写入xlsx 的文件
EasyExcel.write(path,StudentMode.class).sheet("学生信息表").doWrite(stu);
方法二 (这种方法适合数量比较大,可以用来写入数据量比较多的情况)
try{
ExcelWriter excelWriter = EasyExcel.write(path, StudentMode.class).build();
WriteSheet sheet = EasyExcel.writerSheet("学生信息表").build();
//就用上面的 ArrayList stu
excelWriter.write(stu, sheet);
//excelWriter 会自动 close
//如果我们有很多数据写入的话, 在这里, 我们可以使用 循环
// 比如说从数据库中 查出分页的数据, 再写入表中
/** 下面是伪代码
for(int page = 1;page<10;page++){
pagestulist = ....
excelWriter.write(pagestulist,sheet)
}
*/
}catch (Exception e){
System.out.printf(e.getMessage());
}
通过模板写入数据
个人认为, 通过模板写入数据, 好像就是把模板的数据和新加的数据合起来写入了 excel 表中
首选去新建一个模板,然后, 再指定新的生成的 xlsx 文件的路径
String demopath = "C:\\Users\\Administrator\\Desktop\\学生信息表.xlsx"; //模板文件的位置
String filename = "D:/mywriteWithModel.xlsx"; //新生成的文件的位置
//就用上面的 ArrayList stu
EasyExcel.write(filename, StudentMode.class).withTemplate(demopath).sheet().doWrite(stu);
在web 项目中写excel
有时候我们在 web 项目中, 会使用 下载表格成 excel 的功能
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}
如果我们下载excel时表单出错了, 可以这样返回 json 数据 , 主要要注意 catch 语句中的 response.reset
@GetMapping("downloadFailedUsingJson")
public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
try {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
.doWrite(data());
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = MapUtils.newHashMap();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
读取excel
EasyExcel 的读取excel 主要是使用的监听器,读取时的操作逻程就是写在监听器的方法中
方法
创建一个相应的监听器,继承 ReadListener(T) 加上,表的实例对象, T
比如我们要读取上面的 生成出来的 excel 文件
第一步, 创建 StudentMode 的类, 这个已经创建过了
第二步, 创建 ReadListener<StudentMode>
package com.huang.testrenren.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import java.util.Map;
public class StudentModeReadListener implements ReadListener<StudentMode> {
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
//这个方法可以得到表头的信息
// System.out.println(headMap.get(0).getStringValue());
// Set<Integer> integers = headMap.keySet();
// for (Integer integer : integers) {
// String stringValue = headMap.get(integer).getStringValue();
// System.out.println(stringValue);
//}
System.out.println("***"+headMap);
}
@Override
public void invoke(StudentMode studentMode, AnalysisContext analysisContext) {
//这个方法可以得到表中的数据信息
//逻辑方法可以写在这里面, 比如对数据的处理, 或者把数据 存入数据库
System.out.println("****"+studentMode);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//这里是最后执行的方法, 可以用来关闭 资源句柄什么的
}
}