前言
在工作經常會遇到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()+"】行");
}
小結
報表在工作中遇到的還算多,總結一下方便以后使用。