百摩网
当前位置: 首页 生活百科

springboot上传excel(SpringBoot整合easyexcel实现Excel的导入与导出)

时间:2023-06-01 作者: 小编 阅读量: 1 栏目名: 生活百科

之前使用poi导出excel需要自己先去创建excel文件,还要创建sheet,写表头,操作起来确实很麻烦,针对产品这种随心而欲的需求我们能不能快速的做完这样一个产品看起来挺简单的功能。基于这样一个快速开发的场景,我们来看看easyexcel应该如何使用。首先我们创建一个springboot项目,在此就不过多的啰嗦,创建好之后,首先需要引入easyexcel的maven坐标。我们来看下导出的效果,这样就可以满足我们平时开发需要的excel导出功能。

导出

在一般不管大的或者小的系统中,各家的产品都一样,闲的无聊的时候都喜欢让我们这些程序员导出一些数据出来供他观赏,非说这是必须需求,非做不可,那么我们就只能苦逼的哼哧哼哧的写bug喽。

之前使用poi导出excel需要自己先去创建excel文件,还要创建sheet,写表头,操作起来确实很麻烦,针对产品这种随心而欲的需求我们能不能快速的做完这样一个产品看起来挺简单的功能。

基于这样一个快速开发的场景,我们来看看easyexcel应该如何使用。

首先我们创建一个springboot(版本是 2.1.4.RELEASE)项目,在此就不过多的啰嗦,创建好之后,首先需要引入easyexcel的maven坐标。

<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>1.1.2-beta5</version></dependency>

导入好了之后,我们接下来需要创建一个导出的模板类,首先要集成BaseRowModel,set、get省略,@ExcelProperty注解中的value就是表头的信息,index是在第几列,没有加注解的不会导出。

public class OrderExcelBO extends BaseRowModel { @ExcelProperty(value = {"订单ID"}, index = 0) private String id; /** * 订单描述 */ @ExcelProperty(value = {"订单描述"}, index = 2) private String description; /** * 订单对应产品id */ @ExcelProperty(value = {"产品ID"}, index = 2) private Integer productId; /** * 支付方式描述,如:apple pay */ @ExcelProperty(value = {"支付方式"}, index = 3) private String payMethod; /** * create_time */ @ExcelProperty(value = {"时间"}, index = 4) private String createTime; /** * update_time */ private String updateTime; /** * 产生订单的用户 */ @ExcelProperty(value = {"用户ID"}, index = 5) private Integer userId; /** * 支付状态:0 未支付、1支付成功支付完成、-1支付失败 */ @ExcelProperty(value = {"支付状态"}, index = 6) private String status; /** * 订单来源描述,如:ios 安卓 */ @ExcelProperty(value = {"手机型号"}, index = 7) private String platform; /** * 订单流水 */ @ExcelProperty(value = {"订单流水号"}, index = 8) private String flowNum; /** * 订单金额 */ @ExcelProperty(value = {"金额"}, index = 9) private BigDecimal price; // @ExcelProperty(value = {"收据字段"}, index = 10) private String receipt; @ExcelProperty(value = {"APP来源"}, index = 10) private String sources;}


导出的模板定义好之后,接下来就是一些封装好的工具类的调用

