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 根据模版导出项目代码

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 如下:
    package com.liu.susu.excel.template.poi.common;import com.alibaba.fastjson.JSONObject;
    import com.liu.susu.excel.template.poi.example.data.DogEntity2;
    import org.apache.commons.beanutils.BeanMap;import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;/*** @Description* @Author susu* @Date 2024/2/19*/
    public class MapObjectUtil {/*** @description: 将object的list数据 转换成 map的list(如:List<Map<String, Object>>)* @param objDataList* @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>* @author susu*/public static List<Map<String, Object>> objListToMapList(List<?> objDataList){List<Map<String, Object>> dataList = new ArrayList<>();if (objDataList==null || objDataList.size()<1){return null;}objDataList.forEach(obj->{try {Map<String, Object> map = MapObjectUtil.objectToMap(obj);dataList.add(map);} catch (IllegalAccessException e) {throw new RuntimeException(e);}});return dataList;}/*** @description: 将object数据转换成map数据* @param obj* @return java.util.Map<java.lang.String,java.lang.Object>* @author susu*/public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {Map<String, Object> map = new HashMap();Class<?> cla = obj.getClass();Field[] fields = cla.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String keyName = field.getName();Object value = field.get(obj);if (value == null)value = "";map.put(keyName, value);}return map;}/*** @description: 使用 JSONObject 将object转换成map* @param obj* @return java.util.Map<?,?>* @author susu*/public static Map<?, ?> objectToMap2(Object obj) {if (obj == null)return null;return JSONObject.parseObject(JSONObject.toJSONString(obj),Map.class);}/*** @description: 使用BeanMap将object转换成map* @param obj* @return java.util.Map<?,?>* @author susu*/public static Map<?, ?> objectToMap3(Object obj) {if (obj == null)return null;return new BeanMap(obj);}public static void main(String[] args) {DogEntity2 dog = new DogEntity2();dog.setDogId("A-1001");dog.setDogAge(3);dog.setDogName("aaa");
    //        Map map = JSONObject.parseObject(JSONObject.toJSONString(dog),Map.class);Map map = objectToMap2(dog);System.out.println(map);}}
    

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

  • ExcelTemplateProc.java 如下:
    package com.liu.susu.excel.template.poi.common;import org.apache.commons.lang3.StringUtils;
    import org.apache.poi.ss.usermodel.CellCopyPolicy;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.xssf.usermodel.XSSFCell;
    import org.apache.poi.xssf.usermodel.XSSFRow;
    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.springframework.util.ResourceUtils;import java.io.*;
    import java.util.List;
    import java.util.Map;/*** @Description 根据模版导出Excel程序* @Author susu* @Date 2024/2/19*/
    public class ExcelTemplateProc {/*** @param templateFileName* @param exportFilePathAndName* @param staticDataMap* @param dynamicDataMappingList* @return void* @description: 根据模版导出Excel入口* @author susu* @date 2024/2/20*/public static void doExportExcelByTemplateProc(String templateFileName, String exportFilePathAndName,Map<String, Object> staticDataMap,List<DynamicDataMapping> dynamicDataMappingList) throws IOException {/*** 1. 从resources下加载模板并替换*    使用 ResourceUtils 加载文件*/File file = ResourceUtils.getFile("classpath:"+templateFileName);InputStream inputStream = new FileInputStream(file);Workbook workbook = dealFirstSheetByTemplate(inputStream, staticDataMap, dynamicDataMappingList);// 2. 保存到本地saveExportFile(workbook, exportFilePathAndName);}/*** @param workbook* @param excelFilePath* @return void* @description: 保存导出的Excel文件到服务器* @author susu* @date 2024/2/20*/public static void saveExportFile(Workbook workbook, String excelFilePath) throws IOException {FileOutputStream outputStream = new FileOutputStream(excelFilePath);executeWorkBookWrite(workbook, outputStream);}/*** @param workbook* @param outputStream* @return void* @description: 数据输出* @author susu* @date 2024/2/20*/public static void executeWorkBookWrite(Workbook workbook, OutputStream outputStream) throws IOException {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*/public static Workbook dealFirstSheetByTemplate(InputStream inputStream,Map<String, Object> staticDataMap,List<DynamicDataMapping> dynamicDataMappingList) throws IOException {XSSFWorkbook workbook = new XSSFWorkbook(inputStream);XSSFSheet sheet = workbook.getSheetAt(0);// 按模板处理sheet页dealSheetDataByTemplate(sheet, staticDataMap, dynamicDataMappingList);return workbook;}/*** @param sheet* @param staticDataMap* @param dynamicDataMappingList* @return void* @description: 按模板处理sheet页里的数据* @author susu* @date 2024/2/19*/private static void dealSheetDataByTemplate(XSSFSheet sheet, Map<String, Object> staticDataMap, List<DynamicDataMapping> dynamicDataMappingList) {// 循环sheet里每一行for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {XSSFRow row = sheet.getRow(i);DynamicDataMapping dynamicDataMapping = 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*/private static void dealTemplateDataRow(XSSFRow row, String dataPrefix, Map<String, Object> dataMap) {if (dataMap == null) {return;}for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {XSSFCell cell = row.getCell(i);fillInTemplateCellDataValue(cell, dataPrefix, dataMap);}}/*** @param cell* @param dataPrefix* @param dataMap* @return void* @description: 填充模版里单元格的值* @author susu* @date 2024/2/20*/private static void fillInTemplateCellDataValue(XSSFCell cell, String dataPrefix, Map<String, Object> dataMap) {if (cell == null) {return;}String cellValue = cell.getStringCellValue();//获取模版里设置的数据if (StringUtils.isEmpty(cellValue)) {return;}boolean flag = false;dataPrefix = StringUtils.isEmpty(dataPrefix) ? "" : (dataPrefix + ".");for (Map.Entry<String, Object> entry : dataMap.entrySet()) {// 循环所有,因为可能一行有多个占位符String cellTemplateStr = "{{" + 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*/private static DynamicDataMapping getDynamicRowDataByMatch(XSSFRow row, List<DynamicDataMapping> dynamicDataMappingList) {if (dynamicDataMappingList == null || dynamicDataMappingList.size() < 1) {return null;}for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {XSSFCell cell = row.getCell(j);String value = cell.getStringCellValue();if (value != null) {for (DynamicDataMapping dynamicData : dynamicDataMappingList) {if (value.startsWith("{{" + dynamicData.getDataId() + ".")) {return dynamicData;}}}}return null;}/*** @param sheet* @param rowIndex* @param dynamicDataMapping* @return int* @description: 根据动态数据的条数动态复制模版行,每处理一个类型的list返回最后的行数,进而处理下一个类型的list* @author susu* @date 2024/2/20*/private static int getTemplateLastRowIndexAfterDealTemplate(XSSFSheet sheet, int rowIndex, DynamicDataMapping dynamicDataMapping) {if (dynamicDataMapping == null) {return rowIndex;}int dataRows = dynamicDataMapping.getDataList().size();// 需要拷贝的行数(因为模板行本身占1行,所以-1)int copyRows = dataRows - 1;if (copyRows > 0) {/*** shiftRows: 从动态数据模版行(rowIndex)到最后一行,这些全部行都向下移copyRows行*            相当于模版行上面插入n行空行(n=copyRows)*/sheet.shiftRows(rowIndex, sheet.getLastRowNum(), copyRows, true, false);// 拷贝策略CellCopyPolicy cellCopyPolicy = makeCellCopyPolicy();// 因为从模版行开始向下平移了copyRows行,所以这里 模板行=rowIndex + copyRows,int templateDataRow = rowIndex + copyRows;// 因为模版行上新增了空行,所以要把模板所在行的模版 拷贝到上面新增的空行for (int i = 0; i < copyRows; i++) {//templateDataRow-模版行数据   rowIndex + i循环的当前空行sheet.copyRows(templateDataRow, templateDataRow, rowIndex + i, cellCopyPolicy);}}// 循环模版行:动态替换模版行(将模版行里的模版替换成动态数据)for (int j = rowIndex; j < rowIndex + dataRows; j++) {Map<String, Object> dataMap = dynamicDataMapping.getDataList().get(j - rowIndex);dealTemplateDataRow(sheet.getRow(j), dynamicDataMapping.getDataId(), dataMap);}return rowIndex + copyRows;}/*** @param* @return org.apache.poi.ss.usermodel.CellCopyPolicy* @description: 拷贝策略* @author susu* @date 2024/2/20*/public static CellCopyPolicy makeCellCopyPolicy() {CellCopyPolicy cellCopyPolicy = new CellCopyPolicy();cellCopyPolicy.setCopyCellValue(true);cellCopyPolicy.setCopyCellStyle(true);return cellCopyPolicy;}}

3.4.3 导出工具类入口代码

  • ExportExcelByTemplateUtils.java 如下:
    package com.liu.susu.excel.template.poi.common;import java.util.HashMap;
    import java.util.List;
    import java.util.Map;/*** @Description 根据模版导出Excel工具类* @Author susu* @Date 2024/2/19*/
    public class ExportExcelByTemplateUtils {/*** @description: 根据模版导出Excel入口(单个list数据)* @param templateFileName* @param exportFilePathAndName* @param staticDataMap* @param dataId* @param originDataList* @return void* @author susu* @date 2024/2/21*/public static void doExportExcelOneListByTemplate(String templateFileName, String exportFilePathAndName,Map<String, Object> staticDataMap,String dataId,List<?> originDataList) throws Exception{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*/public static void doExportExcelMoreListByTemplate(String templateFileName,String exportFilePathAndName,Map<String, Object> staticSource,Map<String, List<?>> originDataMapList) throws Exception{Map<String,List<Map<String, Object>>> transMap = new HashMap<>();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).

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2811997.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

数字电路 第四章—第一节(触发器——概述)

一、对触发器的基本要求 1、触发器的概念 在数字电路中&#xff0c;基本的工作信号是二进制数字信号和两状态逻辑信号&#xff0c;而触发器就是存放这些信号的单元电路。 2、对触发器的基本要求 &#xff08;1&#xff09;具有两个稳定状态——0状态和1状态&#xff0c;以正…

负载均衡.

简介: 将请求/数据【均匀】分摊到多个操作单元上执行&#xff0c;负载均衡的关键在于【均匀】。 负载均衡的分类: 网络通信分类 四层负载均衡:基于 IP 地址和端口进行请求的转发。七层负载均衡:根据访问用户的 HTTP 请求头、URL 信息将请求转发到特定的主机。 载体维度分类 硬…

物资管理新篇章:Java+SpringBoot实战

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

List去重有几种方式

目录 1、for循环添加去重 2、for 双循环去重 3、for 双循环重复坐标去重 4、Set去重 5、stream流去重 1、for循环添加去重 List<String> oldList new ArrayList<>();oldList.add("张三");oldList.add("张三");oldList.add("李四&q…

数字电路 第三章—第七节(用中规模集成电路实现组合逻辑函数)

一、用数据选择器实现组合逻辑函数 1、基本原理和步骤 &#xff08;1&#xff09;原理&#xff1a;选择器的输出为标准与或式&#xff0c;含地址变量的全部最小项&#xff08;如下图所示的红线标注部分&#xff09;&#xff0c;而任何组合逻辑函数都可以表示成为最小项之和的…

项目管理工具git

git 1. git介绍1.1. 版本控制系统 2. 创建本地版本库2.1 概念2.2 操作步骤 3. 修改文件4. 练习: 添加一个本地项目到仓库5. 添加远程仓库5.1 添加远程仓库5.2 本地仓库同步到远程仓库5.3 克隆远程仓库到本地5.4 SSH设置 6. 分支管理6.1 创建分支6.2 切换分支6.3 合并分支6.4 解…

实践航拍小目标检测,基于轻量级YOLOv8n开发构建无人机航拍场景下的小目标检测识别分析系统

关于无人机相关的场景在我们之前的博文也有一些比较早期的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《deepLabV3Plus实现无人机航拍目标分割识别系统》 《基于目标检测的无人机航拍场景下小目标检测实践》 《助力环保河道水质监测&#xff0c;基于yolov…

QT之项目经验(windows下的sqlite,c++开发)

目录 一、需要时间去磨练gui的调整和优化 1. 借鉴网上开源项目学习 2. gui的布局及调整是磨人的一件事情 3. gui的布局也是可以用组件复刻的 4. 耗时的设备树 二、多线程异步弹窗 三、定时任务动态变更设定 1.确定按钮触发 2.此处监听定时任务时间的改变 3.此处对改变做出具…

[算法沉淀记录]排序算法 —— 快速排序

排序算法 —— 快速排序介绍 基本概念 快速排序&#xff08;Quicksort&#xff09;是一种排序算法&#xff0c;最早由东尼霍尔提出。在平均状况下&#xff0c;排序 n 个项目要 Ο(n log n) 次比较。在最坏状况下则需要 Ο(n2) 次比较&#xff0c;但这种状况并不常见。事实上&…

linux centos7.9改dns和ip

vi /etc/sysconfig/network-scripts/ifcfg-ens32 &#xff1a;wq后 重启网络服务 systemctl restart network —————————————————————————— 篇外话题 软件下载 xshell可以从腾讯软件中心下载

Open CASCADE学习|GC_MakeArcOfCircle构造圆弧

目录 1、通过圆及圆的两个参数创建圆弧&#xff0c;参数为弧度角 2、通过圆及圆上的一点、圆的1个参数创建圆弧&#xff0c;参数为弧度角&#xff0c;Sense决定方向 3、通过圆及圆上的两个点创建圆弧&#xff0c;Sense决定方向 4、通过三点创建圆弧&#xff0c;最后一点应安…

react useRef用法

1&#xff0c;保存变量永远不丢失 import React, { useState,useRef } from react export default function App() { const [count,setcount] useState(0) var mycount useRef(0)//保存变量永远不丢失--useRef用的是闭包原理 return( <div> <button onClick{()>…

SpringBoot使用classfinal-maven-plugin插件加密Jar包

jar包加密 1、在启动类的pom.xml中加入classfinal-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><…

Qt QWidget 简约美观的加载动画 第五季 - 小方块风格

给大家分享两个小方块风格的加载动画 &#x1f60a; 第五季来啦 &#x1f60a; 效果如下: 一个三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QGridLayout> int main(int argc, char *arg…

Python之词频统计(自然语言处理)

背景 词频统计是指对一段文本中每个单词出现的次数进行计数分析。这种分析有助于了解文本的重点词汇、主题或作者的写作风格。如果你有一个特定的文本或想要分析某些内容的词频&#xff0c;你可以提供文本&#xff0c;我可以为你进行简单的词频统计。 例如&#xff0c;如果你…

jeesite用字典项配置二级下拉选

1、配置字典项 2、html代码&#xff1a;修改下拉选项框 <div class"col-xs-6"><div class"form-group"><label class"control-label col-sm-4" title""><span class"required">*</span> ${…

备考北京高考数学:历年选择题真题练一练和解析(2014-2023)

还有三个多月的时间就要高考了&#xff0c;我们今天继续看北京市高考数学真题和解析。今天看5道选择题。独家制作的在线练习集&#xff0c;可以便捷地反复刷这些真题&#xff0c;吃透真题&#xff08;背后的知识点和解题技巧&#xff09;&#xff0c;让高考数学再上一个台阶。 …

OpenAI Sora 关键技术详解:揭秘时空碎片 (Spacetime Patches) 技术

编者按&#xff1a;近日&#xff0c;OpenAI发布其首个视频生成模型“Sora”&#xff0c;该模型生成的视频内容可以呈现出多个角色、特定动作以及复杂场景&#xff0c;为构建能够理解和模拟现实世界的人工智能模型奠定了基础。 本文解析的重点即是 Sora 背后的核心技术 Spacetim…

单片机51 定时器

一、基本概念 1.1简介 单片机的定时器是一种内部功能模块&#xff0c;用于产生计时、计数、延时等功能。定时器通常由一个或多个计数器和相关的控制逻辑组成。单片机的定时器可以运行在不同的工作模式下&#xff0c;以适应不同的计时和计数需求。 C51中的定时器和计数器是同…

Tomcat 下部署若依单体应用可观测最佳实践

实现目标 采集指标信息采集链路信息采集日志信息采集 RUM 信息会话重放 即用户访问前端的一系列过程的会话录制信息&#xff0c;包括点击某个按钮、操作界面、停留时间等&#xff0c;有助于客户真是意图、操作复现 版本信息 Tomcat (9.0.81)Springboot(2.6.2)JDK (>8)DDT…