热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

云e办(后端)——导入导出员工数据(EasyPoi注解使用)

云e办(后端)——导入导出员工数据(EasyPoi注解使用)在我们日常工作中经常需要导入和导出我们的员工数据,



云e办(后端)——导入导出员工数据(EasyPoi注解使用)

在我们日常工作中经常需要导入和导出我们的员工数据,所以本次我们完善此功能

在这里插入图片描述

一、EasyPoi注解使用


介绍:

poi :poi就是批量的操作文件或数据的导入以及导出 ,但是因为其使用起来需要过多的编辑代码,所以我们在此采用easypoi。

国内有很多开源项目对poi进行了封装,大大减少代码量,使其能够更简单的被我们使用并提高开发效率,例如EasyPoi,Excel4J,HuTools等优秀的开源项目。我们这次以EasyPoi为例

Easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法。

特点:

设计精巧,使用简单
接口丰富,扩展简单
默认值多,write less do more
AbstractView支持,web导出可以简单明了

二、导出员工数据前期准备


1、添加依赖


<dependency>
<groupId>cn.afterturngroupId>
<artifactId>easypoi-spring-boot-starterartifactId>
<version>4.1.3version>
dependency>

2、修改员工类

EasyPoi最大的特点是&#xff1a;可以通过注解定义导出的字段。

  • 普通属性&#xff1a;员工类使用注解&#64;Excel 定义了需要导出的属性&#xff0c; name 为导出的列名&#xff0c; width 可以定义列的宽度&#xff0c; format可以定义导入和导出的日期格式

  • 实体类对象作为属性&#xff1a;员工类中还有其他类作为属性&#xff0c;例如民族&#xff0c;政治面貌&#xff0c;职称&#xff0c;职位等。这些使用&#64;ExcelEntity 标记为实体类。
    并且在该实体类对象中加入注解 &#64;Excel即可。

修改pojo包下的Employee类
employee类是员工类:

/**
* &#64;Excel 注解的部分参数&#xff1a;
* name:导出到excel的列名
* width:是导入到excel时&#xff0c;表格的宽度
* suffix &#61; "年" 后缀&#xff0c;比如说工龄是1年
*/

---------------------- ----------------------
/**
* 民族、婚姻政治面貌、部门、职位等肯定不是导入导出id&#xff0c;而是导出对应的表中的名字
* 以民族为例子&#xff1a;
* 民族nation是一个对象&#xff0c;也是POJO类&#xff0c;那怎么定义实体类呢&#xff1f;
* 第一步&#xff1a;加入注解 &#64;ExcelEntity
* 第二部&#xff1a;修改POJO类 加入&#xff1a;&#64;Excel(name &#61; "民族")
*
* -- 那么会通过注解ExcelEntity表示是一个实体类&#xff0c;从而导入真实的数据
*
*/

&#64;ApiModelProperty(value &#61; "入职日期")
&#64;JsonFormat(pattern &#61; "yyyy-MM-dd",timezone &#61; "Asia/Shanghai")
&#64;Excel(name &#61; "入职日期",width &#61; 20, format &#61; "yyyy-MM-dd")
private LocalDate beginDate;
&#64;ApiModelProperty(value &#61; "在职状态")
&#64;Excel(name &#61; "在职状态")
private String workState;
&#64;ApiModelProperty(value &#61; "工号")
&#64;Excel(name &#61; "工号")
private String workID;
&#64;ApiModelProperty(value &#61; "合同期限")
&#64;Excel(name &#61; "合同期限",suffix &#61; "年")
private Double contractTerm;
/**
* 表中有很多外界id&#xff0c;都需要对应外界的表中。
* 表需要对应pojo的对象中
*/

&#64;ApiModelProperty(value &#61; "民族")
//在正常的员工表中是不存在的
&#64;TableField(exist&#61;false)
&#64;ExcelEntity(name &#61; "民族")
private Nation nation;


