EasyExcel——Excel读写工具

EasyExcel——Excel读写工具

  • Excel 读写
    • 1.1 EasyExcel
      • 1.1.1 依赖
      • 1.1.2 实体对象
      • 1.1.3 解析数据的监听器类(读)
      • 1.1.4 测试类(读)
      • 1.1.5 测试类(写)
      • 1.1.6 EasyExcel 工具类(读)
      • 1.1.7 自定义转换器(拓展)
        • 1.1.7.1 自定义转换器的使用
    • 2.2 POI
      • 2.2.1 依赖
      • 2.2.2 导出Excel,填充数据

Excel 读写

1.1 EasyExcel

搬运参考地址:庄家钜(语雀)

1.1.1 依赖

<dependency><groupId>com.alibabagroupId><artifactId>easyexcelartifactId><version>3.0.5version>
dependency>

1.1.2 实体对象

/*** @Description 实体类对象**/
public class Employee {//不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配//强制读取第1个 @ExcelProperty(index = 0)private Integer eid;//用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据@ExcelProperty("姓名")private String ename;@ExcelProperty("性别")private String esex;@ExcelProperty("年龄")private Integer eage;@ExcelProperty("工资")private Double esalary;//省略 get、set、构造 方法
}

1.1.3 解析数据的监听器类(读)

/*** @Description 解析数据的监听器类ExcelReadListener* @Date 2021-11-23 9:48** ReadListener : 监听读取结果的接口**/
@Component
public class ExcelReadListener implements ReadListener<Employee> {//slf4j 日志private Logger log = LoggerFactory.getLogger(ExcelReadListener.class);//解析的行数private Integer analysisCount = 0;/*** 分析一行时触发调用函数。(即每行数据解析的时候都会触发该方法)* @param employee* @param analysisContext 上下文是 Excel 阅读器的主要定位点。*/@Overridepublic void invoke(Employee employee, AnalysisContext analysisContext) {log.info("解析到一条数据:{}", JSON.toJSONString(employee));analysisCount++;}/*** 所有数据解析完后调用该方法* @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info("共解析数据:{}",analysisCount);}
}

1.1.4 测试类(读)

@SpringBootTest
public class EasyExcelTest {/*** 步骤:* 1.创建Excel对应的实体对象* 2.创建excel一行一行的回调监听器(默认一行行的读取excel)* 3.直接读取*/@Testvoid readExcelTet(){String fileName = "E:\\Desktop\\tempFile" + File.separator + "员工信息表.xls";/*** fileName : 要读取的文件路径* Employee.class : 注释配置信息的类(用这个类取读)* ExcelReadListener : 读取侦听器(这里自己实现了ReadListener接口)* sheet() : 默认读取第一个sheet(可以自己指定读取第几个sheet)* doRead() : 解析指定的sheet,SheetNo从0开始。完成整个读取文件。释放缓存并关闭流。*/EasyExcel.read(fileName, Employee.class, new ExcelReadListener()).sheet().doRead();}}

读取结果测试:
在这里插入图片描述

1.1.5 测试类(写)

单sheet写入:

	//写入到Excel文件的一个Sheet中@Testpublic void writeToExcel() {String filePath = "E:\\Desktop\\tempFile\\员工信息表(写入测试).xls";List<Employee> list=new ArrayList<>();list.add(new Employee(1,"Jack","男",26,8500.0));list.add(new Employee(2,"Rose","女",24,8600.5));/*** 1.建立 excel 写入*      pathName - 要写入的文件路径*      head – 注释类以获取配置信息* 2.将数据写入工作表*/EasyExcel.write(filePath,Employee.class).sheet().doWrite(list);}

