目录
一、前言
二、使用
2、导出示例
2.2.直接将List>数据导出为excel示例(无需模板)
2.3.通过注解,直接将Object(集合)数据导出为excel示例(无需模板)
一、前言
1、目前个人调查,关于excel的操作,使用较多的有Apache POI、EasyPoi、EasyExcel;Apache POI是Apache旗下的产品,之前用过一次,感受不怎么友好,api太多了,EasyExcel是阿里出的一款产品;个人觉得EasyPoi文档比较全面,所以本次使用EasyPoi进行导出
easyExcel地址 https://www.yuque.com/easyexcel/doc/easyexcel
2、EasyPoi文档地址:http://easypoi.mydoc.io
地址2:http://doc.wupaas.com/docs/easypoi/easypoi-1c0u4mo8p4ro8
二、使用
1、导入以下依赖
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
或者以下依赖
<!-- easy-poi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.0</version>
</dependency>
2、导出示例
官网说明了Excel的导入导出是Easypoi的核心功能,基本也是围绕这个打造的,主要分为三种方式的处理
- 注解方式,注解变种方式
- 模板方式
- Html方式
其中模板和Html目前只支持导出,因为支持Map.class其实导入应该是怎样都支持的
模板标签语法
看一个常见的到处模板--专项支出用款申请书
代码如何写?这里介绍四种使用示例
2.1.使用定义好的模板
定义好的excel模板放在项目resource下
使用模板将Map<String, Object>数据导出为excel示例(需要模板)
// 模板导出---Map组装数据
// 注:.xls的模板可以导出.xls文件,也可以导出xlsx的文件;同样的, .xlsx的模板可以导出.xls文件,也可以导出xlsx的文件;
@Test
public void templateExportExcelByMap() throws IOException {
// 加载模板
TemplateExportParams params = new TemplateExportParams("templates/templateMap.xls");
Map<String, Object> map = new HashMap<>(16);
map.put("title", "全亚洲,最帅气人员名单");
map.put("date", "2018-12-05");
map.put("interviewer", "JustryDeng");
List<Map<String, Object>> list = new ArrayList<>(16);
Map<String, Object> tempMap;
for (int i = 0; i < 5; i++) {
tempMap = new HashMap<>();
tempMap.put("name", "邓沙利文");
tempMap.put("gender", new Random().nextInt(2) == 0 ? "男" : "女");
tempMap.put("age", new Random().nextInt(90) + 11);
tempMap.put("hobby", "活的,女的!!!");
tempMap.put("handsomeValue", "100分(满分100分)");
tempMap.put("motto", "之所以只帅到了全亚洲,是因为其他地方审美不同!");
list.add(tempMap);
}
map.put("dataList", list);
// 生成workbook 并导出
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
File savefile = new File("E:/temp/easypoi");
if (!savefile.exists()) {
boolean result = savefile.mkdirs();
System.out.println("目录不存在,进行创建,创建" + (result ? "成功!" : "失败!"));
}
FileOutputStream fos = new FileOutputStream("E:/temp/easypoi/采访结果.xls");
workbook.write(fos);
fos.close();
}
使用模板将Object数据导出为excel示例(需要模板)
// 模板导出---对象组装数据
// 注:实际上仍然是"模板导出---Map组装数据",不过这里借助了工具类,将对象先转换为了Map<String, Object>
// 注:.xls的模板可以导出.xls文件,也可以导出xlsx的文件;同样的, .xlsx的模板可以导出.xls文件,也可以导出xlsx的文件;
@Test
public void templateExportExcelByObject() throws IOException, IllegalAccessException {
// 加载模板
TemplateExportParams params = new TemplateExportParams("templates/templateObject.xlsx");
// 组装数据
InterviewResult interviewResult = new InterviewResult();
interviewResult.setTitle("全亚洲最帅人员名单");
interviewResult.setInterviewer("邓沙利文");
interviewResult.setDate("2018-12-05");
List<HandsomeBoy> list = new ArrayList<>(8);
interviewResult.setList(list);
HandsomeBoy handsomeBoy;
for (int i = 0; i < 5; i++) {
handsomeBoy = new HandsomeBoy();
handsomeBoy.setAge(20 + i);
handsomeBoy.setGender(i % 2 == 0 ? "女" : "男");
handsomeBoy.setHandsomeValue(95 + i + "(满分100分)");
handsomeBoy.setHobby("女。。。。");
handsomeBoy.setMotto("我是一只小小小小鸟~");
handsomeBoy.setName("JustryDeng");
list.add(handsomeBoy);
}
// 生成workbook 并导出
Workbook workbook = ExcelExportUtil.exportExcel(params, objectToMap(interviewResult));
File savefile = new File("E:/temp/easypoi");
if (!savefile.exists()) {
boolean result = savefile.mkdirs();
System.out.println("目录不存在,进行创建,创建" + (result ? "成功!" : "失败!"));
}
FileOutputStream fos = new FileOutputStream("E:/temp/easypoi/采访结果.xlsx");
workbook.write(fos);
fos.close();
}
2.2.直接将List<Map<String, Object>>数据导出为excel示例(无需模板)
/**
* 直接导出(无需模板) 注:此方式存在一些不足之处,在对性能、excel要求比较严格时不推荐使用
*
* @throws IOException
*/
@Test
public void directExportExcel() throws IOException {
// Map作为每一行的数据容器,List作为行的容器
List<Map<String, Object>> rowDataList = new ArrayList<>();
// 每个ExcelExportEntity存放Map行数据的key
List<ExcelExportEntity> keyList = new ArrayList<>();
Map<String, Object> aRowMap;
final int COMMON_KEY_INDEX = 10;
for (int i = 0; i < 5; i++) {
// 一个Map对应一行数据(如果需要导出多行数据,那么需要多个Map)
aRowMap = new HashMap<>(16);
for (int j = 0; j < COMMON_KEY_INDEX; j++) {
String key = j + "";
aRowMap.put(key, "坐标(" + i + "," + j + ")");
}
rowDataList.add(aRowMap);
// 同一列对应的cell,在从Map里面取值时,会共用同一个key
// 因此ExcelExportEntity的个数要保持和列数做多的行 的map.size()大小一致
if (i == 0) {
ExcelExportEntity excelExportEntity;
for (int j = 0; j < COMMON_KEY_INDEX; j++) {
excelExportEntity = new ExcelExportEntity();
excelExportEntity.setKey(j + "");
// 设置cell宽
excelExportEntity.setWidth(15D);
// 设置cell是否自动换行
excelExportEntity.setWrap(true);
keyList.add(excelExportEntity);
}
}
}
// excel总体设置
ExportParams exportParams = new ExportParams();
// 不需要标题
exportParams.setCreateHeadRows(false);
// 指定sheet名字
exportParams.setSheetName("直接导出数据测试");
// 生成workbook 并导出
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, keyList, rowDataList);
File savefile = new File("E:\\temp\\easypoi");
if (!savefile.exists()) {
boolean result = savefile.mkdirs();
System.out.println("目录不存在,创建" + result);
}
FileOutputStream fos = new FileOutputStream("E:\\temp\\easypoi\\坐标.xls");
workbook.write(fos);
fos.close();
}
2.3.通过注解,直接将Object(集合,需要在模型的属性添加@excel注解)数据导出为excel示例(无需模板)
/**
* 对象---直接导出(无需模板) 注:如果模型 的父类的属性也有@Excel注解,那么导出excel时,会连该模型的父类的属性也一会儿导出
*
* @throws IOException
*/
@Test
public void directExportExcelByObject() throws IOException {
List<Student> list = new ArrayList<>(16);
Student student;
Random random = new Random();
for (int i = 0; i < 10; i++) {
student = new Student(i + "", "name" + i, random.nextInt(2), random.nextInt(100), new Date(),
"className" + i);
student.setSchoolName("学校名称" + i);
student.setSchoolAddress("学校地址" + i);
list.add(student);
}
ExportParams exportParams = new ExportParams();
exportParams.setSheetName("我是sheet名字");
// 生成workbook 并导出
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Student.class, list);
File savefile = new File("E:/temp/easypoi");
if (!savefile.exists()) {
boolean result = savefile.mkdirs();
System.out.println("目录不存在,创建" + result);
}
FileOutputStream fos = new FileOutputStream("E:/temp/easypoi/学生.xls");
workbook.write(fos);
fos.close();
}
实战
模型
import cn.afterturn.easypoi.excel.annotation.Excel;
import java.io.Serializable;
public class ReamQuotaMonthBo implements Serializable {
/**
* Id
*
* @mbggenerated
*/
@Excel(name = "ID")
private Integer id;
/**
* 用户id
*
* @mbggenerated
*/
@Excel(name = "用户id")
private Integer userId;
/**
* 用户姓名
*/
@Excel(name = "姓名")
private String userName;
/**
* 年月
*
* @mbggenerated
*/
@Excel(name = "年月")
private String dt;
/**
* 当月总报销额度
*
* @mbggenerated
*/
@Excel(name = "总额度")
private Double totalAmount;
/**
* 当月剩余报销额度
*
* @mbggenerated
*/
@Excel(name = "剩余额度")
private Double leftAmount;
/**
* Id
* @return
*
* @mbggenerated
*/
public Integer getId() {
return id;
}
/**
* Id
* @param id
*
* @mbggenerated
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 用户id
* @return
*
* @mbggenerated
*/
public Integer getUserId() {
return userId;
}
/**
* 用户id
* @param userId
*
* @mbggenerated
*/
public void setUserId(Integer userId) {
this.userId = userId;
}
/**
* 年月
* @return
*
* @mbggenerated
*/
public String getDt() {
return dt;
}
/**
* 年月
* @param dt
*
* @mbggenerated
*/
public void setDt(String dt) {
this.dt = dt == null ? null : dt.trim();
}
/**
* 当月总报销额度
* @return
*
* @mbggenerated
*/
public Double getTotalAmount() {
return totalAmount;
}
/**
* 当月总报销额度
* @param totalAmount
*
* @mbggenerated
*/
public void setTotalAmount(Double totalAmount) {
this.totalAmount = totalAmount;
}
/**
* 当月剩余报销额度
* @return
*
* @mbggenerated
*/
public Double getLeftAmount() {
return leftAmount;
}
/**
* 当月剩余报销额度
* @param leftAmount
*
* @mbggenerated
*/
public void setLeftAmount(Double leftAmount) {
this.leftAmount = leftAmount;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "ReamQuotaMonthBo{" +
"id=" + id +
", userId=" + userId +
", userName='" + userName + '\'' +
", dt='" + dt + '\'' +
", totalAmount=" + totalAmount +
", leftAmount=" + leftAmount +
'}';
}
}
直接导出
@RequestMapping(value="/exportReimQuotaMonthList", method = RequestMethod.GET)
public void exportReimQuotaMonthList(Integer year, String month, HttpServletResponse response) throws Exception {
if(month!=null && !month.equals("")){
month =year+"-"+month;
}
log.info("查询参数分别是:year="+year+"month="+month);
List<ReamQuotaMonthBo> reimQuotaMonthBos = reimQuotaMonthService.selectAllByCon(year,month);
// 设置响应输出的头类型
response.setHeader("content-Type", "application/vnd.ms-excel");
// 设计导出文件的名称,尽量不要中文
String fileName = new String("excel.xls".getBytes(), "ISO-8859-1");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
//输出流。
ServletOutputStream out = response.getOutputStream();
// 创建参数对象(用来设定excel得sheet的内容等信息)
ExportParams params = new ExportParams() ; //sheet
// title的参数为ExportParams类型,目前仅仅在ExportParams中设置了sheetName
params.setSheetName("导出");
Workbook workbook = ExcelExportUtil.exportExcel(params, ReamQuotaMonthBo.class,reimQuotaMonthBos) ;
workbook.write(out);
}
附: 对象转换为Map<String, Object>的工具类
/**
* 对象转换为Map<String, Object>的工具类
*
* @param obj 要转换的对象
* @return
* @throws IllegalAccessException
*/
private static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
Map<String, Object> map = new HashMap<>(16);
Class<?> clazz = obj.getClass();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
map.put(fieldName, value);
}
return map;
}
注意:注:
通过模板导只能以xls为结尾,xlsx为结尾时不能正常打开。
不用模板xls,xlsx都能正常打开,通过ExcelType设置,ExcelType.HSSF:xls ExcelType.XSSF:xlsx。