&#64;ApiModelProperty(value &#61; "政治面貌")
&#64;TableField(exist &#61; false)
&#64;ExcelEntity(name &#61; "政治面貌")
private PoliticsStatus politicsStatus;
&#64;ApiModelProperty(value &#61; "部门")
&#64;TableField(exist &#61; false)
&#64;ExcelEntity(name &#61; "部门")
private Department department;
&#64;ApiModelProperty(value &#61; "职称")
&#64;TableField(exist &#61; false)
&#64;ExcelEntity(name &#61; "职称")
private Joblevel joblevel;
&#64;ApiModelProperty(value &#61; "职位")
&#64;TableField(exist&#61; false)
&#64;ExcelEntity(name &#61; "职位")
private Position position;
&#64;ApiModelProperty(value &#61; "工资账套")
&#64;TableField(exist &#61; false)
private Salary salary;

再去修改nation类中的代码&#xff1a;

package com.xxxx.server.pojo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
&#64;Data
//of: 要重写的属性。 以name重写了Equals和hashcode。表示以name重写了equals/hashcode以及写完了
//当新建对象的时候&#xff0c;可以直接把name放进去&#xff0c;表示得到一个唯一的。&#xff1a;有参构造
&#64;RequiredArgsConstructor
&#64;NoArgsConstructor
&#64;EqualsAndHashCode(callSuper &#61; false,of &#61; "name")
&#64;Accessors(chain &#61; true)
&#64;TableName("t_nation")
&#64;ApiModel(value&#61;"Nation对象", description&#61;"")
public class Nation implements Serializable {
private static final long serialVersionUID &#61; 1L;
&#64;ApiModelProperty(value &#61; "id")
&#64;TableId(value &#61; "id", type &#61; IdType.AUTO)
private Integer id;
&#64;ApiModelProperty(value &#61; "民族")
&#64;Excel(name &#61; "民族")
//非空的&#xff0c;写新的有参构造时&#xff0c;name是必填的。
&#64;NonNull
private String name;
}

在这里插入图片描述

三、导出数据


controller


  • 获取员工的数据
  • 准备导出的参数&#xff08;表名、sheet名字、导出的excel类型&#xff09; 【ExportParams类准备参数】
  • 将数据导出&#xff08;导出的参数、实体类对象、导出的具体数据&#xff09;【ExcelExporUtil导出工具类】
  • 通过流的形式进行导出【Response】

//通过流的形式传出去&#xff1a;httpServletResponse response
// produces通过流形式传输&#xff0c;解决乱码
&#64;ApiOperation(value &#61; "导出员工数据")
&#64;GetMapping(value &#61; "/export",produces &#61; "application/octet-stream")
public void exportEmployee(HttpServletResponse response) throws UnsupportedEncodingException {
//获取当前员工的数据-具体的数据
List<Employee> list &#61; iEmployeeService.getEmployee(null);
/**
* 导出的参数&#xff1a;
* 导出员工的数据&#xff1a;&#xff08;文件名的名字&#xff0c;sheet表名&#xff0c;excel的版本&#xff09;
* excel &#xff1a;
* 03&#xff1a; HSSF &#xff0d; 提供读写Microsoft Excel XLS格式档案的功能。03打不开07
* 07&#xff1a; XSSF &#xff0d; 提供读写Microsoft Excel OOXML XLSX格式档案的功能。07能打开03
*
* 03的HSSF比07的XSSF优点&#xff1a;
* 1.速度快
* 2.兼容性好。03打不开07&#xff0c; 07能打开03
*/

ExportParams params &#61; new ExportParams("员工表","sheet员工表", ExcelType.HSSF);
/**
* ExcelExportUtil导出工具类&#xff1a;&#xff08;导出的参数、对象类名.class、具体的数据&#xff09;
* 返回的是Workbook。是poi的一个类。相当于工作簿&#xff08;工作簿就是一个Excel&#xff09;
*/

Workbook book &#61; ExcelExportUtil.exportExcel(params, Employee.class, list);
/**
* response。输出流形式 输出workboo
*
* 导出需要一些请求头的响应信息
* 防止中文乱码
*/

ServletOutputStream out &#61; null;
try{
//流形式&#xff0c;设置一个头
response.setHeader("content-type","application/octet-stream");
//防止中文乱码
response.setHeader("content-disposition","attachment;filename&#61;"&#43;
URLEncoder.encode("员工表.xls","UTF-8"));
out &#61; response.getOutputStream();
book.write(out);
}catch (Exception e){
e.printStackTrace();
}finally {
try{
out.flush();
out.close();
}catch (IOException e){
e.printStackTrace();
}
}
}

四、导入员工