  1. 查出我们需要导出的数据;
  2. 生成Excel文件名和sheet名称;
  3. 直接调用封装好的工具类导出文件即可;

我们来看下导出的效果

如果你的表头比较复杂,那么根据需求,你也可自行定义,例如如下这种复杂的表头,应该如何设置

首先要修改模板类,如果合并的单元格最大为2,那么所有的表格都需要设置为2,不合并的单元格用空字符串填充,需要合并的单元格将合并部分写上相同的名称,并且排列的序号要连续,不能分开。

我们来看下导出的效果,这样就可以满足我们平时开发需要的excel导出功能。简单易上手。

工具类:

import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import java.util.ArrayList;import java.util.List;/** * 监听类,可以自定义 * * @author liuyi * @Created 2019-7-18 18:01:53 **/public class ExcelListener extends AnalysisEventListener { /** * 自定义用于暂时存储data。 * 可以通过实例获取该值 */ private List<Object> datas = new ArrayList<>(); /** * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据 */ @Override public void invoke(Object object, AnalysisContext context) { //数据存储到list,供批量处理,或后续自己业务逻辑处理。 datas.add(object); //根据业务自行 do something doSomething(); /* 如数据过大,可以进行定量分批处理 if(datas.size()<=100){ datas.add(object); }else { doSomething(); datas = new ArrayList<Object>(); } */ } /** * 根据业务自行实现该方法 */ private void doSomething() { } @Override public void doAfterAllAnalysed(AnalysisContext context) { /* datas.clear(); 解析结束销毁不用的资源 */ } public List<Object> getDatas() { return datas; } public void setDatas(List<Object> datas) { this.datas = datas; }}

import com.alibaba.excel.Excelreader;import com.alibaba.excel.ExcelWriter;import com.alibaba.excel.metadata.BaseRowModel;import com.alibaba.excel.metadata.Font;import com.alibaba.excel.metadata.Sheet;import com.alibaba.excel.metadata.TableStyle;import com.alibaba.excel.support.ExcelTypeEnum;import com.mochu.exception.ExcelException;import org.apache.poi.poifs.filesystem.FileMagic;import org.apache.poi.ss.usermodel.IndexedColors;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.BufferedinputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.List;/** * Excel工具类 * * @author liuyi * @Created 2019-7-18 18:01:53 **/public class ExcelUtil { /** * 读取 Excel(多个 sheet) * * @param excel 文件 * @param rowModel 实体类映射,继承 BaseRowModel 类 * @return Excel 数据 list */ public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel) { ExcelListener excelListener = new ExcelListener(); ExcelReader reader = getReader(excel, excelListener); if (reader == null) { return null; } for (Sheet sheet : reader.getSheets()) { if (rowModel != null) { sheet.setClazz(rowModel.getClass()); } reader.read(sheet); } return excelListener.getDatas(); } /** * 读取某个 sheet 的 Excel * * @param excel 文件 * @param rowModel 实体类映射,继承 BaseRowModel 类 * @param sheetNo sheet 的序号 从1开始 * @return Excel 数据 list */ public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo) { return readExcel(excel, rowModel, sheetNo, 1); } /** * 读取某个 sheet 的 Excel * * @param excel 文件 * @param rowModel 实体类映射,继承 BaseRowModel 类 * @param sheetNo sheet 的序号 从1开始 * @param headLineNum 表头行数,默认为1 * @return Excel 数据 list */ public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo, int headLineNum) { ExcelListener excelListener = new ExcelListener(); ExcelReader reader = getReader(excel, excelListener); if (reader == null) { return null; } reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass())); return excelListener.getDatas(); } /** * 导出 Excel :一个 sheet,带表头 * * @param response HttpServletResponse * @param list 数据 list,每个元素为一个 BaseRowModel * @param fileName 导出的文件名 * @param sheetName 导入文件的 sheet 名 * @param object 映射实体类,Excel 模型 */ public static void writeExcel(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName, String sheetName, BaseRowModel object) { ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX); Sheet sheet = new Sheet(1, 0, object.getClass()); sheet.setSheetName(sheetName); TableStyle tableStyle = new TableStyle(); tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE); Font font = new Font(); font.setFontHeightInPoints((short) 9); tableStyle.setTableHeadFont(font); tableStyle.setTableContentFont(font); sheet.setTableStyle(tableStyle); writer.write(list, sheet); writer.finish(); } /** * 导出 Excel :多个 sheet,带表头 * * @param response HttpServletResponse * @param list 数据 list,每个元素为一个 BaseRowModel * @param fileName 导出的文件名 * @param sheetName 导入文件的 sheet 名 * @param object 映射实体类,Excel 模型 */ public static ExcelWriterFactory writeExcelWithSheets(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName, String sheetName, BaseRowModel object) { ExcelWriterFactory writer = new ExcelWriterFactory(getOutputStream(fileName, response), ExcelTypeEnum.XLSX); Sheet sheet = new Sheet(1, 0, object.getClass()); sheet.setSheetName(sheetName); sheet.setTableStyle(getTableStyle()); writer.write(list, sheet); return writer; } /** * 导出融资还款情况表 * * @param response * @param list * @param fileName * @param sheetName * @param object */ public static void writeFinanceRepayment(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName, String sheetName, BaseRowModel object) { ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX); Sheet sheet = new Sheet(1, 0, object.getClass()); sheet.setSheetName(sheetName); sheet.setTableStyle(getTableStyle()); writer.write(list, sheet); for (int i = 1; i <= list.size(); i= 4) { writer.merge(i, i3, 0, 0); writer.merge(i, i3, 1, 1); } writer.finish(); } /** * 导出文件时为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", "filename="fileName); return response.getOutputStream(); } catch (Exception e) { throw new ExcelException("导出异常!"); } } /** * 返回 ExcelReader * * @param excel 需要解析的 Excel 文件 * @param excelListener new ExcelListener() */ private static ExcelReader getReader(MultipartFile excel, ExcelListener excelListener) { String filename = excel.getOriginalFilename(); if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) { throw new ExcelException("文件格式错误!"); } InputStream inputStream; try { inputStream = new BufferedInputStream(excel.getInputStream()); return new ExcelReader(inputStream, null, excelListener, false); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 资金收支导出 Excel :一个 sheet,带表头 * * @param response HttpServletResponse * @param list 数据 list,每个元素为一个 BaseRowModel * @param fileName 导出的文件名 * @param sheetName 导入文件的 sheet 名 * @param object 映射实体类,Excel 模型 */ public static void exportFundBudgetExcel(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName, String sheetName, BaseRowModel object) throws IOException { ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX); Sheet sheet = new Sheet(1, 0, object.getClass()); sheet.setSheetName(sheetName); sheet.setTableStyle(getTableStyle()); writer.write(list, sheet); writer.merge(2, 3, 0, 0); writer.merge(4, 13, 0, 0); writer.merge(14, 14, 0, 1); writer.finish(); } /** * 读取Excel表格数据,封装成实体 * * @param inputStream * @param clazz * @param sheetNo * @param headLineMun * @return */ public static Object readExcel(InputStream inputStream, Class<? extends BaseRowModel> clazz, Integer sheetNo, Integer headLineMun) { if (null == inputStream) { throw new NullPointerException("the inputStream is null!"); } ExcelListener listener = new ExcelListener(); ExcelReader reader = new ExcelReader(inputStream, valueOf(inputStream), null, listener); reader.read(new Sheet(sheetNo, headLineMun, clazz)); return listener.getDatas(); } /** * 根据输入流,判断为xls还是xlsx,该方法原本存在于easyexcel 1.1.0 的ExcelTypeEnum中。 */ public static ExcelTypeEnum valueOf(InputStream inputStream) { try { FileMagic fileMagic = FileMagic.valueOf(inputStream); if (FileMagic.OLE2.equals(fileMagic)) { return ExcelTypeEnum.XLS; } if (FileMagic.OOXML.equals(fileMagic)) { return ExcelTypeEnum.XLSX; } throw new ExcelException("excelTypeEnum can not null"); } catch (IOException e) { throw new RuntimeException(e); } } /** * 设置全局样式 * * @return */ private static TableStyle getTableStyle() { TableStyle tableStyle = new TableStyle(); tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE); Font font = new Font(); font.setBold(true); font.setFontHeightInPoints((short) 9); tableStyle.setTableHeadFont(font); Font fontContent = new Font(); fontContent.setFontHeightInPoints((short) 9); tableStyle.setTableContentFont(fontContent); return tableStyle; }}

