0


springboot集成easypoi实现excel导入导出

前言

文章通过springboot集成easypoi实现基础的excel导入和导出

1.maven依赖和工具类

(1)集成maven依赖

<dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version><exclusions><exclusion><artifactId>hutool-all</artifactId><groupId>cn.hutool</groupId></exclusion><exclusion><artifactId>poi</artifactId><groupId>org.apache.poi</groupId></exclusion><exclusion><artifactId>poi-ooxml</artifactId><groupId>org.apache.poi</groupId></exclusion><exclusion><artifactId>poi-ooxml-schemas</artifactId><groupId>org.apache.poi</groupId></exclusion></exclusions></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency>

(2)封装工具类

根据项目业务需要封装的工具类:

@Slf4jpublicclassExcelUtil{/**
     * 通过Excel获取数据集
     * @param fileName
     * @param pojoClass
     * @return
     */publicstatic<T>List<T>getDataList(String fileName,Class<T> pojoClass)throwsFileNotFoundException{FileUtils fileUtils =FileUtils.getInstance();File file =newFile(fileUtils.getResourcePath()+"/temp/"+ fileName);if(!file.exists()){thrownewRRException("文件不存在");}FileInputStream fileInputStream =newFileInputStream(file);List<T> list =importExcel(fileInputStream,0,1, pojoClass);returnCollUtil.emptyIfNull(list);}/**
     *
     * @param file excel文件
     * @param pojoClass
     * @param <T>
     * @return
     * @throws FileNotFoundException
     */publicstatic<T>List<T>getDataList(File file,Class<T> pojoClass)throwsFileNotFoundException{if(!file.exists()){thrownewRRException("文件不存在");}FileInputStream fileInputStream =newFileInputStream(file);List<T> list =importExcel(fileInputStream,0,1, pojoClass);returnCollUtil.emptyIfNull(list);}publicstatic<T>List<T>importExcel(InputStream inputStream,Integer titleRows,Integer headerRows,Class<T> pojoClass){ImportParams params =newImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);List<T> list =null;try{
            list =ExcelImportUtil.importExcel(inputStream, pojoClass, params);}catch(NoSuchElementException e){thrownewRRException("系统导入Excel异常");}catch(Exception e){
            log.info("导入异常 -> {}", e.getMessage());thrownewRRException("系统导入Excel异常");}return list;}/**
     * 原生poi导出 - 用poi自带的工具类来处理合并后的边框
     * @param border
     * @param region
     * @param sheet
     */publicstaticvoidsetBorderStyle(BorderStyle border,CellRangeAddress region,HSSFSheet sheet){RegionUtil.setBorderBottom(border,region, sheet);RegionUtil.setBorderLeft(border,region, sheet);RegionUtil.setBorderRight(border,region, sheet);RegionUtil.setBorderTop(border,region, sheet);}/**
     * 原生poi导出 - 设置合并后的单元格样式
     * @param sheet
     * @param region
     * @param cs
     */publicstaticvoidsetRegionStyle(XSSFSheet sheet,CellRangeAddress region,XSSFCellStyle cs){for(int i = region.getFirstRow(); i <= region.getLastRow(); i++){XSSFRow row = sheet.getRow(i);if(row ==null){
                row = sheet.createRow(i);}for(int j = region.getFirstColumn(); j <= region.getLastColumn(); j++){XSSFCell cell = row.getCell(j);if(cell ==null){
                    cell = row.createCell(j);}
                cell.setCellStyle(cs);}}}}

2. excel的导入

这里介绍基础的一行为一个数据的导入,不存在一对多关系间的导入.
excel如下图:
在这里插入图片描述
这里没有标题,但是有表头(id,学校),所以适用工具类中的导入:

// 0表示标题占0行,1表示表头占1行,这里也可以根据自己业务需要修改或者当做一个参数传入List<T> list =importExcel(fileInputStream,0,1, pojoClass);

excel对应实体类封装

@Data@ApiModel("excel数据")publicclassExcelData{@Excel(name ="id")privateString id;@Excel(name ="学校")@ApiModelProperty("学校")privateString school;}

Excel导入时就调用上面的工具类进行导入,根据@Excel注解中的name属性值,作数据字段映射。

3. excel导出

(1)基础导出

导出成上面截图中的excel形式,这里也是使用的注解方式导出。