导入时&#xff0c;因为在我们的excel表中所给出的民族name&#xff0c;政治面貌name等&#xff0c;但我们需要获取到对应的民族id&#xff0c;政治面貌id&#xff0c;职称id&#xff0c;职位id等。有两种方法

  • 根据name属性的值去数据库查询对应的id&#xff0c;显然在循环里面不断去查询数据库非常消耗性能&#xff0c;不推荐
  • 取巧&#xff1a;重写equals和hashCode方法&#xff0c;只要name属性的值一致就表示对象一致。前提是name属性的值基本不会变动。
    &#xff08;例如民族。民族、政治面貌都是固定不变的。那么name属性是唯一的&#xff0c;那么就能根据name属性能知道创建对象的对象是唯一的。对象是唯一的话&#xff0c;那么就可以拿到对象的id&#xff09;

我们选择第二种方法实现

1、导入准备&#xff1a;重写equals和hashCode方法

在这里插入图片描述

2、controller。

&#64;ApiOperation(value &#61; "导入员工数据")
&#64;PostMapping("/import")
public RespBean importEmployee(MultipartFile file){
//创建导入对象
ImportParams params &#61; new ImportParams();
//去掉标题第一行
params.setTitleRows(1);
/**
* 导入 流的形式、POJO对象类的字节码、数据--- 返回的是数据
*
* 导入完成后&#xff0c;pojo.Employee-nation是有值的
* pojo.nation拿到的就是name 是因为&#xff1a;
* Excel注解&#xff0c;ExcelEntiy注解&#xff1a;
* 能通过汉族名字获取到它是nation.ExcelEntiy就知道了是对象里面的&#xff0c;从而得到name
* 如何获得name的id呢&#xff1f;
*
* for循环
* 重写了hashcode方法&#xff0c;也准备了有参构造。
* 1.从excel导入的数据中&#xff0c;拿到了nation对象&#xff0c;对象里面有name&#xff0c;id是空的
* 2.查询所有的nationList,获取对象索引下标&#xff1a;重写了equals和hashcode&#xff0c;
* 通过name名字去nationList比较。能获取一样的对象.从而得到下标。
* 3.通过nationList.get(下标).getId() 获取完整的对象&#xff1a;有id&#xff0c;name\
* 4.在从id&#xff0c;name中获取id。 将id放入到employee中。
*
* if插入&#xff1a;saveBatch批量插入。 插入集合
*
*/

List<Nation> nationlList &#61; nationService.list();
List<PoliticsStatus> politicsStatusList &#61; politicsStatusService.list();
List<Department> departmentList &#61; departmentService.list();
List<Joblevel> joblevelList &#61; joblevelService.list();
List<Position> positionList &#61; positionService.list();
try{
List<Employee> list &#61; ExcelImportUtil.importExcel(file.getInputStream(), Employee.class, params);
list.forEach(employee -> {
//民族id
employee.setNationId(nationlList.get(nationlList.indexOf(
new Nation(employee.getNation().getName()))).getId());
//政治面貌id
employee.setPoliticId(politicsStatusList.get(politicsStatusList.indexOf(
new PoliticsStatus(employee.getPoliticsStatus().getName()))).getId());
//部门id
employee.setDepartmentId(departmentList.get(departmentList.indexOf(new
Department(employee.getDepartment().getName()))).getId());
//职称id
employee.setJobLevelId(joblevelList.get(joblevelList.indexOf(new
Joblevel(employee.getJoblevel().getName()))).getId());
//职位id
employee.setPosId(positionList.get(positionList.indexOf(new
Position(employee.getPosition().getName()))).getId());
});
if (iEmployeeService.saveBatch(list)){
return RespBean.success("导入成功!");
}
return RespBean.error("导入失败!");
} catch (Exception e){
e.printStackTrace();
}
return RespBean.error("导入失败!");
}






推荐阅读
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • 面向对象之3:封装的总结及实现方法
    本文总结了面向对象中封装的概念和好处,以及在Java中如何实现封装。封装是将过程和数据用一个外壳隐藏起来,只能通过提供的接口进行访问。适当的封装可以提高程序的理解性和维护性,增强程序的安全性。在Java中,封装可以通过将属性私有化并使用权限修饰符来实现,同时可以通过方法来访问属性并加入限制条件。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
author-avatar
倾听雨2502862143
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有