写入效果测试:
在这里插入图片描述
多sheet写入:

	//写入到Excel文件多个Sheet中@Testpublic void writeToExcel2() {String filePath = "E:\\Desktop\\tempFile\\员工信息表(多个sheet写入测试).xls";//将每个sheet的数据写入一个集合中,多个sheet对应多个集合List<Dept> list1 = new ArrayList<>();list1.add(new Dept(1, "研发部"));list1.add(new Dept(2, "销售部"));List<Employee> list2 = new ArrayList<>();list2.add(new Employee(1, "Jack", "男", 26, 8500.0));list2.add(new Employee(2, "Rose", "女", 24, 8600.5));//Excel Writer 此工具用于通过 POI 将值写入 ExcelExcelWriter excelWriter = EasyExcel.write(filePath).build();//写单WriteSheet sheet1 = EasyExcel.writerSheet(0, "部门表").head(Dept.class).build();excelWriter.write(list1, sheet1); //将数据写入工作表//写单WriteSheet sheet2 = EasyExcel.writerSheet(1, "员工表").head(Employee.class).build();excelWriter.write(list2, sheet2); //将数据写入工作表//finish()调用,关闭 IO;保证文件不损坏excelWriter.finish();}

在这里插入图片描述
在这里插入图片描述

1.1.6 EasyExcel 工具类(读)

