超简洁!利用easyExcel导出导入Excel

​ 深夜,在东莞,7天酒店,打开电脑,访问国内最大的同性交友网站。

​        日常开发中,导出导入场景非常多,尤其是对于后台管理更是一个列表一个导出,如果从导出的业务中抽离出复用代码,专注于逻辑开发,对于开发者而言非常重要。前有使用POI,但作者还是更喜EasyExcel的简洁高效不拖沓,所以特意写篇文章记录下。

# 准备工作

​        准备工作是看文档了解EasyExcel吗?不,我们直接上手吧!我发现最近的业务里面,最简单的例子已经应付下来了!所以准备工作自然只需导入EasyExcel的jar包,这里我们由于是springboot项目,所以直接使用maven。直接上最新的版本了!pom.xml给它加上:

```java

<dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>easyexcel</artifactId>

            <version>2.2.5</version>

</dependency>

```

# 导出

​        准备工作已经完成,导出开始,首先需要一个Bean类,导出的字段和Excel文件的字段一样即可。@Data是用了lombok,@ExcelProperty则包含了Excel首行的名称和字段所在位置,从0开始,不能重复。

```java

@Data

public class ExportVo {


  @ExcelProperty(value = "名称", index = 0)

  private String name;

  @ExcelProperty(value = "时间", index = 1)

  private Date time;


  @NumberFormat("#.##%")

  @ExcelProperty(value = "完成率", index = 2)

  private Float rate;


}

```

​        接下来是逻辑实现:

```java

  @PostMapping("/export")

  public void export(@RequestBody ExportDto dto, HttpServletResponse response)

          throws IOException {

    String fileName = "统计表";

    ExcelUtil.download(response, fileName, ExportVo.class,

            getExportVoList());

  }

  private List getExportVoList() {

    //  这里主要是获取List<ExportVo>内容,不提供实现了,需要说下注意点。

      1、导出列表应该有时间之类的限制(例如最近一个月),避免导出Excel过大,过大Excel一般采用分sheet导出(尤其xls文件,有65535条数限制)、分文件打包导出,上传文件服务器异步导出,不可突破的最大导出(限死5w条)。

      2、一来考虑数据库查询和内存压力,二来分页插件可能存在最大页数限制,所以较多条数时必须做分页查询,再组合List对象。

      3、一般从数据库直接查出数据不满足导出字段需要,有必要时需要做字段转换。

  }

```

​      导出的处理类:

```java

public class ExcelUtil {

  public static void download(HttpServletResponse response, String fileName,

                              Class cls, List dataList)

          throws IOException {

    response.setContentType("application/vnd.ms-excel");

    response.setCharacterEncoding("utf-8");

    String fname = URLEncoder.encode(fileName, "utf-8");

    response.setHeader("Content-disposition",

            "attachment;filename=" + fname + ExcelTypeEnum.XLSX.getValue());

    LongestMatchColumnWidthStyleStrategy longestMatchColumnWidthStyleStrategy =

            new LongestMatchColumnWidthStyleStrategy();

    EasyExcel.write(response.getOutputStream(), cls)

            .sheet("sheet1")

            .registerWriteHandler(longestMatchColumnWidthStyleStrategy)

            .doWrite(dataList);

    response.flushBuffer();

  }

```

​        启动程序,使用postman试下,直接点Send的话会返回一堆乱码,选择Send and Download则可导出Excel,不过文件名是URL编码过的,这个文件名编码问题在浏览器则不会存在。

![image-20200702002721411](C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20200702002721411.png)

# 导入

​        导入是为了减少人工录入大量数据的烦恼,挺好的。

```java

  @Autowired

  private ImportService importService;

  @PostMapping("/import")

  public void import(

          @RequestParam(value = "file") MultipartFile file,

          @Min(1) @RequestParam("type") int type

  ) throws IOException {

    ImportQueryDto dto = new ImportQueryDto();

    dto.setType(type);

    // ImportDto是导入对应类,UploadDataListener是处理类,逻辑处理服务需要以参数形式传入

    EasyExcel.read(file.getInputStream(), ImportDto.class,

            new UploadDataListener(importService)).sheet().doRead();

  }

```

​    导入Excel对应类,ExcelProperty对应导入字段的首部。

```java

@Data

public class ImportDto {

  @ExcelProperty("名称")

  private String name;

  @ExcelProperty("数量")

  private Integer num;

}

```

​      导入处理:

```java

public class UploadDataListener

        extends AnalysisEventListener<ImportDto> {

  //  一次导入多少便入库,避免大量入库

  private static final int BATCH_COUNT = 50;

  //  存放导入列表

  List<ImportDto> list = new ArrayList<>();

  private ImportService importService;

  public UploadDataListener(ImportService importService) {

    this.importService = importService;

  }

  @Override

  public void invoke(ImportDto importDto, AnalysisContext analysisContext) {

    list.add(importDto);

    if (list.size() >= BATCH_COUNT) {

      saveData();

      list.clear();

    }

  }

  @Override

  public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    saveData();

  }

  private void saveData() {

    List<ImportModel> importModelList = new ArrayList<>();

    for (ImportDto dto : list) {

      ImportModel model = new ImportModel();

      model.setName(dto.getName());

      model.setNum(dto.getNum())

      importModelList.add(model);

    }

    importService.saveBatch(importModelList);

  }

}

```

​        实际上,导入文件的内容是需要校验的,数据格式校验等,需要询问产品是否忽略错误的数据,只导入正常的数据,然后怎么友好提示错误的内容,通过返回一个包含错误信息Excel或提示框,更进一步的提示,则是提示到哪一个格子有问题。

​      睡觉。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339