privatestaticvoiddefaultExport(List<ExcelData> list,String fileName,HttpServletResponse response){Workbook workbook =ExcelExportUtil.exportExcel(list,ExcelType.HSSF);try{
        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type","application/vnd.ms-excel");
        response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        workbook.write(response.getOutputStream());}catch(IOException e){//throw new NormalException(e.getMessage());}}

(2)注解导出

基于前面(1)中提到的注解方式导出,这里使用注解导出一对多的excel。
对应的实体类和注解,多级使用@ExcelCollection注解,同时其他层级使用needMerge = true表示需要合并单元格。

@Data@ApiModel("excel数据")@BuilderpublicclassExcelData{@Excel(name ="id", needMerge =true)privateString id;@Excel(name ="学校", needMerge =true)@ApiModelProperty("学校")privateString school;@ExcelCollection(name ="年级集合")@ApiModelProperty("年级")privateList<Grade> gradeList;@Data@ApiModel("年级")@BuilderpublicstaticclassGrade{@Excel(name ="年级")privateString name;}}

导出代码:

publicResultexport(){// 准备数据List<ExcelData> list =newArrayList<>();List<ExcelData.Grade> gradeList =newArrayList<>();
        gradeList.add(ExcelData.Grade.builder().name("高三年级").build());
        gradeList.add(ExcelData.Grade.builder().name("高二年级").build());
        list.add(ExcelData.builder().id("1").school("大竹中学").gradeList(gradeList).build());String headTitle ="学校";ExportParams params =newExportParams(headTitle,"sheet1",ExcelType.XSSF);Workbook workbook =ExcelExportUtil.exportExcel(params,ExcelData.class, list);FileOutputStream fos =null;try{
            fos =newFileOutputStream("D:\\study\\"+"test.xlsx");
            workbook.write(fos);}catch(FileNotFoundException e){
            e.printStackTrace();}catch(IOException e){
            e.printStackTrace();}finally{try{if(fos !=null){
                    fos.close();}}catch(IOException e){
                e.printStackTrace();}}returnResult.success();}

导出效果如下图:
在这里插入图片描述
这里可以设置一些样式,例如表头黑色背景色,表格黑色线条等样式:

params.setStyle(style);// 这里的style可以百度,有很多的

(3)模板导出

有些表头比较复杂,使用注解导出不能导出成我们想要的样子,这里就可以使用模板导出,为Excel制定一些样式模板,然后使用easypoi提供的语法,实现模板导出。
这里介绍基础的模板语法,更多的可以查看官方文档:easypoi教程V1.0

a.首先制定模板

在这里插入图片描述

b.封装实体类
@Data@ApiModel("excel数据")@BuilderpublicclassExcelData{@Excel(name ="id", needMerge =true)privateString id;@Excel(name ="学校", needMerge =true)@ApiModelProperty("学校")privateString school;@ExcelCollection(name ="年级集合")@ApiModelProperty("年级")privateList<Grade> gradeList;@ApiModelProperty("管理者")privateString manager;@Data@ApiModel("年级")@BuilderpublicstaticclassGrade{@Excel(name ="年级")privateString name;@ApiModelProperty("所属")privateString part;}}
c.导出代码
publicvoidexcelTemplate(){TemplateExportParams params =newTemplateExportParams("E:\\study-java\\template.xlsx");// 封装数据Map<String,Object> data =newHashMap<>();List<ExcelData> list =newArrayList<>();List<ExcelData.Grade> gradeList =newArrayList<>();
        gradeList.add(ExcelData.Grade.builder().name("高三年级").part("高中部").build());
        gradeList.add(ExcelData.Grade.builder().name("初三年级").part("初中部").build());
        list.add(ExcelData.builder().id("1").school("大竹中学").gradeList(gradeList).manager("xxx").build());
        list.add(ExcelData.builder().id("2").school("大竹二中").gradeList(gradeList).manager("ooo").build());
        data.put("list", list);
        data.put("area","大竹县");Workbook workbook =ExcelExportUtil.exportExcel(params, data);FileOutputStream fos =null;try{
            fos =newFileOutputStream("E:\\study-java\\"+"testTemplate.xlsx");
            workbook.write(fos);System.out.println("导出成功");}catch(FileNotFoundException e){
            e.printStackTrace();}catch(IOException e){
            e.printStackTrace();}finally{try{if(fos !=null){
                    fos.close();}}catch(IOException e){
                e.printStackTrace();}}}
d.导出效果图

在这里插入图片描述这里看到有部分线条缺失,这里是easypoi自身的bug。

(4)导出带图片的excel

有时会遇到导出的excel需要有图片的需求,最简单的方式就是用注解导出,在注解设置对应的属性值,这里可以参考官方文档去查看注解属性值怎么设置。
当图片导出遇到复杂表头导出时,这里可以选择模板导出的方式,但是图片需要特殊处理。
这里先给出官方文档写出的图片处理代码:

@Testpublicvoidone()throwsException{TemplateExportParams params =newTemplateExportParams("doc/exportTemp_image.xls",true);Map<String,Object> map =newHashMap<String,Object>();// sheet 2
     map.put("month",10);Map<String,Object> temp;for(int i =1; i <8; i++){
         temp =newHashMap<String,Object>();
         temp.put("per", i *10);
         temp.put("mon", i *1000);
         temp.put("summon", i *10000);ImageEntity image =newImageEntity();
         image.setHeight(200);
         image.setWidth(500);
         image.setUrl("imgs/company/baidu.png");
         temp.put("image", image);
         map.put("i"+ i, temp);}Workbook book =ExcelExportUtil.exportExcel(params, map);File savefile =newFile("D:/excel/");if(!savefile.exists()){
         savefile.mkdirs();}FileOutputStream fos =newFileOutputStream("D:/excel/exportTemp_image.xls");
     book.write(fos);
     fos.close();}

通过官方文档描述和 代码可以看到图片处理为ImageEntity,然后放到数据集map中,在模板对应的取值模板去赋值图片,但是我这想要每一行数据有个图片,用这种方式实现不了,我就将ImageEntity 放到我的对象中,作为属性尝试,这样尝试发现导出是没有图片的,我就想到对导出的excel再次进行处理,添加图片到excel中,使用这种方式,注意设置图片的大小适应,避免超出理想范围。
使用easypoi导出excel后得到一个workbook,通过workbook获取对应sheet,对sheet中的指定单元格做图片插入操作,代码如下:

/**
     * 插入图片到excel
     *  设置图片覆盖范围,不设置图片大小适应
     * @param sheet
     * @param imagePath 图片路径
     * @param startRow 图片起始行,从0开始
     * @param startCol 图片起始列,从0开始
     * @param endRow 图片结束行,从0开始
     * @param endCol 图片结束列,从0开始
     * @throws IOException
     */publicstaticvoidinsertImage(Sheet sheet,String imagePath,int startRow,int startCol,int endRow,int endCol)throwsIOException{File file =newFile(imagePath);if(!file.exists()){
            log.info("文件没找到 path -> {}", imagePath);return;}FileInputStream fis =newFileInputStream(imagePath);byte[] imageBytes =IOUtils.toByteArray(fis);
        fis.close();int pictureIdx = sheet.getWorkbook().addPicture(imageBytes,Workbook.PICTURE_TYPE_JPEG);CreationHelper helper = sheet.getWorkbook().getCreationHelper();Drawing<?> drawing = sheet.createDrawingPatriarch();ClientAnchor anchor = helper.createClientAnchor();// 设置图片的位置和大小
        anchor.setCol1(startCol);
        anchor.setRow1(startRow);
        anchor.setCol2(endCol);
        anchor.setRow2(endRow);// 创建图片并插入到单元格中Picture picture = drawing.createPicture(anchor, pictureIdx);
        picture.resize();}/**
     * 插入到指定单元格,并适应单元格大小
     * @param sheet
     * @param imagePath
     * @param row
     * @param col
     * @throws IOException
     */publicstaticvoidinsertImageAndFitToCell(Sheet sheet,String imagePath,int row,int col)throwsIOException{File file =newFile(imagePath);if(!file.exists()){
            log.info("文件没找到 path -> {}", imagePath);return;}FileInputStream fis =newFileInputStream(imagePath);byte[] imageBytes =IOUtils.toByteArray(fis);
        fis.close();int pictureIdx = sheet.getWorkbook().addPicture(imageBytes,Workbook.PICTURE_TYPE_JPEG);CreationHelper helper = sheet.getWorkbook().getCreationHelper();Drawing<?> drawing = sheet.createDrawingPatriarch();ClientAnchor anchor = helper.createClientAnchor();// 设置图片的位置和大小
        anchor.setCol1(col);
        anchor.setRow1(row);// 创建图片并插入到单元格中Picture picture = drawing.createPicture(anchor, pictureIdx);// 调整图片大小,以适应单元格
        picture.resize(1.0,1.0);}

(5)easypoi缺陷

使用easypoi工具导出,无论是注解还是模板导出方式,都不支持表格过于复杂的导出,去年做项目遇到的Excel导出,包含三四层数据,表头也比较复杂,还有很多样式,使用注解和模板导出到第三层数据的时候,整个表格就乱掉了,当时因为催得急,也没去试试阿里的EasyExcel能不能解决,后来用原生poi写的导出,有大佬知道这种怎么解决的可以评论区分享分享

标签: spring boot excel java

本文转载自: https://blog.csdn.net/qq_50867577/article/details/130080140
版权归原作者 SingleCase 所有, 如有侵权,请联系我们删除。

“springboot集成easypoi实现excel导入导出”的评论:

还没有评论