import com.alibaba.excel.ExcelWriter;import com.alibaba.excel.metadata.BaseRowModel;import com.alibaba.excel.metadata.Sheet;import com.alibaba.excel.support.ExcelTypeEnum;import java.io.IOException;import java.io.OutputStream;import java.util.List;/** *ExcelWriterFactory 工具类 * @author liuyi * @Created 2019-7-18 18:01:53 **/public class ExcelWriterFactory extends ExcelWriter { private OutputStream outputStream; private int sheetNo = 1; public ExcelWriterFactory(OutputStream outputStream, ExcelTypeEnum typeEnum) { super(outputStream, typeEnum); this.outputStream = outputStream; } public ExcelWriterFactory write(List<? extends BaseRowModel> list, String sheetName, BaseRowModel object) { this.sheetNo; try { Sheet sheet = new Sheet(sheetNo, 0, object.getClass()); sheet.setSheetName(sheetName); this.write(list, sheet); } catch(Exception ex) { ex.printStackTrace(); try { outputStream.flush(); } catch(IOException e) { e.printStackTrace(); } } return this; } @Override public void finish() { super.finish(); try { outputStream.flush(); } catch(IOException e) { e.printStackTrace(); } }}

导入

其实在提供的那几个工具类中已经有了导入的方法,只需要直接调用即可。下面我们来简单演示一下,如何导入。我们先看下Controller是如何写的

