Life has its own fate, and meeting may not be accidental.

0%

Spring-boot中java-poi导出execl

Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。

Apache POI

Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。

  • HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
  • XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
  • HWPF - 提供读写Microsoft Word DOC格式档案的功能。
  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
  • HDGF - 提供读Microsoft Visio格式档案的功能。
  • HPBF - 提供读Microsoft Publisher格式档案的功能。
  • HSMF - 提供读Microsoft Outlook格式档案的功能。

在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量,这时对于百万级别数据,Excel肯定容纳不了,而且在计算机性能稍低的机器上测试,就很容易导致堆溢出。而当我升级到XSSF对象时,它可以直接支持excel2007以上版本,因为它采用ooxml格式。这时excel可以支持1048576条数据,单个sheet表就支持近104万条数据了,虽然这时导出100万数据能满足要求,但使用XSSF测试后发现偶尔还是会发生堆溢出,所以也不适合百万数据的导出。

pom.xml依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>

因为我有点懒,不太想写Service层。
这个项目没有Service层,所以我都写在了controller

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.example.logSystem.controller;
import com.example.logSystem.mapper.LogMapper;
import com.example.logSystem.pojo.Log;
import org.apache.poi.hssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
* 生成数据表
*/
@RestController
@RequestMapping("/down")
public class Down {

@Autowired
// UserService userService;
LogMapper logMapper;

@RequestMapping("/export")
public String Export(HttpServletResponse response,String logdate,String classroom) throws IOException {

HSSFWorkbook workbook = new HSSFWorkbook(); // 创建一个Excel文件
HSSFSheet sheet = workbook.createSheet("日志表"); // 创建一个Excel的Sheet
// List<UserDetails> classmateList = userService.getUserDetails();
sheet.setDefaultColumnWidth(12);
System.out.println(logdate+" "+classroom);
List<Log> logList = logMapper.selectLog(logdate); //查询语句
System.out.println("yes");
// 设置要导出的文件的名字
String fileName = "Log" + new Date() + ".xls";

// 新增数据行,并且设置单元格数据
int rowNum = 1;

// headers表示excel表中第一行的表头 在excel表中添加表头
String[] headers= {"教师名字", "班级", "课程类型", "课程" , "教室" , "教室名称" , "应到" , "实到" , "日期" , "节次" , "故障设备数","备注"};
HSSFRow row = sheet.createRow(0); // 创建第一行
for(int i=0;i<headers.length;i++){
HSSFCell cell = row.createCell(i);
HSSFRichTextString text = new HSSFRichTextString(headers[i]);
cell.setCellValue(text);
}

//在表中存放查询到的数据放入对应的列
for (Log item : logList) {
HSSFRow row1 = sheet.createRow(rowNum);
row1.createCell(0).setCellValue(item.getTeachername()); //教室名称
row1.createCell(1).setCellValue(item.getClassname());
row1.createCell(2).setCellValue(item.getCoursetype());
row1.createCell(3).setCellValue(item.getCoursename());
row1.createCell(4).setCellValue(item.getClassroom());
row1.createCell(5).setCellValue(item.getClassroomname());
row1.createCell(6).setCellValue(item.getFalsenumber());
row1.createCell(7).setCellValue(item.getTruenumber());
row1.createCell(8).setCellValue(item.getLogdate());
row1.createCell(9).setCellValue(item.getSectionnumber());
row1.createCell(10).setCellValue(item.getMachine());
row1.createCell(11).setCellValue(item.getRemarks());
rowNum++;
}

//设置响应的文件格式为excel,编码格式
response.setContentType("application/vnd.ms-excel;charset=utf-8");
OutputStream os = response.getOutputStream();
// response.setHeader("Content-disposition", "attachment;filename=" + fileName);
//URLEncoder.encode(fileName,"UTF-8")能适配所有浏览器编码问题,具体的请查看源码
response.setHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode(fileName,"UTF-8"));
response.setCharacterEncoding("utf-8");
workbook.write(os);
os.flush();
os.close();
return "OK";
}
}

我的思路是在控制层写一个下载,当前端页面好了,对这这个接口进行post,页面接收到后就会生成一个execl来进行返回,其中数据是通过mybatis自动生成的查询框架来查询的。

利用postman 发送请求

其中如果表头是中文的话可以在编译器中吧编码从gdk改为utf-8,否则string会导致乱码。

以上代码参考(感谢):
请叫我头头哥