SpringBoot2:web开发常用功能实现及原理解析-整合EasyExcel实现Excel导入导出功能

news2024/9/29 23:28:37

1、工程包结构

主要是这5个Java类
在这里插入图片描述

2、导入EasyExcel包

这里同时贴出其他相关springboot的基础包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入easyExcel依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>

3、Java代码

ExcelSysUser


import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import lombok.ToString;
import org.apache.poi.ss.usermodel.HorizontalAlignment;

@ContentRowHeight(25)
@HeadRowHeight(15)
@ColumnWidth(25)
@HeadFontStyle(fontHeightInPoints=9)
@ContentStyle(horizontalAlignment= HorizontalAlignment.CENTER)
@Data
@ToString
public class ExcelSysUser {

	public ExcelSysUser(){

	}

	public ExcelSysUser(String loginName, String userName, String userPwd){
		this.loginName = loginName;
		this.userName = userName;
		this.userPwd = userPwd;
	}

	@ExcelProperty(value = "登录名",index = 0)
	private String loginName;

	@ExcelProperty(value = "用户名",index = 1)
	private String userName;

	@ExcelProperty(value = "密码",index = 2)
	private String userPwd;

}

ExcelFillCellMergeHandler


import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 合并单元格处理类
 */
public class ExcelFillCellMergeHandler implements CellWriteHandler {

	//需要合并的列
	private int[] mergeColumnIndex;
	//从哪一列开始合并
	private int mergeRowIndex;

	public ExcelFillCellMergeHandler() {
	}

	public ExcelFillCellMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) {
		this.mergeRowIndex = mergeRowIndex;
		this.mergeColumnIndex = mergeColumnIndex;
	}

	@Override
	public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

	}

	@Override
	public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

	}

	@Override
	public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

	}

	@Override
	public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
		int curRowIndex = cell.getRowIndex();
		int curColIndex = cell.getColumnIndex();
		if (curRowIndex > mergeRowIndex) {
			for (int i = 0; i < mergeColumnIndex.length; i++) {
				if (curColIndex == mergeColumnIndex[i]) {
					mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
					break;
				}
			}
		}
	}

	/**
	 * 当前单元格向上合并
	 *
	 * @param writeSheetHolder
	 * @param cell             当前单元格
	 * @param curRowIndex      当前行
	 * @param curColIndex      当前列
	 */
	private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
		Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
		Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
		Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
		// 将当前单元格数据与上一个单元格数据比较
		Boolean dataBool = preData.equals(curData);
		Boolean bool = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue());
		if (dataBool && bool) {
			Sheet sheet = writeSheetHolder.getSheet();
			List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
			boolean isMerged = false;
			for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
				CellRangeAddress cellRangeAddr = mergeRegions.get(i);
				// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
				if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
					sheet.removeMergedRegion(i);
					cellRangeAddr.setLastRow(curRowIndex);
					sheet.addMergedRegion(cellRangeAddr);
					isMerged = true;
				}
			}
			// 若上一个单元格未被合并,则新增合并单元
			if (!isMerged) {
				CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
				sheet.addMergedRegion(cellRangeAddress);
			}
		}
	}

}

ExcelListener


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.ArrayList;
import java.util.List;

/**
 * 解析监听器,
 * 每解析一行会回调invoke()方法。
 * 整个excel解析结束会执行doAfterAllAnalysed()方法
 */
public class ExcelListener extends AnalysisEventListener {

	private List<Object> datas = new ArrayList<>();

	public List<Object> getDatas() {
		return datas;
	}

	public void setDatas(List<Object> datas) {
		this.datas = datas;
	}

	/**
	 * 逐行解析
	 * object : 当前行的数据
	 */
	@Override
	public void invoke(Object object, AnalysisContext context) {
		//当前行
		// context.getCurrentRowNum()
		if (object != null) {
			datas.add(object);
		}
	}


	/**
	 * 解析完所有数据后会调用该方法
	 */
	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		//解析结束销毁不用的资源
	}
}

EasyExcelUtil

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.atguigu.boot.handler.ExcelFillCellMergeHandler;
import com.atguigu.boot.listener.ExcelListener;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

/**
 * EasyExcel工具类
 */
public class EasyExcelUtil {