/*** EasyExcel 工具类*/
public class EasyExcelUtil{/*** 读取Excel操作* @return 包含Excel数据的list集合*/public static <T> List<T> readFromExcel(InputStream stream, Class<T> tClass, int sheetNo) {//slf4j 日志Logger log = LoggerFactory.getLogger(EasyExcelUtil.class);//解析的行数final Integer[] analysisCount = {0};List<T> list = new ArrayList<>();EasyExcel.read(stream)//反射获取类型.head(tClass)//读取的excel的sheet索引.sheet(sheetNo)//注册监听器.registerReadListener(new AnalysisEventListener<T>() {@Overridepublic void invoke(T t, AnalysisContext analysisContext) {log.info("解析到一条数据:{}", JSON.toJSONString(t));list.add(t);analysisCount[0]++;}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info("读取数据完毕,共解析数据:{}",analysisCount[0]);}}).doRead();return list;}/*** 将数据写入Excel* @param response http响应* @param clazz 使用的目标对象* @param fileName 下载时文件的名字* @param sheetName 写入到文件时对应的sheet的名称* @param dataList 要写入的数据的集合*/public static void writeToExcel(HttpServletResponse response,Class clazz,String fileName,String sheetName,List dataList){try {//处理浏览器下载/导出文件时中文错误显示问题fileName = new String(fileName.getBytes(),"ISO-8859-1");} catch (UnsupportedEncodingException e) {e.printStackTrace();}ServletOutputStream outputStream = null;//设置响应内容类型(内容类型可以和编码一起设置)response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");//设置响应头(inline :将文件内容直接显示在页面;attachment:弹出对话框让用户下载)response.setHeader("Content-Disposition","attachment;fileName="+fileName+".xlsx");try {outputStream = response.getOutputStream();EasyExcel.write(outputStream,clazz).registerConverter(new LocalDateConverter()).sheet(sheetName).doWrite(dataList);} catch (IOException e) {e.printStackTrace();} finally {if (null != outputStream){try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}}}

1.1.7 自定义转换器(拓展)

EasyExcel默认不支持LocalDate类型,即不能把该类型数据写入到Excel的Cell中,此时要定义一个转换器;

/*** @Description EasyExcel支持LocalDate类型的转换器(自定义,EasyExcel中没有LocalDate相应的转换器)* @Author cb* @Date 2021-12-28 16:54**/
public class LocalDateConverter implements Converter<LocalDate> {//日期的格式化字符串private final String  dateFormatStr="yyyy-MM-dd";//回到 Java 中的对象类型@Overridepublic Class<?> supportJavaTypeKey() {return LocalDate.class;}//回到excel中的数据类型@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 把Excel单元格数据转换为LocalDate类型* @param cellData Excel单元格中的数据* @param contentProperty* @param globalConfiguration* @return* @throws Exception*/@Overridepublic LocalDate convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {LocalDate localDate = LocalDate.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern(dateFormatStr));return localDate;}/*** 向Excel对象中写入string类型的数据* @param localDate* @param contentProperty* @param globalConfiguration* @return* @throws Exception*/@Overridepublic WriteCellData<?> convertToExcelData(LocalDate localDate, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {WriteCellData<?> writeCellData = new WriteCellData<>(localDate.format(DateTimeFormatter.ofPattern(dateFormatStr)));return writeCellData;}
}
1.1.7.1 自定义转换器的使用

方法1: 在导出数据的pojo类的LocalDate属性上多配置一个converter属性;

@ExcelProperty(value = "出生日期",converter = LocalDateConverter.class)
private LocalDate birthday;

方法2:直接在EasyExcel写入数据方法上去注册转换器;

EasyExcel.write(pathName,Student.class).registerConverter(new LocalDateConverter()).sheet("学生信息表").doWrite(studetnList);

2.2 POI

2.2.1 依赖

EasyExcel 的依赖依赖于POI的依赖。使用上面EasyExcel的依赖即可。

2.2.2 导出Excel,填充数据

/*** 导出Excel文件,该文件中需要填充运营数据* @param response* @return*/
@GetMapping("exportBusinessReport")
public Result exportBusinessReportExcel(HttpServletResponse response) throws Exception{try {//获取运营数据Map<String, Object> map = reportService.getBusinessReport();//获取到Excel模板文件的路径ClassPathResource classPathResource = new ClassPathResource("templates/report_template.xlsx");InputStream inputStream = classPathResource.getInputStream();//创建一个代表Exel文件(WorkBook)的对象XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);//获取到第1个表格XSSFSheet sheet = xssfWorkbook.getSheetAt(0);//获取表格里的行XSSFRow row = sheet.getRow(2);//设置行中第6列的值row.getCell(5).setCellValue(map.get("reportDate").toString());row = sheet.getRow(4);row.getCell(5).setCellValue(Integer.valueOf(map.get("todayNewMember").toString()));//今日会员数row.getCell(7).setCellValue(Integer.valueOf(map.get("totalMember").toString()));//总会员数row = sheet.getRow(5);row.getCell(5).setCellValue(Integer.valueOf(map.get("thisWeekNewMember").toString()));//本周新增会员数row.getCell(7).setCellValue(Integer.valueOf(map.get("thisMonthNewMember").toString()));//本月新增会员数row = sheet.getRow(7);row.getCell(5).setCellValue(Integer.valueOf(map.get("todayOrderNumber").toString()));//今日预约数row.getCell(7).setCellValue(Integer.valueOf(map.get("todayVisitsNumber").toString()));//今日到诊数row = sheet.getRow(8);row.getCell(5).setCellValue(Integer.valueOf(map.get("thisWeekOrderNumber").toString()));//本周预约数row.getCell(7).setCellValue(Integer.valueOf(map.get("thisWeekVisitsNumber").toString()));//本周到诊数row = sheet.getRow(9);row.getCell(5).setCellValue(Integer.valueOf(map.get("thisMonthOrderNumber").toString()));//本月预约数row.getCell(7).setCellValue(Integer.valueOf(map.get("thisMonthVisitsNumber").toString()));//本月到诊数//热门套餐List<Map<String, Object>> hotmeals = (List<Map<String, Object>>) map.get("hotSetmeal");int rowIndex = 12;for (Map<String, Object> hotmeal : hotmeals) {row = sheet.getRow(rowIndex);row.getCell(4).setCellValue(String.valueOf(hotmeal.get("name")));row.getCell(5).setCellValue(Integer.valueOf(hotmeal.get("setmeal_count").toString()));row.getCell(6).setCellValue(Double.valueOf(hotmeal.get("proportion").toString()));rowIndex++;//注意填充数据的开始行}//获取到输出流ServletOutputStream outputStream = response.getOutputStream();//设置浏览器能解析的内容类型response.setContentType("application/vnd.ms-excel");//设置响应头response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode("运营数据报表.xlsx", "UTF-8"));//向输出流中写入Excel文件xssfWorkbook.write(outputStream);//清理资源outputStream.flush();outputStream.close();xssfWorkbook.close();return null; //response提交过后不能在返回消息,否则会报错} catch (Exception e) {e.printStackTrace();return new Result(false, "导出运营数据失败");}
}

导出的效果图
在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部