Java使用EasyExcel生成動(dòng)態(tài)表頭和多Sheet數(shù)據(jù)的Excel實(shí)例
Java使用EasyExcel生成動(dòng)態(tài)表頭和多Sheet數(shù)據(jù)的Excel
由于業(yè)務(wù)需求,Excel的表頭需要固定表頭+動(dòng)態(tài)表頭,不同Sheet使用不同的動(dòng)態(tài)表頭進(jìn)行Excel導(dǎo)出,這里還是使用EasyExcel進(jìn)行數(shù)據(jù)導(dǎo)出,對(duì)關(guān)鍵部分代碼會(huì)進(jìn)行釋義:
1、動(dòng)態(tài)表頭+數(shù)據(jù)Excel
String fileName = "設(shè)備臺(tái)賬" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
//根據(jù)模版id進(jìn)行分組,不同模板下的數(shù)據(jù),導(dǎo)出為不同Sheet的數(shù)據(jù)
Map<Long, DeviceLedgerTemplateEntity> templateMap = deviceTemplateList.stream().collect(Collectors.toMap(DeviceLedgerTemplateEntity::getLedgerTemplateId, v -> v));
int i = 0;
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
for (Map.Entry<Long, List<DeviceLedgerImportVO>> deviceMap : deviceTemplateMap.entrySet()) {
Long templateId = deviceMap.getKey();
List<List<String>> headList = new ArrayList<>();
List<List<String>> dataList = new ArrayList<>();
if (templateMap.containsKey(templateId)) {
DeviceLedgerTemplateEntity templateEntity = templateMap.get(templateId);
List<FormDTO> formList = JSONArray.parseArray(templateEntity.getFormItems(), FormDTO.class);
//動(dòng)態(tài)生成多個(gè)Sheet的表頭
getHeadList(headList, formList);
List<DeviceLedgerImportVO> deviceList = deviceTemplateMap.get(templateId);
//動(dòng)態(tài)填充多個(gè)Sheet的數(shù)據(jù)
getDataList(dataList, deviceList);
//循環(huán)輸出sheet和表頭以及表格內(nèi)容
WriteSheet sheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(headList).build();
excelWriter.write(dataList, sheet);
}
i++;
}
excelWriter.finish();- getHeadList 動(dòng)態(tài)生成表頭
private void getHeadList(List<List<String>> headList, List<FormDTO> formList) {
//生成Excel中表頭
//固定表頭
Field[] fields = DeviceLedgerImportVO.class.getDeclaredFields();
for (Field field : fields) {
boolean bool = field.isAnnotationPresent(ExcelProperty.class);
if (bool) {
String value = Arrays.stream(field.getAnnotation(ExcelProperty.class).value()).findFirst().get();
List<String> filedList = new ArrayList<>();
filedList.add(value);
headList.add(filedList);
}
}
//動(dòng)態(tài)表頭
formList.stream().forEach(form -> {
List<String> filedList = new ArrayList<>();
filedList.add(form.getLabel());
headList.add(filedList);
});
}- getDataList 動(dòng)態(tài)生出數(shù)據(jù)
private void getDataList(List<List<String>> dataList, List<DeviceLedgerImportVO> deviceList) {
//生成Excel中值
deviceList.stream().forEach(device -> {
//固定表頭下的數(shù)據(jù)
List<String> valueList = new ArrayList<>();
valueList.add(device.getDeviceSn());
valueList.add(device.getDeviceName());
valueList.add(device.getDeviceTypeName());
valueList.add(device.getLocation());
valueList.add(device.getStatus());
//動(dòng)態(tài)表頭下的數(shù)據(jù)
List<FormDTO> formList = JSONArray.parseArray(device.getFormItems(), FormDTO.class);
if (CollectionUtil.isNotEmpty(formList)) {
formList.stream().forEach(form -> valueList.add(form.getValue()));
}
dataList.add(valueList);
});
}- Sheet1數(shù)據(jù):

- Shee2數(shù)據(jù):

也可以將Excel導(dǎo)出那部分寫到工具類,懶的抽出來了,也懶得寫Demo了,大概邏輯差不多,需要修改headList和dataList也根據(jù)索引導(dǎo)出每個(gè)Sheet的數(shù)據(jù),在此,提供工具類:
注意:需要修改headList和dataList,不可直接使用上面的headList和dataList方法
public static void writeDynamicBatchExcel(HttpServletResponse response, String fileName, String sheetName, List<List<String>> headList, List<List<Object>> dataList) throws Exception {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
//循環(huán)輸出sheet和表頭以及表格內(nèi)容
for (int i = 0; i < dataList.size(); i++) {
WriteSheet sheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(Collections.singletonList(headList.get(i))).build();
excelWriter.write(dataList.get(i), sheet);
}
excelWriter.finish();
}2、動(dòng)態(tài)表頭Excel
如果只生成動(dòng)態(tài)表頭模版,不需要數(shù)據(jù)的話,getHeadList()不變,僅供參考
public void downloadDeviceLedger(DeviceLedgerSearchDTO param, HttpServletResponse response) throws IOException {
//查詢模版
DeviceLedgerTemplateEntity templateEntity = deviceLedgerTemplateService.queryDeviceLedgerTemplate(param.getLedgerTemplateId());
List<FormDTO> formList = JSONArray.parseArray(templateEntity.getFormItems(), FormDTO.class);
String fileName = "設(shè)備臺(tái)賬" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
List<List<String>> resultList = new ArrayList<>();
getHeadList(resultList, formList);
EasyExcelUtils.writeDynamicExcel(response, fileName, "設(shè)備臺(tái)賬", resultList, Collections.EMPTY_LIST);
}EasyExcelUtils.writeDynamicExcel工具類:
public static void writeDynamicExcel(HttpServletResponse response, String fileName, String sheetName, List<List<String>> headList, List<List<Object>> dataList) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream())
// 設(shè)置動(dòng)態(tài)頭
.head(headList)
.sheet(sheetName)
.doWrite(dataList);
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法
這篇文章主要介紹了Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法,結(jié)合實(shí)例形式分析了java操作csv文件時(shí)使用utf-16le編碼與utf8編碼相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
Java中struts2和spring MVC的區(qū)別_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java中struts2和spring MVC的區(qū)別,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09
Java利用FTPClient實(shí)現(xiàn)文件上傳和下載的實(shí)踐指南
本文介紹如何使用Java中的FTPClient庫來執(zhí)行文件的上傳和下載操作,首先,講解了FTPClient的基本用法,包括連接FTP服務(wù)器和登錄驗(yàn)證,然后,詳細(xì)說明了如何使用 storeFile() 和 retrieveFile() 方法分別實(shí)現(xiàn)文件上傳和下載,需要的朋友可以參考下2025-05-05
詳解SpringBoot中自定義starter的開發(fā)與使用
starter是SpringBoot中非常重要的一個(gè)機(jī)制,他是基于約定優(yōu)于配置的思想所衍生出來的,本文主要介紹了SpringBoot中自定義starter的開發(fā)與使用,感興趣的可以了解下2023-09-09
HttpClient的DnsResolver自定義DNS解析另一種選擇深入研究
這篇文章主要為大家介紹了HttpClient的DnsResolver自定義DNS解析另一種選擇深入研究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
spring-boot-maven-plugin:unknown的完美解決方法
這篇文章主要介紹了spring-boot-maven-plugin:unknown的完美解決方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
springboot讀取自定義配置文件節(jié)點(diǎn)的方法
這篇文章主要介紹了springboot讀取自定義配置文件節(jié)點(diǎn)的方法,本文給大家介紹的非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2018-05-05