	/**
	 * 读取 Excel(多个 sheet)
	 *
	 * @param excel 文件
	 * @param rowModel 实体类映射
	 * @return Excel 数据 list
	 */
	public static List<Object> readExcel(MultipartFile excel, Object rowModel) throws IOException {
		String filename = excel.getOriginalFilename();
		if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
			throw new RuntimeException("文件格式错误!");
		}
		ExcelListener excelListener = new ExcelListener();
		EasyExcel.read(excel.getInputStream(),rowModel.getClass(),excelListener).doReadAll();
		return excelListener.getDatas();
	}

	/**
	 * 导出 Excel :一个 sheet,带表头
	 *
	 * @param response HttpServletResponse
	 * @param list 数据 list
	 * @param fileName 导出的文件名
	 * @param sheetName 导入文件的 sheet 名
	 * @param object 映射实体类,Excel 模型
	 */
	public static void writeExcel(HttpServletResponse response, List<?> list, String fileName,
								  String sheetName, Object object) {
		EasyExcel.write(getOutputStream(fileName, response),object.getClass())
				.excelType(ExcelTypeEnum.XLSX)
				.autoCloseStream(Boolean.TRUE)
				.sheet(sheetName)
				.doWrite(list);
	}

	/**
	 * 导出 Excel 自动合并单元格
	 * @param response HttpServletResponse
	 * @param list 数据 list
	 * @param fileName 导出的文件名
	 * @param sheetName 导入文件的 sheet 名
	 * @param object 映射实体类,Excel 模型
	 * @param mergeColumnIndex 需要合并的列
	 * @param mergeRowIndex 从哪一列开始合并
	 */
	public static void writeMergeExcel(HttpServletResponse response, List<?> list, String fileName,
									   String sheetName, Object object, int[] mergeColumnIndex, int mergeRowIndex) {
		EasyExcel.write(getOutputStream(fileName, response),object.getClass())
				.excelType(ExcelTypeEnum.XLSX)
				.autoCloseStream(Boolean.TRUE)
				.registerWriteHandler(new ExcelFillCellMergeHandler(mergeRowIndex,mergeColumnIndex))
				.sheet(sheetName)
				.doWrite(list);
	}

	/**
	 * 导出文件时为Writer生成OutputStream
	 */
	private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
		//创建本地文件
		fileName = fileName + ".xls";

		try {
			fileName = new String(fileName.getBytes(), "ISO-8859-1");
			response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

			return response.getOutputStream();
		} catch (Exception e) {
			throw new RuntimeException("导出异常!");
		}
	}

}

EasyExcelLoadsController


import com.atguigu.boot.bean.ExcelSysUser;
import com.atguigu.boot.utils.EasyExcelUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/excel")
public class EasyExcelLoadsController {

	/**
	 * 用户信息导出Excel
	 */
	@RequestMapping(value = "/exportSysUser",method = RequestMethod.GET)
	public void exportSysUser(HttpServletResponse response){
		List<ExcelSysUser> excelSysUsers = new ArrayList<>();
		ExcelSysUser excelSysUser1 = new ExcelSysUser("张三", "zhangsan002", "zsmm123");
		ExcelSysUser excelSysUser2 = new ExcelSysUser("张三", "zhangsan003", "zsmm456");
		ExcelSysUser excelSysUser3 = new ExcelSysUser("张三", "zhangsan001", "zsmm789");
		ExcelSysUser excelSysUser4 = new ExcelSysUser("李四", "zhangsan001", "zsmm123");
		ExcelSysUser excelSysUser5 = new ExcelSysUser("李四", "zhangsan001", "zsmm456");
		excelSysUsers.add(excelSysUser1);
		excelSysUsers.add(excelSysUser2);
		excelSysUsers.add(excelSysUser3);
		excelSysUsers.add(excelSysUser4);
		excelSysUsers.add(excelSysUser5);
		EasyExcelUtil.writeExcel(response, excelSysUsers,"用户信息","用户信息", new ExcelSysUser());

	}

