清华主页 - 清华新闻 - 综合时讯 - 正文

Java根据excel模版导出Excel(easyexcel、poi)——含项目测试例子拿来即用

Java根据excel模版导出Excel(easyexcel、poi)——含项目测试例子拿来即用

  • 1. 前言
    • 1.1 关于Excel的一般导出
    • 2.2 关于easyexcel的根据模版导出
  • 2. 先看效果
    • 2.1 模版
    • 2.2 效果
  • 3. 代码实现(核心代码)
    • 3.1 项目代码结构
    • 3.2 静态填充例子代码
    • 3.3 动态list填充代码
    • 3.4 附核心代码
      • 3.4.1 object转map工具类
      • 3.4.2 根据模版导出Excel程序代码
      • 3.4.3 导出工具类入口代码
  • 4. 附项目
    • 4.1 一般导出项目代码
    • 4.2 根据模版导出项目代码
  • 5. 关于 DynamicDataMapping 代码

1. 前言

1.1 关于Excel的一般导出

  • 一般列表导出以及个性化样式设置请看下面的文章:
    • JAVA导出Excel通用工具类——第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选、动态合并横向(纵向)单元格等多种复杂情况.
    • JAVA导出Excel通用工具——第二篇:使用EasyExcel导出excel的多种情况的例子介绍.

2.2 关于easyexcel的根据模版导出

  • 如果使用easy Excel的话,下面就不用看了,这个官网关于怎么使用以及例子提供的非常详细,git上还能下载源码,官网如下,使用不再介绍,具体看官网即可:
    Easy Excel 之 填充excel.

2. 先看效果

2.1 模版

  • 静态填充简单模版如下:
    在这里插入图片描述
  • 动态填充简单模版:
    • 单个list:
      在这里插入图片描述
    • 多个list:
      在这里插入图片描述
    • 单个list单条数据:
      在这里插入图片描述

2.2 效果

  • 静态填充效果如下:
    在这里插入图片描述
  • 动态填充效果如下:
    • 单个list:
      在这里插入图片描述
    • 多个list:
      在这里插入图片描述
    • 单个list单条数据:
      在这里插入图片描述

3. 代码实现(核心代码)

3.1 项目代码结构

  • 如下:
    在这里插入图片描述

3.2 静态填充例子代码

  • 工具类代码已封装,所以调用很简单即可实现,如下:
    在这里插入图片描述

3.3 动态list填充代码

  • 单个list:
    在这里插入图片描述
  • 多个list
    在这里插入图片描述
  • 单个list单条数据:
    在这里插入图片描述

3.4 附核心代码

