前言
在工作经常会遇到excel导出报表的功能,自己也做过一些,然后在项目里看到同事封装的一个excel导出工具类,着实不错,拿来分享一下。然后,又在网上看到一个使用easypoi实现cxcel导出的博客,于是自己也仿着搞了一下,在这也分享一下。
使用POI实现excel导出
- 首先,引入jar包,这是POI需要的jar包。
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
- 下面是主要的实现方法。
定义一个函数式接口,用于自定义格式。
package com.mz.util;
import java.io.IOException;
/**
* @version V1.0
* @Description:
* @date 2018/10/31 17:16
*/
@FunctionalInterface
public interface ExportConsumer<ByteArrayOutputStream, Workbook, List> {
/**
*自定义导出数据拼装
* @param fileOut 输出流
* @param wb workbook对象
* @param listData 数据集
* @throws IOException
*/
void accept(ByteArrayOutputStream fileOut, Workbook wb, List listData) throws IOException;
}
- 工具类主要方法
package com.mz.util;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class POIExportUtil {
/**
* 导出excel
*
* @param fileOut 输出流
* @param wb excel workbook对象
* @param listData 需要导出的数据
* @param consumer 自定义导出excel的格式
* @param fileName 文件名
* @return ResponseEntity
* @throws IOException
*/
public static <T> ResponseEntity<byte[]> exportExcel(ByteArrayOutputStream fileOut,
Workbook wb,
List<T> listData,
String fileName,
ExportConsumer<ByteArrayOutputStream, Workbook, List<T>> consumer) throws IOException {
consumer.accept(fileOut, wb, listData);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", new String((fileName + ".xls").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
return new ResponseEntity<>(fileOut.toByteArray(), headers, HttpStatus.OK);
}
}
- 使用案例,页面通过<a>标签访即可。
//表头字段名
private static final String[] COLUMN_NAMES = {"序号", "单号/流水号", "PNR", "业务类", "发生时间", "付款科目", "总金额",
"预存款期初金额", "预存款发生金额", "预存款期末金额", "授信期初金额", "授信发生金额", "授信期末金额",
"协议欠款期初金额", "协议欠款发生金额", "协议欠款期末金额", "分销商", "操作员"};
/**
* 导出流水报表
* @param request
* @return
*/
@Override
public ResponseEntity exportExcel(TradDetailRequest request) {
ByteArrayOutputStream fileout = new ByteArrayOutputStream();
try {
//数据库的数据
List<B2bTradedetail> tradeDetailForExport = tradedetailMapper.getTradeDetailForExport(request);
//创建workbook对象
Workbook wb = new HSSFWorkbook();
return POIExportUtil.exportExcel(fileout, wb, tradeDetailForExport, "流水记录报表",
(out, workbook, data) -> createCell(wb, data).write(fileout));
} catch (Exception e) {
LOGGER.error("B2bTradedetailServiceImpl.exportExcel:" + e.getMessage());
return new ResponseEntity<>("导出错误!\\n" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
try {
fileout.close();
} catch (IOException e) {
LOGGER.error("B2bTradedetailServiceImpl.exportExcel 输出流关闭错误" + e.getMessage());
}
}
}
/**
* 设置excel标题和数据
* @param wb
* @param data
* @return
*/
private Workbook createCell(Workbook wb, List<B2bTradedetail> data) {
String safeName = WorkbookUtil.createSafeSheetName("sheet1");
Sheet sheet = wb.createSheet(safeName);
//第一行标题
Row title = sheet.createRow(0);
for (int i = 0; i < COLUMN_NAMES.length; i++) {
title.createCell(i).setCellValue(COLUMN_NAMES[i]);
}
//插入数据
data.forEach(b2bTradedetail -> {
Row row = sheet.createRow(data.indexOf(b2bTradedetail) + 1);
row.createCell(0).setCellValue(data.indexOf(b2bTradedetail) + 1);
row.createCell(1).setCellValue(b2bTradedetail.getDealno());
row.createCell(2).setCellValue(b2bTradedetail.getPnrno());
row.createCell(3).setCellValue(b2bTradedetail.getOperatetypeno());
row.createCell(4).setCellValue(b2bTradedetail.getCreatetime());
row.createCell(5).setCellValue(b2bTradedetail.getPaytypeno());
row.createCell(6).setCellValue(b2bTradedetail.getTotalmoney());
row.createCell(7).setCellValue(b2bTradedetail.getAccountbefore());
row.createCell(8).setCellValue(b2bTradedetail.getAccountmoney());
row.createCell(9).setCellValue(b2bTradedetail.getAccountafter());
row.createCell(10).setCellValue(b2bTradedetail.getCreditbefore());
row.createCell(11).setCellValue(b2bTradedetail.getCreditmoney());
row.createCell(12).setCellValue(b2bTradedetail.getCreditafter());
row.createCell(13).setCellValue(b2bTradedetail.getProtocoldebtbefore());
row.createCell(14).setCellValue(b2bTradedetail.getProtocoldebtmoney());
row.createCell(15).setCellValue(b2bTradedetail.getProtocoldebtafter());
row.createCell(16).setCellValue(b2bTradedetail.getCompid());
row.createCell(17).setCellValue(b2bTradedetail.getOperatorid());
});
return wb;
}
使用easypoi实现,这里直接是一个工具类和使用案例,关于这个教程可以参考easypoi教程
- 先导入jar包
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
- 一个实体类,报表的主要数据。
package com.mz.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import java.io.Serializable;
import java.util.Date;
/**
* @version V1.0
* @Description:
* @date 2018/10/31 15:31
*/
public class StudentEntity implements Serializable {
/**
* id
*/
private String id;
/**
* 学生姓名
*/
@Excel(name = "姓名", isImportField = "true_st")
private String name;
/**
* 学生性别
*/
@Excel(name = "性别", replace = { "男_1", "女_2" }, isImportField = "true_st")
private int sex;
@Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd", isImportField = "true_st")
private Date birthday;
@Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd")
private Date registrationDate;
public StudentEntity(String id, String name, int sex, Date birthday, Date registrationDate) {
this.id = id;
this.name = name;
this.sex = sex;
this.birthday = birthday;
this.registrationDate = registrationDate;
}
//省略setter getter方法
- 工具类方法,包含两个excel的方法,没有测试过。
package com.mz.util;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* @version V1.0
* @Description: Excel导出工具类
* @date 2018/10/31 19:16
*/
public class ExportExcelUtil {
/**
*
* @param list 数据集合
* @param title 内容标题
* @param sheetName excel名称
* @param pojoClass 实体类
* @param fileName 导出的文件名
* @param isCreateHeader 是否创建excel表头
* @param response 响应
*/
public static void exportExcel(List<?> list,
String title,
String sheetName,
Class<?> pojoClass,
String fileName,
boolean isCreateHeader,
HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 导出
* @param list 数据集合
* @param title 内容标题
* @param sheetName excel名称
* @param pojoClass 实体类
* @param fileName 导出的文件名
* @param response 响应
*/
public static void exportExcel(List<?> list,
String title,
String sheetName,
Class<?> pojoClass,
String fileName,
HttpServletResponse response){
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
/**
* 导出 无内容标题和excel表名
* @param list
* @param pojoClass
* @param fileName
* @param response
*/
public static void exportExcel(List<?> list,
Class<?> pojoClass,
String fileName,
HttpServletResponse response) {
defaultExport(list, pojoClass, fileName, response, new ExportParams());
}
/**
* 导出
* @param list 数据集合
* @param fileName 导出的文件名
* @param response 响应
*/
public static void exportExcel(List<Map<String, Object>> list,
String fileName,
HttpServletResponse response){
defaultExport(list, fileName, response);
}
/**
*
* @param list 数据集合
* @param pojoClass 实体类
* @param fileName 导出的文件名
* @param response 响应
* @param exportParams
*/
private static void defaultExport(List<?> list,
Class<?> pojoClass,
String fileName,
HttpServletResponse response,
ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams,pojoClass,list);
if (workbook != null) {
doExport(fileName, response, workbook);
}
}
/**
*
* @param list 数据集合
* @param fileName 导出的文件名
* @param response 响应
*/
private static void defaultExport(List<Map<String, Object>> list,
String fileName,
HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null){
doExport(fileName, response, workbook);
}
}
/**
* 导出
* @param fileName 导出的文件名
* @param response 响应
* @param workbook 工作表
*/
private static void doExport(String fileName,
HttpServletResponse response,
Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls");
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new NormalException(e.getMessage());
}
}
/**
*
* @param filePath
* @param titleRows
* @param headerRows
* @param pojoClass
* @param <T>
* @return
*/
public static <T> List<T> importExcel(String filePath,
Integer titleRows,
Integer headerRows,
Class<T> pojoClass) {
if (StringUtils.isBlank(filePath)){
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
}catch (NoSuchElementException e){
throw new NormalException("模板不能为空");
} catch (Exception e) {
e.printStackTrace();
throw new NormalException(e.getMessage());
}
return list;
}
/**
*
* @param file
* @param titleRows
* @param headerRows
* @param pojoClass
* @param <T>
* @return
*/
public static <T> List<T> importExcel(MultipartFile file,
Integer titleRows,
Integer headerRows,
Class<T> pojoClass){
if (file == null){
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
}catch (NoSuchElementException e){
throw new NormalException("excel文件不能为空");
} catch (Exception e) {
throw new NormalException(e.getMessage());
}
return list;
}
}
- 使用案例,可以写一个Controller直接通过浏览器访问。
@RequestMapping(value = "/")
public void getname(HttpServletResponse response) {
List<StudentEntity> list = new ArrayList<>();
StudentEntity studentEntity = new StudentEntity("a","路飞",1,new Date(),new Date());
StudentEntity studentEntity1 = new StudentEntity("a","路飞",1,new Date(),new Date());
StudentEntity studentEntity2 = new StudentEntity("a","路飞",1,new Date(),new Date());
StudentEntity studentEntity3 = new StudentEntity("a","路飞",1,new Date(),new Date());
StudentEntity studentEntity4 = new StudentEntity("a","路飞",1,new Date(),new Date());
list.add(studentEntity);
list.add(studentEntity1);
list.add(studentEntity2);
list.add(studentEntity3);
list.add(studentEntity4);
ExportExcelUtil.exportExcel(list, StudentEntity.class, "学生报表", response);
// response.setHeader("content-Type", "application/vnd.ms-excel");
// response.setHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis() + ".xls");
// response.setCharacterEncoding("UTF-8");
// Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("","学生"),
// StudentEntity.class, list);
// ExportExcelUtil.exportExcel(list,"学生信息", "学生",StudentEntity.class,
// "学生报表", true, response);
// if (workbook != null) {
// try {
// workbook.write(response.getOutputStream());
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//return "Hello Spring Boot";
}
*导入报表使用
<form id="loginForm" method="post" action="/import" enctype="multipart/form-data">
<ul>
<li>
<span>上 传:</span>
<span class="input">
<input type="file" id="file" name="file"/>
</span>
<input type="submit" placeholder="提交">
</li>
</ul>
</form>
@RequestMapping(value = "/import", method = RequestMethod.POST)
public void importExcel(@RequestParam("file") MultipartFile file) {
System.out.println("进来了");
System.out.println("名字:" + file.getName());
List<StudentEntity> personList = ExportExcelUtil.importExcel(file, 0,1, StudentEntity.class);
System.out.println(personList.size());
personList.forEach(stu -> {
System.out.println(stu.getName() + " " + stu.getRegistrationDate() + " " + stu.getSex());
});
System.out.println("导入数据一共【"+personList.size()+"】行");
}
小结
报表在工作中遇到的还算多,总结一下方便以后使用。