	/**
	 * 用户信息导出Excel(合并单元格)
	 */
	@RequestMapping(value = "/exportMergeSysUser",method = RequestMethod.GET)
	public void exportMergeSysUser(HttpServletResponse response){
		List<ExcelSysUser> excelSysUsers = new ArrayList<>();
		ExcelSysUser excelSysUser1 = new ExcelSysUser("张三", "zhangsan002", "zsmm123");
		ExcelSysUser excelSysUser2 = new ExcelSysUser("张三", "zhangsan003", "zsmm456");
		ExcelSysUser excelSysUser3 = new ExcelSysUser("张三", "zhangsan001", "zsmm789");
		ExcelSysUser excelSysUser4 = new ExcelSysUser("李四", "zhangsan001", "zsmm123");
		ExcelSysUser excelSysUser5 = new ExcelSysUser("李四", "zhangsan001", "zsmm456");
		excelSysUsers.add(excelSysUser1);
		excelSysUsers.add(excelSysUser2);
		excelSysUsers.add(excelSysUser3);
		excelSysUsers.add(excelSysUser4);
		excelSysUsers.add(excelSysUser5);
		int[] mergeColumnIndex = {0,1};
		int mergeRowIndex = 0;
		EasyExcelUtil.writeMergeExcel(response, excelSysUsers,"用户信息","用户信息", new ExcelSysUser(), mergeColumnIndex, mergeRowIndex);

	}

	@RequestMapping(value = "/importSysUser",method = RequestMethod.POST)
	public void importSysUser(MultipartFile excel){
		List<Object> dataList = null;
		try {
			dataList = EasyExcelUtil.readExcel(excel, new ExcelSysUser());
		} catch (IOException e) {
			e.printStackTrace();
		}
		dataList.forEach(o -> System.out.println(o.toString()));
	}

}

4、测试Excel

导入需要准备下图中的数据,导出直接浏览器访问接口即可。
在这里插入图片描述

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

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

相关文章

Docker 网络基本概念

在之前讲 Redis 集群搭建的时候&#xff0c;我们用过一个选项 --net host​&#xff0c;现在就来讲讲该选项&#xff0c;以及 Docker 的网络。 docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluste…

【python】OpenCV—Mask RCNN for Object Detection and Instance Segmentation

文章目录 1、任务描述2、MASR RCNN 网络结构3、方法实现4、结果展示5、涉及到的库getPerfProfile 6、参考 1、任务描述 利用 mask rcnn 网络&#xff0c;进行图片和视频的目标检测和实例分割 2、MASR RCNN 网络结构 3、方法实现 # Copyright (C) 2018-2019, BigVision LLC (L…

YOLOv5改进 | 模块缝合 | C3 融合Self-Calibrated Convolutions丰富特征图【CVPR2020】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv5入门 改…

pgrouting实战应用

1&#xff09;下载地区地区数据&#xff08;下载数据是XYZM 四位数据&#xff09; 2&#xff09;下载裁剪行政区数据 3&#xff09;使用arcgis pro添加路网数据和行政区数据 4&#xff09;裁剪数据&#xff0c;仅历下行政区路网 5&#xff09;arcgis pro要素转线&#xff0…

基础GAN生成式对抗网络(pytorch实验)

&#xff08;Generative Adversarial Network&#xff09; 一、理论 https://zhuanlan.zhihu.com/p/307527293?utm_campaignshareopn&utm_mediumsocial&utm_psn1815884330188283904&utm_sourcewechat_session 大佬的文章中的“GEN的本质”部分 二、实验 1、数…

SIP ACK method

SIP ACK同样在RFC3261中定义。 ACK仅仅用于对INVITE request的response的回复&#xff0c;例如在通话结束时&#xff0c;MO要断开连接&#xff0c;此时就会生成一条BYE 消息。BYE不会经过代理&#xff0c;而是直接路由到MT。MT通过200 (OK) 响应确认收到 BYE&#xff0c;然后就…

vagrant+virtualbox+ubuntu22.04无法上网问题

一、过程 vagrantfile配置私有网络 config.vm.network "private_network", ip: "192.168.56.10"启动虚拟机&#xff0c;可以ping通百度的实际IP&#xff0c;ping不通域名修改/etc/netplan/50-vagrant.yaml&#xff0c;配置DNS network:renderer: Networ…

计算机毕业设计Python知识图谱美团美食推荐系统 美团餐厅推荐系统 美团推荐系统 美食价格预测 美团爬虫 美食数据分析 美食可视化大屏

《Python知识图谱美团美食推荐系统》开题报告 一、研究背景与意义 随着信息技术的飞速发展和互联网应用的普及&#xff0c;人们的消费习惯逐渐从线下转移到线上&#xff0c;外卖行业迎来了前所未有的发展机遇。美团作为国内领先的生活服务电子商务平台&#xff0c;拥有庞大的…

基于SpringBoot+Vue的考务报名平台(带1w+文档)