3.4.1 object转map工具类

  • MapObjectUtil.java如下:
    packagecom.liu.susu.excel.template.poi.common;importcom.alibaba.fastjson.JSONObject;importcom.liu.susu.excel.template.poi.example.data.DogEntity2;importorg.apache.commons.beanutils.BeanMap;importjava.lang.reflect.Field;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/** * @Description * @Author susu * @Date 2024/2/19 */publicclassMapObjectUtil{ /**    * @description: 将object的list数据 转换成 map的list(如:List>)    * @param objDataList    * @return java.util.List>    * @author susu    */publicstaticList<Map<String,Object>>objListToMapList(List<?>objDataList){ List<Map<String,Object>>dataList =newArrayList<>();if(objDataList==null||objDataList.size()<1){ returnnull;}objDataList.forEach(obj->{ try{ Map<String,Object>map =MapObjectUtil.objectToMap(obj);dataList.add(map);}catch(IllegalAccessExceptione){ thrownewRuntimeException(e);}});returndataList;}/**    * @description: 将object数据转换成map数据    * @param obj    * @return java.util.Map    * @author susu    */publicstaticMap<String,Object>objectToMap(Objectobj)throwsIllegalAccessException{ Map<String,Object>map =newHashMap();Class<?>cla =obj.getClass();Field[]fields =cla.getDeclaredFields();for(Fieldfield :fields){ field.setAccessible(true);StringkeyName =field.getName();Objectvalue =field.get(obj);if(value ==null)value ="";map.put(keyName,value);}returnmap;}/**    * @description: 使用 JSONObject 将object转换成map    * @param obj    * @return java.util.Map    * @author susu    */publicstaticMap<?,?>objectToMap2(Objectobj){ if(obj ==null)returnnull;returnJSONObject.parseObject(JSONObject.toJSONString(obj),Map.class);}/**    * @description: 使用BeanMap将object转换成map    * @param obj    * @return java.util.Map    * @author susu    */publicstaticMap<?,?>objectToMap3(Objectobj){ if(obj ==null)returnnull;returnnewBeanMap(obj);}publicstaticvoidmain(String[]args){ DogEntity2dog =newDogEntity2();dog.setDogId("A-1001");dog.setDogAge(3);dog.setDogName("aaa");//        Map map = JSONObject.parseObject(JSONObject.toJSONString(dog),Map.class);Mapmap =objectToMap2(dog);System.out.println(map);}}

3.4.2 根据模版导出Excel程序代码

  • ExcelTemplateProc.java如下:
    packagecom.liu.susu.excel.template.poi.common;importorg.apache.commons.lang3.StringUtils;importorg.apache.poi.ss.usermodel.CellCopyPolicy;importorg.apache.poi.ss.usermodel.Workbook;importorg.apache.poi.xssf.usermodel.XSSFCell;importorg.apache.poi.xssf.usermodel.XSSFRow;importorg.apache.poi.xssf.usermodel.XSSFSheet;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importorg.springframework.util.ResourceUtils;importjava.io.*;importjava.util.List;importjava.util.Map;/** * @Description 根据模版导出Excel程序 * @Author susu * @Date 2024/2/19 */publicclassExcelTemplateProc{ /**     * @param templateFileName     * @param exportFilePathAndName     * @param staticDataMap     * @param dynamicDataMappingList     * @return void     * @description: 根据模版导出Excel入口     * @author susu     * @date 2024/2/20     */publicstaticvoiddoExportExcelByTemplateProc(StringtemplateFileName,StringexportFilePathAndName,Map<String,Object>staticDataMap,List<DynamicDataMapping>dynamicDataMappingList)throwsIOException{ /**         * 1. 从resources下加载模板并替换         *    使用 ResourceUtils 加载文件         */Filefile =ResourceUtils.getFile("classpath:"+templateFileName);InputStreaminputStream =newFileInputStream(file);Workbookworkbook =dealFirstSheetByTemplate(inputStream,staticDataMap,dynamicDataMappingList);// 2. 保存到本地saveExportFile(workbook,exportFilePathAndName);}/**     * @param workbook     * @param excelFilePath     * @return void     * @description: 保存导出的Excel文件到服务器     * @author susu     * @date 2024/2/20     */publicstaticvoidsaveExportFile(Workbookworkbook,StringexcelFilePath)throwsIOException{ FileOutputStreamoutputStream =newFileOutputStream(excelFilePath);executeWorkBookWrite(workbook,outputStream);}/**     * @param workbook     * @param outputStream     * @return void     * @description: 数据输出     * @author susu     * @date 2024/2/20     */publicstaticvoidexecuteWorkBookWrite(Workbookworkbook,OutputStreamoutputStream)throwsIOException{ workbook.write(outputStream);outputStream.flush();outputStream.close();workbook.close();}/**     * @param inputStream     * @param staticDataMap     * @param dynamicDataMappingList     * @return org.apache.poi.ss.usermodel.Workbook     * @description: 处理只有一个sheet页的模版     * @author susu     * @date 2024/2/20     */publicstaticWorkbookdealFirstSheetByTemplate(InputStreaminputStream,Map<String,Object>staticDataMap,List<DynamicDataMapping>dynamicDataMappingList)throwsIOException{ XSSFWorkbookworkbook =newXSSFWorkbook(inputStream);XSSFSheetsheet =workbook.getSheetAt(0);// 按模板处理sheet页dealSheetDataByTemplate(sheet,staticDataMap,dynamicDataMappingList);returnworkbook;}/**     * @param sheet     * @param staticDataMap     * @param dynamicDataMappingList     * @return void     * @description: 按模板处理sheet页里的数据     * @author susu     * @date 2024/2/19     */privatestaticvoiddealSheetDataByTemplate(XSSFSheetsheet,Map<String,Object>staticDataMap,List<DynamicDataMapping>dynamicDataMappingList){ // 循环sheet里每一行for(inti =sheet.getFirstRowNum();i <=sheet.getLastRowNum();i++){ XSSFRowrow =sheet.getRow(i);DynamicDataMappingdynamicDataMapping =getDynamicRowDataByMatch(row,dynamicDataMappingList);if(dynamicDataMapping !=null){ i =getTemplateLastRowIndexAfterDealTemplate(sheet,i,dynamicDataMapping);}else{ dealTemplateDataRow(row,null,staticDataMap);}}}/**     * @param row     * @param dataMap     * @param dataPrefix     * @return void     * @description: 循环处理模版中每行的数据     * @author susu     * @date 2024/2/20     */privatestaticvoiddealTemplateDataRow(XSSFRowrow,StringdataPrefix,Map<String,Object>dataMap){ if(dataMap ==null){ return;}for(inti =row.getFirstCellNum();i <row.getLastCellNum();i++){ XSSFCellcell =row.getCell(i);fillInTemplateCellDataValue(cell,dataPrefix,dataMap);}}/**     * @param cell     * @param dataPrefix     * @param dataMap     * @return void     * @description: 填充模版里单元格的值     * @author susu     * @date 2024/2/20     */privatestaticvoidfillInTemplateCellDataValue(XSSFCellcell,StringdataPrefix,Map<String,Object>dataMap){ if(cell ==null){ return;}StringcellValue =cell.getStringCellValue();//获取模版里设置的数据if(StringUtils.isEmpty(cellValue)){ return;}booleanflag =false;dataPrefix =StringUtils.isEmpty(dataPrefix)?"":(dataPrefix +".");for(Map.Entry<String,Object>entry :dataMap.entrySet()){ // 循环所有,因为可能一行有多个占位符StringcellTemplateStr ="{ { "+dataPrefix +entry.getKey()+"}}";if(cellValue.contains(cellTemplateStr)){ // 替换模版中单元格的数据cellValue =cellValue.replace(cellTemplateStr,entry.getValue()==null?"":entry.getValue().toString());flag =true;}}if(flag){ cell.setCellValue(cellValue);}}/**     * @param row     * @param dynamicDataMappingList     * @return com.liu.susu.excel.template.poi.common.DynamicDataMapping     * @description: 通过模版sheet中的行数据 与 动态数据匹配,获取此行需要填充的动态数据     * @author susu     * @date 2024/2/21     */privatestaticDynamicDataMappinggetDynamicRowDataByMatch(XSSFRowrow,List<DynamicDataMapping>dynamicDataMappingList){ if(dynamicDataMappingList ==null||dynamicDataMappingList.size()<1){ returnnull;}for(intj =row.getFirstCellNum();j <row.getLastCellNum();j++){ XSSFCellcell =row.getCell(j);Stringvalue =cell.getStringCellValue();if(value !=null){ for(DynamicDataMappingdynamicData :dynamicDataMappingList){ if(value.startsWith("{ { "+dynamicData.getDataId()+".")){ returndynamicData;}}}}returnnull;}/**     * @param sheet     * @param rowIndex     * @param dynamicDataMapping     * @return int     * @description: 根据动态数据的条数动态复制模版行,每处理一个类型的list返回最后的行数,进而处理下一个类型的list     * @author susu     * @date 2024/2/20     */privatestaticintgetTemplateLastRowIndexAfterDealTemplate(XSSFSheetsheet,introwIndex,DynamicDataMappingdynamicDataMapping){ if(dynamicDataMapping ==null){ returnrowIndex;}intdataRows =dynamicDataMapping.getDataList().size();// 需要拷贝的行数(因为模板行本身占1行,所以-1)intcopyRows =dataRows -1;if(copyRows >0){ /**             * shiftRows: 从动态数据模版行(rowIndex)到最后一行,这些全部行都向下移copyRows行             *            相当于模版行上面插入n行空行(n=copyRows)             */sheet.shiftRows(rowIndex,sheet.getLastRowNum(),copyRows,true,false);// 拷贝策略CellCopyPolicycellCopyPolicy =makeCellCopyPolicy();// 因为从模版行开始向下平移了copyRows行,所以这里 模板行=rowIndex + copyRows,inttemplateDataRow =rowIndex +copyRows;// 因为模版行上新增了空行,所以要把模板所在行的模版 拷贝到上面新增的空行for(inti =0;i <copyRows;i++){ //templateDataRow-模版行数据   rowIndex + i循环的当前空行sheet.copyRows(templateDataRow,templateDataRow,rowIndex +i,cellCopyPolicy);}}// 循环模版行:动态替换模版行(将模版行里的模版替换成动态数据)for(intj =rowIndex;j <rowIndex +dataRows;j++){ Map<String,Object>dataMap =dynamicDataMapping.getDataList().get(j -rowIndex);dealTemplateDataRow(sheet.getRow(j),dynamicDataMapping.getDataId(),dataMap);}returnrowIndex +copyRows;}/**     * @param     * @return org.apache.poi.ss.usermodel.CellCopyPolicy     * @description: 拷贝策略     * @author susu     * @date 2024/2/20     */publicstaticCellCopyPolicymakeCellCopyPolicy(){ CellCopyPolicycellCopyPolicy =newCellCopyPolicy();cellCopyPolicy.setCopyCellValue(true);cellCopyPolicy.setCopyCellStyle(true);returncellCopyPolicy;}}

3.4.3 导出工具类入口代码

  • ExportExcelByTemplateUtils.java如下:
    packagecom.liu.susu.excel.template.poi.common;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/** * @Description 根据模版导出Excel工具类 * @Author susu * @Date 2024/2/19 */publicclassExportExcelByTemplateUtils{ /**    * @description: 根据模版导出Excel入口(单个list数据)    * @param templateFileName    * @param exportFilePathAndName    * @param staticDataMap    * @param dataId    * @param originDataList    * @return void    * @author susu    * @date 2024/2/21    */publicstaticvoiddoExportExcelOneListByTemplate(StringtemplateFileName,StringexportFilePathAndName,Map<String,Object>staticDataMap,StringdataId,List<?>originDataList)throwsException{ List<Map<String,Object>>exportDataList =MapObjectUtil.objListToMapList(originDataList);// 只有一个list数据List<DynamicDataMapping>dynamicDataMappingList =DynamicDataMapping.createOneDataList(dataId,exportDataList);// 导出ExcelTemplateProc.doExportExcelByTemplateProc(templateFileName,exportFilePathAndName,staticDataMap,dynamicDataMappingList);}/**    * @description: 根据模版导出Excel入口(多个list数据)    * @param templateFileName    * @param exportFilePathAndName    * @param staticSource    * @param originDataMapList    * @return void    * @author susu    * @date 2024/2/20    */publicstaticvoiddoExportExcelMoreListByTemplate(StringtemplateFileName,StringexportFilePathAndName,Map<String,Object>staticSource,Map<String,List<?>>originDataMapList)throwsException{ Map<String,List<Map<String,Object>>>transMap =newHashMap<>();originDataMapList.forEach((dataId,originDataList)->{ List<Map<String,Object>>transDataList =MapObjectUtil.objListToMapList(originDataList);transMap.put(dataId,transDataList);});// 多个list类型数据List<DynamicDataMapping>dynamicDataMappingList =DynamicDataMapping.createMorDataList(transMap);// 导出ExcelTemplateProc.doExportExcelByTemplateProc(templateFileName,exportFilePathAndName,staticSource,dynamicDataMappingList);}}

4. 附项目

4.1 一般导出项目代码

  • 如下:
    Java导出excel工具详细介绍(POI 和 EasyExcel),各种复杂需求情况的导出(包括动态设置合并单元格等).

4.2 根据模版导出项目代码

  • 如下:
    Java根据自定义模版导出各种需求的Excel(使用POI).

5. 关于 DynamicDataMapping 代码

  • 如下:
    packagecom.liu.susu.excel.template.poi.common;importlombok.Data;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importjava.util.Map;/** * @Description 存放需要导出的动态数据 * @Author susu * @Date 2024/2/19 */@DatapublicclassDynamicDataMapping{ privateStringdataId;privateList<Map<String,Object>>dataList;/**    * @description: 组装只有一个list类型的动态数据    * @param dataId    * @param dataList    * @return java.util.List    * @author susu    * @date 2024/2/20    */publicstaticList<DynamicDataMapping>createOneDataList(StringdataId,List<Map<String,Object>>dataList){ if(dataList ==null)returnnull;returnCollections.singletonList(getDynamicDataMapping(dataId,dataList));}/**    * @description: 组装只有多个list类型的动态数据    * @param transMap    * @return java.util.List    * @author susu    * @date 2024/2/20    */publicstaticList<DynamicDataMapping>createMorDataList(Map<String,List<Map<String,Object>>>transMap){ if(transMap ==null)returnnull;List<DynamicDataMapping>list =newArrayList<>();transMap.forEach((dataId,dataList)->{ list.add(getDynamicDataMapping(dataId,dataList));});returnlist;}publicstaticDynamicDataMappinggetDynamicDataMapping(StringdataId,List<Map<String,Object>>dataList){ DynamicDataMappingdynamicData =newDynamicDataMapping();dynamicData.dataId =dataId;dynamicData.dataList =dataList;returndynamicData;}}

2025-06-24 12:33:45

相关新闻

清华大学新闻中心版权所有,清华大学新闻网编辑部维护,电子信箱: news@tsinghua.edu.cn
Copyright 2001-2020 news.tsinghua.edu.cn. All rights reserved.