Java從零開始實作匯出excel(二)
新人博主,隨筆記錄,主要還是通過自己日常作業積累,系統整理一些技術,希望能夠節省更多人的時間,走出自己的路,
看了自己發的文章,可以幫助一些小伙伴很開心!!
簡述:
上一篇文章主要用我個人覺得,效果很好的方法做excel的匯出,但是那只是符合正常,簡單的excel匯出,可能很多小伙伴,會遇到一些復雜的樣式的excel的匯出,這一篇同樣是用EasyExcel,主要是做一些資料格式復雜的excel,當然這一篇文章不包含復雜表頭的excel匯出
環境搭建:
這一篇的環境和上一篇我們共用一個,因為都是用EasyExcel這個包中的API,所以沒必要換一個工程,還不明白的小伙伴可以去瞟一眼我的上一篇文章Java從零開始實作匯出excel(一)
創建匯出物體:
這里同樣用的是上一篇的物體,不過有點改變,我將性別這一列放開了,

這里有個需要注意的地方,因為EasyExcel是通過物體中@ExcelProperty注解中的index去匹配excel中的列,所以當我們不使用模板時,index一定要是連續且有效的,否則我們生成的excel中會出現空白表頭列的情況
例如:下面這圖是我沒有放開性別那個欄位時匯出的excel表頭

匯出Excel
匯出方法:
/**
* 使用EasyExcel匯出excel
* @param response
* @throws Exception
*/
@GetMapping(value = "/exportExcel")
public void exportExcel(HttpServletResponse response) throws Exception {
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream;charset=utf-8");
LocalDate time = LocalDate.now();
String fileName = URLDecoder.decode("easyExcel匯出_" + time, "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xls" + "\"");
OutputStream out = response.getOutputStream();
List<Student> data = getData();
Map<Integer,String[]> map = new HashMap<>();
map.put(2,new String[]{"男","女"});//下拉匯出
ExcelUtil.exportBySelect(out,data,map);
out.close();
}
//封裝匯出資料
private List<Student> getData() {
List<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student student = new Student();
student.setName("測驗學生姓名-" + i);
student.setAge(i);
student.setSex(i % 2 == 1 ? "男" : "女");
student.setNum(111111L);
student.setAddress("追晨始夢CSDN博客");
list.add(student);
}
return list;
}
工具類:
ExcelUtil
/**
* 功能描述: 匯出資料到Excel
* <p>
* 使用阿里easyPoi 自定義匯出excel攜帶下拉框
*
* @param out 輸出
* @param list 需寫入的資料
* @param mapDropDown 下拉框資料
*/
public static void exportBySelect(OutputStream out, List<? extends BaseRowModel> list, Map<Integer, String[]> mapDropDown) {
EasyExcelFactory.write(out, list.get(0).getClass()).registerWriteHandler(new EasyExcelSheetSelectUtils(mapDropDown)).sheet().doWrite(list);
}
這個公共方法中,我們需要去呼叫registerWriteHandler方法:將我們創建的自定義攔截器放入其中,
這個攔截器是我們這篇文章的重點——直接代碼看
EasyExcelSheetSelectUtils
package com.example.demo;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import java.util.Map;
/**
* 自定義設定excel樣式
*/
public class EasyExcelSheetSelectUtils implements SheetWriteHandler {
//第0列開始 設定某列的下拉內容
private Map<Integer,String[]> mapDropDown;
public EasyExcelSheetSelectUtils(Map<Integer, String[]> mapDropDown) {
this.mapDropDown = mapDropDown;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
/**
* 自定義設定excel樣式
* @param writeWorkbookHolder
* @param writeSheetHolder
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
//獲取sheet頁
Sheet sheet = writeSheetHolder.getSheet();
///開始設定下拉框 //設定下拉框
DataValidationHelper helper = sheet.getDataValidationHelper();
for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
/***起始行、終止行、起始列、終止列**/
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, entry.getKey(), entry.getKey());
/***設定下拉框資料**/
DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
DataValidation dataValidation = helper.createValidation(constraint, addressList);
/***處理Excel兼容性問題**/
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
}
//合并單元格
sheet.addMergedRegion(new CellRangeAddress(1, 2, 0, 0));
}
}
這個里面我寫了兩個常見的案例:
- 下拉框
- 合并單元格
當然了,可能小伙伴們在實際作業中可能有很多不一樣的需求,看完我的兩個案例的實作,相信你所需要的樣式,都可以自己實作,
1. 下拉框
這個功能可能模板匯出時候,會更加方便一點,這里我覺得主要是一個思想
首先我們看實作的程序

我們自定義的攔截器一定要繼承SheetWriteHandler這個介面
這個介面中有兩個虛函式:

我們這里一般會用到下面那個函式 :afterSheetCreate
我們在自定義的攔截器中定義了一個私有屬性mapDropDown,用來裝下拉框的引數,用一個有參構造將我們需要的資料傳進來
key: 表示第幾列需要加入下拉框
value: 表示加入下拉框的值

2.合并單元格
這里我是只做了個案例,將excel表格中的第一列的第一行和第二行進行合并

匯出檔案效果:

這里面,最重要的一步是,我們能獲取到sheet頁
有了這個sheet頁的物件,那其他自定義功能的效果,小伙伴們可以發揮自己的技術,根據自己的需求完成excel匯出!
原始碼鏈接
官方檔案地址
補充
這篇文章寫完,突然想到,其實我們自定義攔截器在模板匯出的方法中也是可以用的,我測驗了一下,只需要改動呼叫方法即可:

效果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/257787.html
標籤:java
上一篇:普歌-碼靈團隊-java中用String類寫用戶登錄案例操作
下一篇:【Java】正則運算式