@PostMapping("/import/order")public ResultMsg import_order(MultipartFile excel) { Object objList = ExcelUtil.readExcel(excel, new OrderExcelBO(), 1, 1); if (objList == null) { return ResultMsg.fail(500, "导入的数据不能为空"); } List<OrderExcelBO> orderList = (List<OrderExcelBO>) objList; if (orderList == null || orderList.size() <= 0) { return ResultMsg.fail(500, "导入的数据不能为空"); } orderList.forEach(System.out::println); return ResultMsg.success();}

我们主要再看下readExcel()方法是如何写的

/** * 读取某个 sheet 的 Excel * * @param excel 文件 * @param rowModel 实体类映射,继承 BaseRowModel 类 * @param sheetNo sheet 的序号 从1开始 * @param headLineNum 表头行数,默认为1 * @return Excel 数据 list */ public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo, int headLineNum) { ExcelListener excelListener = new ExcelListener(); ExcelReader reader = getReader(excel, excelListener); if (reader == null) { return null; } reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass())); return excelListener.getDatas(); }

在底层的方法我就不贴出来了,我大家可在()文章里面找到需要的工具类,我们就直接看下运行结果。

导出结果

那么数据都已经打印出来了,那么存入数据库就超级简单了。

    推荐阅读
  • 手机怎么下载ppt(有了解的吗)

    以下内容大家不妨参考一二希望能帮到您!手机怎么下载ppt如果是现成的ppt课件,直接下载到手机存储卡中,手机上还需要安装一个office手机版才能打开ppt文件。若是直接手机无法打开,建议转换格式为pdf之类的。另外如果没有现成的PPT课件,网上可以搜索一些现成的ppt课件,如果是上课老师讲解的课程,建议下课时找老师拷贝PPT课件,存在手机上就好了。

  • 素颜口红推荐榜单图(京东2022年5月口红榜单)

    根据电商数据搜索工具——“弦镜”数据显示,京东平台2022年5月口红热卖品牌榜单,第一名迪奥,销售额为5905.42万元。第二名圣罗兰,销售额为3975.46万元。第三名纪梵希,销售额为3520.66万元。从第四名到第十名分别为完美日记、兰蔻、阿玛尼、魅可、花西子、汤姆福特、雅诗兰黛。统计区间:2022年5月1日-5月31日覆盖平台:京东统计工具:弦镜数据说明:弦镜数据全部来自公开网页,不涉及个人隐私、商业秘密,此数据为消费者视角数据。

  • 空气炸锅制作小饼干窍门(空气炸锅做番茄小饼干的做法)

    我们一起去了解并探讨一下这个问题吧!空气炸锅制作小饼干窍门准备半个西红柿,去皮切碎。打一个鸡蛋,加入10克白糖,5克芝麻。揉成光滑的面团。用磨具扣出形状。用叉子扎出小孔。全部做好以后的样子。放入空气炸锅,160度10分钟。烤至两面焦黄即可,空气炸锅版的番茄小饼干出锅。成品还不错,一口一个嘎嘣脆。喜欢的可以试试,香脆可口。

  • 驾考手动挡开车起步7个步骤(驾考手动挡开车起步有哪些步骤)

    驾考手动挡开车起步7个步骤?下面更多详细答案一起来看看吧!一踩:踩离合器;二挂:挂到1挡;三转:打开左转向灯;四鸣:鸣喇叭;五放:放手刹;最后六稳和七抬最好一并说,稳住油门和抬起离合踏步。

  • 绿竹怎么养(水养绿竹怎么养)

    栽植绿竹所使用的土壤要确保土质营养充沛、疏松透气,可用泥炭土、腐叶土等材料混合制成,满足绿竹生长所需。生长温度范围温度稳定在20~25℃之间。植株对于低温的耐受力比较差,低于0℃生长就容易出现问题,当温度低于零下5℃则会被冻伤。冬季时做好保温防寒工作。

  • 剖腹产伤口多久愈合()

    休息时,最好采取侧卧微屈体位休息,以减少腹壁张力。保持伤口清洁干爽保持伤口的清洁与干燥,能有效预防感染,促进伤口愈合。烤伤口时至少要离伤口15-20厘米,以免烫伤皮肤。这是因为通过持续加压可造成瘢痕局部缺氧,从而抑制瘢痕生长。剖腹产后吃什么促进伤口愈合1、产后一周内,可以增加蛋白质食物。如牛奶、鸡蛋等,高蛋白可以促使伤口尽快愈合。也切忌吃辛辣及刺激性的食物,以免影响伤口复原。

  • 天正cad不允许修改图层怎么回事(天正建筑CAD顽固图层删不掉)

    不知道大家有没有觉得,其实自己画的图纸也没多复杂,但是导出来的CAD文件就是很大!传输要传老半天不说,有时要打开再修改一下突然就卡死了,简直难受!很多时候都是这个东西在作怪——图层!那么要怎么清理呢?小编今天就来教你如何删除图层!看完这些操作技巧,不仅要保存收藏,还需要经常反复拿出来练习并运用,才能真正成为自己的知识和技能。↓↓↓↓点击下方“了解更多”,学习天正建筑CAD软件视频教程

  • 一个猪圈有非瘟几天能传染上 一个猪圈有非瘟几天能传染上,隔壁院传染吗

    非瘟是由非洲猪瘟病毒感染家猪和各种野猪而引起的一种急性、出血性、烈性传染病。猪群得了非洲猪瘟一般10-15天内就会死亡,非洲猪瘟有5-9天的自然感染潜伏期,发病时体温会升至41℃,一般发热后第7天就会死亡,严重的1、2天便死亡。一旦猪场确诊有一只感染非洲猪瘟,一般需要将同一猪圈的生猪全部扑杀。

  • 手上长透明小水泡很痒该怎么办(手上又见透明小水泡痒到怀疑人生)

    “汗疱疹”主要表现为深在性小水疱,粟粒至米粒大小,略高出皮肤表面,常无红晕。伴不同程度的灼热及瘙痒,常连续发作数年。杨敏表示,当前医学对于“汗疱疹”的病因尚不十分清楚,只有少数病人发现和身体他处的霉菌感染或金属过敏甚至情绪压力有关。杨敏指出,一旦出现“汗疱疹”,可根据其具体症状进行防治。

  • 食品安全知识资料(食品要这样才够安全)

    食品安全知识资料到正规商店里购买,不买校园周边、街头巷尾的“三无”食品。购买正规厂家生产的食品,尽量选择信誉度较好的品牌。煮熟后放置2小时以上的食品,重新加热到70℃以上再食用;瓜果洗净并去除外皮后才食用。不购食来路不明和超过保质期的食。不吃已确认变质或怀疑可能变了质的食品。不吃明知添加了防腐剂或色素而又不能肯定其添加量是否符合食品卫生安全标准的食品。