基于SpringBootVue的考务报名平台(带1w文档) 基于SpringBootVue的考务报名平台(带1w文档) 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进…

026.(娱乐)魔改浏览器-任务栏图标右上角加提示徽章

一、目标&#xff1a; windows中&#xff0c;打开chromium&#xff0c;任务栏中会出现一个chromium的图标。我们的目标是给这个图标的右上角&#xff0c;加上"有1条新消息"的小提示图标&#xff0c;也叫徽章(badge)注意&#xff1a;本章节纯属娱乐&#xff0c;有需要…

【DS】AVL树

目录 AVL树的介绍AVL树节点的定义认识AVL树的抽象图AVL树的插入BSTree规则插入更新平衡因子平衡因子的判断 AVL树的旋转左单旋右单旋左右双旋右左双旋 AVL树的验证AVL树的查找AVL树的性能 在上篇搜索二叉树末尾提到过&#xff0c;得益于搜索二叉树的性质&#xff1a;大于根往右…

计算机毕业设计Python深度学习垃圾邮件分类检测系统 朴素贝叶斯算法 机器学习 人工智能 数据可视化 大数据毕业设计 Python爬虫 知识图谱 文本分类

基于朴素贝叶斯的邮件分类系统设计 摘要&#xff1a;为了解决垃圾邮件导致邮件通信质量被污染、占用邮箱存储空间、伪装正常邮件进行钓鱼或诈骗以及邮件分类问题。应用Python、Sklearn、Echarts技术和Flask、Lay-UI框架&#xff0c;使用MySQL作为系统数据库&#xff0c;设计并实…

java: 程序包org.junit.jupiter.api不存在

明明idea没有报错&#xff0c;引用包也没问题&#xff0c;为啥提示java: 程序包org.junit.jupiter.api不存在&#xff1f; 配置&#xff01;还TMD是配置&#xff01; 如果是引用包的版本不对或者其他&#xff0c;直接就是引用报错或者pom里面飘红了。 这个应该是把generat…

微服务-- Sentinel的使用

目录 Sentinel&#xff1a;微服务的哨兵 生态系统景观 sentinel与spring cloud Hystrix 对比 Sentinel 主要分为两部分 Sentinel安装与使用 Sentinel的控制规则 流控规则 流控规则的属性说明 新增流控规则 关联流控模式 SentinelResource注解的使用 SentinelResou…

如何将自己的项目发布到Maven中央仓库

1.背景 本教程为2024年9月最新版 我有一个java项目想发布到maven中央仓库&#xff0c;然后任何人都可以在pom文件中引用我写的代码 引用格式如下&#xff1a; <!-- 这是引用rocketmq的坐标 --> <dependency><groupId>org.apache.rocketmq</groupId>&l…

炫酷HTML蜘蛛侠登录页面

全篇使用HTML、CSS、JavaScript&#xff0c;建议有过基础的进行阅读。 一、预览图 二、HTML代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…

ESP8266做httpServer提示Header fields are too long for server to interpret

CONFIG_HTTP_BUF_SIZE512 CONFIG_HTTPD_MAX_REQ_HDR_LEN1024 CONFIG_HTTPD_MAX_URI_LEN512CONFIG_HTTPD_MAX_REQ_HDR_LEN由512改为1024

C++ | Leetcode C++题解之第404题左叶子之和

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isLeafNode(TreeNode* node) {return !node->left && !node->right;}int sumOfLeftLeaves(TreeNode* root) {if (!root) {return 0;}queue<TreeNode*> q;q.push(root);int ans 0;while …

氢能源多旋翼无人机技术详解

1. 技术背景与优势 随着全球对低碳、环保和高效能源解决方案的需求日益增长&#xff0c;氢能源作为一种清洁、高效的能源形式&#xff0c;在多个领域展现出巨大的应用潜力。在无人机领域&#xff0c;氢能源多旋翼无人机因其独特的优势逐渐受到关注。相比传统锂电池无人机&…

Linux sh命令

目录 一. 基本语法二. 选项2.1 -c 字符串中读取内容&#xff0c;并执行2.1.1 基本用法2.1.2 获取当前目录下失效的超链接 2.2 -x 每个命令执行之前&#xff0c;将其打印出来2.3 结合Here文档使用 一. 基本语法 ⏹Linux 和 Unix 系统中用于执行 shell 脚本 或 运行命令 的命令。…