300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > java使用EasyExcel实现导入导出几种方式(导入 模板导出 和不需要模板的导出)

java使用EasyExcel实现导入导出几种方式(导入 模板导出 和不需要模板的导出)

时间:2022-06-08 03:48:53

相关推荐

java使用EasyExcel实现导入导出几种方式(导入 模板导出 和不需要模板的导出)

java通过EasyExcel实现导入导出(导入、模板导出、和不需要模板的导出)

此文章只是涉及到简单的导入导出

通过实体模板导入数据无实体模板导入数据导出数据通过模板导出数据

使用到的maven依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.0</version></dependency>

用到的实体和工具类

package com.example.entity;import cn.hutool.core.date.DatePattern;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.format.DateTimeFormat;import lombok.Data;import java.util.Date;/*** @Author user* @Date /5/6 12:03* @Description*/@Datapublic class User {@ExcelProperty(value = "姓名",index = 0)private String name;@ExcelProperty(value = "年龄",index = 1)private Integer age;@ExcelProperty(value = "性别",index = 2)private String sex;@ExcelProperty(value = "生日",index = 3)@DateTimeFormat(value = DatePattern.NORM_DATE_PATTERN)private Date birthday;@ExcelProperty(value = "备注",index = 4)private String remark;}

package com.example.util;import com.alibaba.excel.annotation.ExcelProperty;import org.apache.poi.ss.usermodel.*;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.io.UnsupportedEncodingException;import java.lang.reflect.Field;import .URLEncoder;import java.nio.charset.StandardCharsets;import java.util.ArrayList;import java.util.Iterator;import java.util.List;/*** @Author user* @Date /5/6 12:38* @Description*/public class ExcelUtil {/*** 手写校验表头* @param is excel文件流* @param clazz 模板类*/public static void checkExcelHeaders(InputStream is, Class clazz) {List<String> inputList = new ArrayList<>();List<String> requiredList = new ArrayList<>();Field[] allFields = clazz.getDeclaredFields();for (int i = 0; i < allFields.length; ++i) {Field field = allFields[i];ExcelProperty attr = field.getAnnotation(ExcelProperty.class);if (null != attr) {//excel里面加入多余的字段requiredList.add(attr.value()[0]);}}try {Workbook wb = WorkbookFactory.create(is);Sheet sheet = wb.getSheetAt(0);Row row = sheet.getRow(0);for (Iterator<Cell> iter = row.cellIterator(); iter.hasNext(); ) {Cell cell = iter.next();inputList.add(cell.getStringCellValue());}} catch (IOException e) {e.printStackTrace();}if (requiredList.stream().anyMatch(e -> !inputList.contains(e))|| inputList.stream().anyMatch(e -> !requiredList.contains(e))) {throw new RuntimeException("Excel表头不一致");}}/*** 设置返回的头部信息* @param response 返回流信息* @param fileName 文件名称*/public static void setResponse(HttpServletResponse response, String fileName){//设置头response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String excelFileName = null;try {excelFileName = URLEncoder.encode(fileName, String.valueOf(StandardCharsets.UTF_8)).replaceAll("\\+", "%20");} catch (UnsupportedEncodingException e) {e.printStackTrace();}response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");/*** attachment这个代表要下载的,如果去掉就直接打开了(attachment-作为附件下载,inline-在线打开)* excelFileName是文件名,另存为或者下载时,为默认的文件名*/response.setHeader("Content-disposition", "attachment;filename=" + excelFileName + ".xlsx");response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");}}

导入(读)数据的几个方式

无实体模板都数据

// 无模板读取数据,此处read的重载方法很多,这里用到的是输入流的方式List<Object> list = EasyExcel.read(file.getInputStream()).sheet(0).doReadSync();

通过实体模板的方式导入数据

// 有模板读取数据无监听器List<Object> doReadSync = EasyExcel.read(file.getInputStream(), User.class, null).sheet(0).doReadSync();

读取到对应的数据后通过序列化的方式转换为我们所使用到的对象列表

/通过序列化转换成对应的数据List<User> users = JSONUtil.toList(JSONUtil.toJsonStr(doReadSync), User.class);

通过监听器的方式读取数据

//通过监听器读取文件/*** headRowNumber:当读数据时, 0 -这个表没有头,因为第一行是数据 1 -该表有一个行头,这是默认的 2 -这张表有两行头,因为第三行是数据*/EasyExcel.read(file.getInputStream(), User.class, new UserListener()).headRowNumber(1).sheet().doRead();

监听器的类

package com.example.listener;import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import com.example.entity.User;import java.util.HashMap;import java.util.Map;/*** 这里监听器不要托管Spring* @Author user* @Date /5/6 14:42* @Description*/public class UserListener extends AnalysisEventListener<User> {Map<Integer, String> headMap = new HashMap<>();Map<Integer, User> userMap = new HashMap<>();public UserListener() {}/*** 这里可以获取到Excel对应的表头* @param headMap 表头* @param context*/@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {this.headMap = headMap;}/*** 这里会把解析到的每一行的数据在这里处理* 我这里用来获取了行号, 把每一行的数据放进map中* @param data 行数据* @param context*/@Overridepublic void invoke(User data, AnalysisContext context) {//获取当前行 || 这里也可以进行校验数据的空属性等问题Integer rowIndex = context.readRowHolder().getRowIndex() + 1;// 这里的话不需要行号的话可以放进list列表中userMap.put(rowIndex, data);}/*** 这里是把所有的数据解析完成后做的最后处理,我这里是用来校验入库。* @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {//校验表头checkHead();/*** 校验是否符合入库标准*/// 保存入库}public void checkHead(){String[] headList = {"姓名", "年龄", "性别", "生日", "备注"};for (int i = 0; i < headList.length; i++) {if (!headMap.get(i).equals(headList[i])) {throw new RuntimeException("Excel模板不匹配, 请核对模板表头", null);}}}}

推荐官网的监听器(可以进行分批读取和保存数据)监听器读数据 更专业清晰

导出数据的几个方式

无模板导出 (很简单)

实体类

package com.example.entity;import cn.hutool.core.date.DatePattern;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.format.DateTimeFormat;import lombok.Data;import java.util.Date;/*** @Author user* @Date /5/6 12:03* @Description*/@Datapublic class User {@ExcelProperty(value = "姓名",index = 0)private String name;@ExcelProperty(value = "年龄",index = 1)private Integer age;@ExcelProperty(value = "性别",index = 2)private String sex;@ExcelProperty(value = "生日",index = 3)@DateTimeFormat(value = DatePattern.NORM_DATE_PATTERN)private Date birthday;@ExcelProperty(value = "备注",index = 4)private String remark;}

List<User> userList = new ArrayList<>();//这里是初始化的数据,实际业务中是从数据库中查询出来的数据DataList.initializationUser(userList);ExcelUtil.setResponse(response, "测试用户数据导出");try {EasyExcelFactory.write(response.getOutputStream(), User.class).sheet("用户信息").doWrite(userList);} catch (IOException e) {e.printStackTrace();}

复杂的导出请参考官网

有模板导出

用到的实体

TotalTiWen

package com.example.entity.tiwen;import lombok.Data;/*** @Author user* @Date /5/6 13:40* @Description*/@Datapublic class TotalTiWen {private String a;private String b;private String c;private String d;private String e;private String f;private String g;private String h;}

TiWen

package com.example.entity.tiwen;import lombok.Data;/*** @Author user* @Date /5/6 13:40* @Description*/@Datapublic class TiWen {private String j;private String k;private String l;private String m;}

有模板导出步骤

获取模板 (自定义的模板)查询数据(从数据库查询的数据)写入Excel数据

第一步: 准备模板(读取模板文件) - 模板的格式 (注意列表数据是带点的)

//我把模板文件放到了resource下面了,所以读取resource下的模板文件 && 这里也可以是从服务器获取到的文件InputStream inputStream = ResourceUtil.getResourceObj("templates/tiwen.xlsx").getStream();

第二步:查询数据(我这里是初始化的数据)正常业务中是从数据库中查询出来的数据

//处理数据TotalTiWen tiWen = new TotalTiWen();List<TiWen> tiWenList = new ArrayList<>();//TODO 初始化数据,这里的数据,实际是从数据库中查询出来的DataList.initializationTiWen(tiWen, tiWenList);

public static void initializationTiWen(TotalTiWen totalTiWen, List<TiWen> tiWens){totalTiWen.setA("王小海");totalTiWen.setB("海克斯科技");totalTiWen.setC("15617223895");totalTiWen.setD("000023");totalTiWen.setE("20");totalTiWen.setF("MMOO99");totalTiWen.setG("34");totalTiWen.setH("测试机器");TiWen t = new TiWen();t.setJ("1");t.setK("-03-19");t.setL("103");t.setM("OOMM9923321312");TiWen t1 = new TiWen();t1.setJ("2");t1.setK("-06-19");t1.setL("552");t1.setM("OOMM99232312");TiWen t2 = new TiWen();t2.setJ("3");t2.setK("-10-30");t2.setL("423");t2.setM("OOMM99231123");TiWen t3 = new TiWen();t3.setJ("4");t3.setK("-12-24");t3.setL("674");t3.setM("OOMM99233");TiWen t4 = new TiWen();t4.setJ("5");t4.setK("-11-16");t4.setL("423423");t4.setM("OOMM99232");tiWens.add(t);tiWens.add(t1);tiWens.add(t2);tiWens.add(t3);tiWens.add(t4);}

第三步:设置response头部信息(这里是浏览器下载格式)下面用到的工具类在上面

ExcelUtil.setResponse(response, "文件名");

第四步:写入Excel

ServletOutputStream outputStream = null;try {outputStream = response.getOutputStream();} catch (IOException e) {e.printStackTrace();}//设置创建行的方式FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).build();//写入到sheetWriteSheet oneSheet = EasyExcel.writerSheet(0).build();//填充excelWriter.fill(tiWen, oneSheet);excelWriter.fill(tiWenList, fillConfig, oneSheet);

第五步:关闭对应的流

//关流excelWriter.finish();IOUtils.closeQuietly(inputStream);IOUtils.closeQuietly(outputStream);

多sheet导出 (替换上面第四步就行了)

多sheet导出其实和单个sheet一样,只不过是多写入了几次而已

sheet名称就是 打开excel的左下角名称(默认是sheet1 、sheet2、sheet3)

//设置创建行的方式FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLS).build();//创建第一个sheet 这里是根据sheet的名称写入数据WriteSheet oneSheet = EasyExcel.writerSheet("EXPORT BILL").build();/*** excelDto : 第一个sheet的头部* goodList :第一个sheet的列表数据*/excelWriter.fill(excelDto, oneSheet);excelWriter.fill(goodList, fillConfig, oneSheet);//创建第二个sheet 这里是根据sheet的名称写入数据WriteSheet twoSheet = EasyExcel.writerSheet("INV").build();/*** 第二个sheet* totalExcelDto: 第二个sheet的头部* informationList:第二个sheet的列表数据*/excelWriter.fill(informationList, fillConfig, twoSheet);excelWriter.fill(totalExcelDto, twoSheet);//创建第三个sheet 这里是根据sheet的名称写入数据WriteSheet thirdSheet = EasyExcel.writerSheet("PACKINGLIST").build();/*** 第三个sheet* listExcelDto: 第三个sheet的头部* infoExcelDtoList:第三个sheet的列表数据*/excelWriter.fill(infoExcelDtoList, fillConfig, thirdSheet);excelWriter.fill(listExcelDto, thirdSheet);// 下面就是关闭流了,同第五步

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。