POI 匯出列表 excel ( Java Web通用工具類 )
最近開發一個java Web專案,需要用到POI匯出列表資料,在此記錄一下。
專案使用的是SpringBoot + maven + redis + SpringJdbcTemplate等技術實現,全程使用的是註解的方式,而不是xml配置檔案。
這裡不包含專案搭建,只是記錄一下主要的實現部分。
第一步:向maven的pom.xml檔案中新增以下依賴:
<!-- 匯出列表資料 POI--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.15</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.15</version> </dependency>
第二步:在自己的專案工具包中寫一個匯出列表資料的工具類(ExportExcelKit.java)。
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
/** * 匯出Excel工具包 * 通用類 * 需要Map<String, String> title, Map<String, Integer> position, List<Map<String, Object>> data, * String sheetName, OutputStream outputStream * title: 表格列頭 * position: 表頭列的位置 * data: 資料集合,物件資料需要轉為Map<k, v> * sheetName: 出資料後在excel表格中左下角顯示的工作簿名稱(注意:不是匯出後的檔名) * outputStream: 輸出流,通常在controller層以response.getOutputStream的形式獲取 * 三個Map集合key值保持一致 * @author HongYang * @since 2018/4/26 */ public class ExportExcelKit { // 這是記錄log日誌的,沒有配的話可忽略 public static final Logger log = LogManager.getLogger(ExcelExportException.class); /** * 匯出列表資料 * @param title 表頭集合 * @param position 表頭欄位位置集合 * @param data 需要匯出的資料 * @param sheetName 匯出資料後在excel表格中左下角顯示的工作簿名稱(注意:不是匯出後的檔名) * @param outputStream 從controller層通過response獲取到的輸出流 * @throws IOException * @throws ExcelExportException */ public static void exportDataToExcel(Map<String, String> title, Map<String, Integer> position, List<Map<String, Object>> data, String sheetName, OutputStream outputStream) throws IOException, ExcelExportException { if (data == null || data.size() < 1) { return; } try (Workbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet(sheetName); Row header = sheet.createRow(0); // 設定表頭樣式 CellStyle headerStyle = workbook.createCellStyle(); headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 字型樣式 XSSFFont font = ((XSSFWorkbook) workbook).createFont(); font.setFontName("Arial"); font.setFontHeightInPoints((short)14); headerStyle.setFont(font); int col = 0; // 遍歷表頭map集合 for (String key: title.keySet()) { sheet.setColumnWidth(col, 6000); // 設定表格頭部 Cell headerCell = header.createCell(position.get(key)); headerCell.setCellValue(title.get(key) + ""); headerCell.setCellStyle(headerStyle); col++; } CellStyle style = workbook.createCellStyle(); style.setWrapText(true); /* * 遍歷要匯出列表的資料data 並與title的key相比較, 確認後插入值 * 建立列時,根據title的key然後將值插入到對應的列中(position,dataMap,title三個集合的key值是一一對應的) */ if (data != null && data.size() > 0) { int r = 0; for (Map<String, Object> dataMap : data) { Row row = sheet.createRow(r + 1); for (String dkey : dataMap.keySet()) { for (String key : title.keySet()) { if (key.equals(dkey)) { Cell cell = row.createCell(position.get(key)); cell.setCellValue(dataMap.get(dkey) + ""); cell.setCellStyle(style); break; } } } r++; } } workbook.write(outputStream); } catch (Exception ex) { log.error("export data", ex); throw new ExcelExportException("匯出列表失敗。"); } } }
第三步:依賴匯入了,工具類也寫好了,接下來直接從控制層呼叫匯出資料的方法就OK了。
在這裡我就不連線資料庫了,先隨便寫個實體類User.java
然後在控制層新增假資料模擬匯出。
User.java:
public class User {
private String name;
private Integer age;
private String gender;
private String email;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
實體類好了,接下來我們看一下controller。
/**
* UserController
*/
@RestController
@RequestMapping("user")
public class UserController{
/**
* 匯出User列表資訊 頁面訪問路徑:"/user/export_users"
* @param response
* @param cycle
* @param departmentId
*/
@GetMapping("/export_users")
public void exportWorkSchedules (HttpServletResponse response) throws ParseException, BeanNotFoundException, IOException {
Map<String, String> title = new HashMap<>(); // 表頭
List<Map<String, Object>> data = new ArrayList<>(); // 需要匯出的資料
Map<String, Integer> position = new HashMap<>(); // 表頭欄位對應的位置(自定義位置)
// 模擬從資料庫獲取資料(實則手動新增)
List<User> uList = new ArrayList<>();
User u1 = new User();
u1.setName("張三");
u1.setAge(25);
u1.setGender("男");
u1.setEmail("[email protected]");
u1.setAddress("上海市浦東區");
User u2 = new User();
u2.setName("李四");
u2.setAge(28);
u2.setGender("男");
u2.setEmail("[email protected]");
u2.setAddress("深圳市羅湖區");
User u3 = new User();
u3.setName("貝爾·格里爾斯");
u3.setAge(45);
u3.setGender("男");
u3.setEmail("[email protected]");
u3.setAddress("英國特種兵1部");
User u4 = new User();
u4.setName("埃德");
u4.setAge(50);
u4.setGender("男");
u4.setEmail("[email protected]");
u4.setAddress("英國首府");
uList.add(u1);
uList.add(u2);
uList.add(u3);
uList.add(u4);
// 設定表頭欄位位置
position.put("name", 0);
position.put("age", 1);
position.put("gender", 2);
position.put("email", 3);
position.put("address", 4);
// 設定表頭資訊
title.put("name", "姓名");
title.put("age", "年齡");
title.put("gender", "性別");
title.put("email", "郵箱");
title.put("address", "地址");
Map<String, Object> userMap = null;
// 遍歷模擬的資料填充到userMap集合
for (User user : uList) {
userMap = new HashMap<>();
userMap.put("name", user.getName());
userMap.put("age", user.getAge());
userMap.put("gender", user.getGender());
userMap.put("email", user.getEmail());
userMap.put("address", user.getAddress());
data.add(userMap); // 將userMap新增到List集合中
}
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String date = df.format(new Date());
String excelName = "user列表" + date + ".xlsx";
String sheetName = "使用者列表資料";
excelName = URLEncoder.encode(excelName, "UTF-8");
response.setCharacterEncoding("UTF-8");
response.addHeader("Content-Disposition", "attachment;filename=" + excelName);
response.setContentType("application/x-download");
// 呼叫寫好的工具類的匯出資料方法 傳入對應的引數
ExportExcelKit.exportDataToExcel(title, position, data, sheetName, response.getOutputStream());
}
}
第四步:就是在前端的實現了,前端很簡單,只需要呼叫window.open(url)方法就行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<div>
<button id="export">匯出使用者資料</button>
</div>
</body>
<script>
window.onload = function () {
document.getElementById('export').onclick = function () {
let url = 'xxxxx/user/export_users' // 對應後臺匯出列表方法的路徑
window.open(url)
}
}
</script>
</html>
這就是整個匯出列表資料的方法步驟,希望能幫到你,純手寫,因為本人也是一枚菜鳥,所以請見諒,如果有不對或待優化的地方,希望大神指點,謝謝!!!
如需分享,請帶上地址,謝謝。