前后端分离微服务管理系统项目实战SaaS-HRM项目(七)——POI报表入门

七、POI报表

1、服务统一管理

<1>、服务发现组件Eureka

Eureka是Netflix开发的服务发现框架,SpringCloud将它集成在自己的子项目spring-cloud-netfix中,实现SpringCloud的服务发现功能。Eureka包含两个组件:Eureka Server和Eureka Client

  • Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
  • Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就别一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动之后,将会向Eureka Server发送心跳,默认周期是30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)
(1)、Eureka服务端

1、在父工程中引入SpringCloud相关依赖,指定其版本

	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2、创建ihrm_eureka模块导入相关依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

3、在resources目录下创建application.yml添加Eureka服务的相关配置

#eureka服务的配置文件
server:
  port: 6868 #服务端口
eureka:
  client:
    registerWithEureka: false #是否将自己注册到Eureka服务中,本身就是所有无需注册
    fetchRegistry: false #是否从Eureka中获取注册信息
    serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址
      defaultZone: http://127.0.0.1:${server.port}/eureka/

4、创建Eureka服务端的启动类

package com.ihrm.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * eureka服务端的启动类
 */
@SpringBootApplication
@EnableEurekaServer //开启eureka服务端配置
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class,args);
    }
}
(2)、微服务注册

1、在企业微服务、员工微服务和系统微服务的pom中添加依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2、在application,yml中添加eureka的服务地址

#注册到eureka的服务地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:6868/eureka/

3、在微服务的启动类中添加如下注解即可:

@EnableEurekaClient
<2>、微服务调用组件Feign
(1)、简介

Feign是简化java HTTP客户端开发的工具(java-to-httpclient-binder),灵感来自Retrofit、JAXRS-2.0和WebSocket。Feign初衷是降低统一绑定Denominator到HTTP API的复杂度,不区分是否为restful

(2)、操作

1、在系统微服务的pom中引入Feign的相关依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2、修改ihrm-system启动类,添加注解

@EnableDiscoveryClient
@EnableFeignClients

3、创建DepartmentFeignClient接口

package com.ihrm.system.client;

import com.ihrm.common.entity.Result;
import com.ihrm.domain.company.Department;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 声明接口,通过feign调用其他微服务
 */
//声明调用的微服务名称
@FeignClient("ihrm-company")
public interface DepartmentFeignClient {

    /**
     * 调用微服务的接口
     */
    @RequestMapping(value="/company/department/{id}",method = RequestMethod.GET)
    Result findById(@PathVariable(value="id") String id);

4、修改ihrm-system的UserController

	/**
     * 测试Feign组件
     * 调用系统微服务的/test接口传递部门id,通过feign调用部门微服务获取部门信息
     */
    @RequestMapping(value = "/test/{id}", method = RequestMethod.GET)
    public Result testFeign(@PathVariable(value = "id") String id) {
        Result result = departmentFeignClient.findById(id);
        return result;
    }

5、在ihrm_common模块中配置Feign拦截器添加请求头
Feign拦截器的作用:

  • 获取到浏览器发送的请求头
  • 使用Feign调用其他微服务的时候,将请求头信息添加上
package com.ihrm.common.feign;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

@Configuration
public class FeignConfiguration {

    //配置feign拦截器,解决请求头问题
    @Bean
    public RequestInterceptor requestInterceptor() {
        return new RequestInterceptor(){

            //获取所有浏览器发送的请求属性,请求头赋值到feign
            @Override
            public void apply(RequestTemplate requestTemplate) {
                //请求属性
                ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
                if(attributes != null) {
                    HttpServletRequest request = attributes.getRequest();
                    //获取浏览器发起的请求头
                    Enumeration<String> headerNames = request.getHeaderNames();
                    if (headerNames != null) {
                        while (headerNames.hasMoreElements()){
                            String name = headerNames.nextElement(); //请求头名称 Authorization
                            String value = request.getHeader(name);//请求头数据 "Bearer b1dbb4cf-7de6-41e5-99e2-0e8b7e8fe6ee"
                            requestTemplate.header(name,value);
                        }
                    }
                }

            }
        };
    }
}

2、POI报表的概述

<1>、需求说明

在企业级应用开发中,Excel报表是一种最常见的报表需求,Excel报表开发一般分为两种形式:

  • 为了方便操作,基于Excel的报表批量上传数据
  • 通过Java代码生成Excel报表
<2>、Excel的俩种形式

目前市面上的Excel分为两个大的版本Excel2003和Excel2007及以上两个版本,两者的区别如下:
在这里插入图片描述
Excel2003是一个特有的二进制根式,其核心是复合文档类型的结构,存储数据量较小;Excel2007的核心结构是XML类型的结构,采用的是基于XML的压缩方式,使其占用的空间更小,操作效率更高。

<3>、常见的Excel操作工具

Java中常见的用来操作Excel的方式一般有两种:JXL和POI

  • JXL只能对Excel进行操作,属于比较老的框架,只支持Excel95-2000的版本,现在已经停止更新和维护
  • POI是Apache的项目,可对微软的Word、Excel、PPT进行操作,包括office2003和2007,Excel2003和Excel2007。POI现在一直在更新,因此现在主流使用POI。
<4>、POI的概述

Apache POI是Apache软件基金会的开源项目,由Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java语言操作Microsoft Office的功能。

<5>、使用场景
  • 数据报表生成
  • 数据备份
  • 数据批量上传

3、POI入门操作

<1>、搭建环境

创建一个maven工程,导入相关依赖

		<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.0.1</version>
        </dependency>
<2>、结构说明

HSSF提供读写Microsoft Excel XLS格式档案的功能
XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能

HWPF提供读写Microsoft Word DOC格式档案的功能
HSLF提供读写Microsoft PowerPoint格式档案的功能
HDGF提供读Microsoft Visio格式档案的功能
HPBF提供读Microsoft Publisher格式档案的功能
HSMF提供读Microsoft Outlook格式档案的功能

<3>、API说明

在这里插入图片描述

<4>、基本操作
(1)、使用POI创建一个Excel
package poi.test;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;

import java.io.FileOutputStream;

public class PoiTest {

    /**
     *  1、使用POI创建Excel
     */
    @Test
    public void PoiTest01() throws Exception{
        //1、创建工作簿
        Workbook workbook = new XSSFWorkbook();
        //2、创建表单
        Sheet sheet = workbook.createSheet("test");
        //3、文件输出流
        FileOutputStream fos = new FileOutputStream("/Users/xiaotongxin/work/poi/test.xlsx");
        //4、写入文件
        workbook.write(fos);
        //5、关闭流
        fos.close();
    }
}
(2)、创建单元格并写入内容
 	/**
     * 2、创建单元格并写入内容
     */
    @Test
    public void PoiTest02() throws Exception{
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表单
        Sheet sheet = workbook.createSheet("test");
        //创建行对象 参数:索引(从0开始)
        Row row = sheet.createRow(3);
        //创建单元格对象 参数:索引(从0开始)
        Cell cell = row.createCell(3);
        cell.setCellValue("I Love You Forever");
        //文件输出流
        FileOutputStream fos = new FileOutputStream("/Users/xiaotongxin/IdeaProjects/hrm/poi-test/src/poi/test1.xlsx");
        //写入文件
        workbook.write(fos);
        //关闭流
        fos.close();
    }

测试结果如下:
在这里插入图片描述

(3)、单元格样式处理

从上例可以看出,单元格内的内容已经超出了边框,这时需要对写入的内容做一些相应的处理,如字体、字号、边框、行高列宽等等。

	/**
     * 3、单元格样式
     */
    @Test
    public void PoiTest03() throws Exception{
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表单
        Sheet sheet = workbook.createSheet("test");
        //创建行对象 参数:索引(从0开始)
        Row row = sheet.createRow(3);
        //创建单元格对象 参数:索引(从0开始)
        Cell cell = row.createCell(3);
        cell.setCellValue("I Love You Forever");
        /**
         * 样式处理
         */
        //创建样式对象
        CellStyle cellStyle = workbook.createCellStyle();
        //设置边框
        cellStyle.setBorderTop(BorderStyle.HAIR);
        cellStyle.setBorderBottom(BorderStyle.HAIR);
        cellStyle.setBorderLeft(BorderStyle.HAIR);
        cellStyle.setBorderRight(BorderStyle.HAIR);
        //创建字体对象
        Font font = workbook.createFont();
        font.setFontName("仿宋"); //设置字体
        font.setFontHeightInPoints((short) 15); //设置字号
        cellStyle.setFont(font);    //字体对象绑定到样式对象中

        row.setHeightInPoints(50);  //行高
        sheet.setColumnWidth(3, 30 * 256);  //列宽 字符宽度

        cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);   //垂直居中
        cell.setCellStyle(cellStyle);   //样式对象绑定到单元格对象中

        //文件输出流
        FileOutputStream fos = new FileOutputStream("/Users/xiaotongxin/IdeaProjects/hrm/poi-test/src/poi/test2.xlsx");
        //写入文件
        workbook.write(fos);
        //关闭流
        fos.close();
    }

运行结果如下:
在这里插入图片描述

(4)、绘制图形

在实际中,通常需要在Excel表格中添加一些简单的图片

	/**
     * 4、插入图形
     */
    @Test
    public void PoiTest04() throws Exception{
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表单
        Sheet sheet = workbook.createSheet("test");

        //读取图片的文件流
      	FileInputStream fis = new FileInputStream("/Users/xiaotongxin/IdeaProjects/hrm/poi-test/src/poi/1.jpg");
        //转换成二进制数组
        byte[] bytes = IOUtils.toByteArray(fis);
        fis.read(bytes);
        //向POI内存中添加一张图片,返回的值是图片在图片集合中的索引值
        int index = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
        //绘制图片工具类
        CreationHelper helper = workbook.getCreationHelper();
        //创建一个绘图对象
        Drawing<?> patriarch = sheet.createDrawingPatriarch();
        //创建锚点、设置图片的坐标
        ClientAnchor anchor = helper.createClientAnchor();
        anchor.setRow1(1);
        anchor.setCol1(1);
        //绘制图片
        Picture picture = patriarch.createPicture(anchor, index);
        picture.resize();	//自适应渲染图片

        //文件输出流
        FileOutputStream fos = new FileOutputStream("/Users/xiaotongxin/IdeaProjects/hrm/poi-test/src/poi/test3.xlsx");
        //写入文件
        workbook.write(fos);
        //关闭流
        fos.close();
    }

运行结果如下:
在这里插入图片描述

(5)、读取Excel并解析

在实际开发工作中,我们往往不是创建工作簿,大部分都是读取已有的Excel并对其中的数据进行分析,从中获取我们需要的信息。

	/**
     * 5、读取Excel并解析
     *      sheet.getLastRowNum():最后一行索引
     *      row.getLastCellNum():最后一个单元格号码
     */
    @Test
    public void PoiTest05() throws Exception{
        //创建工作簿
        Workbook workbook = new XSSFWorkbook("/Users/xiaotongxin/IdeaProjects/hrm/poi-test/src/poi/hr-demo.xlsx");
        //获取sheet
        Sheet sheet = workbook.getSheetAt(0);
        //获取sheet每一行和每一个单元格
        for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum ++){
            Row row = sheet.getRow(rowNum);
            StringBuilder stringBuilder = new StringBuilder();
            for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum ++){
                //根据索引获取每一个单元格
                Cell cell = row.getCell(cellNum);
                //获取每一个单元格中的内容
                Object value = getValue(cell);
                stringBuilder.append(value).append(",");
            }
            System.out.println(stringBuilder.toString());
        }
    }

    /**
     *  根据传入的cell判断单元格中内容的格式,从而获取到相应的值
     */
    public static Object getValue(Cell cell){
        //获取单元格的属性
        CellType cellType = cell.getCellType();
        //根据单元格属性获取数据
        Object value = null;
        switch (cellType){
            case STRING:
                value = cell.getStringCellValue();
                break;
            case BOOLEAN:
                value = cell.getBooleanCellValue();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)){
                    //日期
                    value = cell.getDateCellValue();
                }else {
                    //数字
                    value = cell.getNumericCellValue();
                }
                break;
            case FORMULA:   //公式
                value = cell.getCellFormula();
        }
        return value;
    }

运行结果如下:
在这里插入图片描述

4、POI报表导入

<1>、需求分析

实现批量导入员工功能,页面端上传Excel表格,服务端解析表格获取数据,批量新增用户
在这里插入图片描述

<2>、员工导入
(1)、环境搭建

在父工程中导入相关依赖

		<!--POI-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.0.1</version>
        </dependency>
(2)、Excel上传

1、在系统微服务中的UserController中添加导入Excel添加用户的方法

	/**
     * 导入Excel,添加用户
     *  文件上传:SpringBoot
     */
    @RequestMapping(value="/user/import",method = RequestMethod.POST)
    public Result importUser(@RequestParam(name="file") MultipartFile file) throws Exception {
        //1.解析Excel
        //1.1.根据Excel文件创建工作簿
        Workbook wb = new XSSFWorkbook(file.getInputStream());
        //1.2.获取Sheet
        Sheet sheet = wb.getSheetAt(0);//参数:索引
        //1.3.获取Sheet中的每一行,和每一个单元格
        //2.获取用户数据列表
        List<User> list = new ArrayList<>();
        System.out.println(sheet.getLastRowNum());
        for (int rowNum = 1; rowNum<= sheet.getLastRowNum() ;rowNum ++) {
            Row row = sheet.getRow(rowNum);//根据索引获取每一个行
            Object [] values = new Object[row.getLastCellNum()];
            for(int cellNum=1;cellNum< row.getLastCellNum(); cellNum ++) {
                Cell cell = row.getCell(cellNum);
                Object value = getCellValue(cell);
                values[cellNum] = value;
            }
            User user = new User(values);
            list.add(user);
        }
        //3.批量保存用户
        userService.saveAll(list,companyId,companyName);

        return new Result(ResultCode.SUCCESS);
    }

2、在ihrm_common工程User类中添加相应的构造方法

	public User(Object [] values) {
        //用户名	手机号	工号	 聘用形式	入职时间	部门编码
        this.username = values[1].toString();
        this.mobile = values[2].toString();
        this.workNumber = new DecimalFormat("#").format(values[3]).toString();
        this.formOfEmployment =((Double) values[4]).intValue();
        this.timeOfEntry = (Date) values[5];
        this.departmentId = values[6].toString(); //部门编码 != 部门id
    }

3、在系统微服务中的UserService中添加批量保存用户的方法

	@Autowired
    private DepartmentFeignClient departmentFeignClient;
	
 	/**
     * 批量保存用户
     */
    @Transactional  //事务处理
    public void saveAll(List<User> list ,String companyId,String companyName){
        for (User user : list) {
            //默认密码
            user.setPassword(new Md5Hash("123456",user.getMobile(),3).toString());
            //id
            user.setId(idWorker.nextId()+"");
            //基本属性
            user.setCompanyId(companyId);
            user.setCompanyName(companyName);
            user.setInServiceStatus(1);
            user.setEnableState(1);
            user.setLevel("user");

            //填充部门的属性
            Department department = departmentFeignClient.findByCode(user.getDepartmentId(), companyId);
            if(department != null) {
                user.setDepartmentId(department.getId());
                user.setDepartmentName(department.getName());
            }
            userDao.save(user);
        }
    }

4、在企业微服务中的DepartmentController添加findByCode方法

	@RequestMapping(value="/department/search",method = RequestMethod.POST)
    public Department findByCode(@RequestParam(value="code") String code,@RequestParam(value="companyId") String companyId) {
        Department dept = departmentService.findByCode(code,companyId);
        return dept;
    }

5、在企业微服务中的DepartmentService添加findByCode方法

 	/**
     * 根据部门编码和企业id查询部门
     */
    public Department findByCode(String code, String companyId) {
        return departmentDao.findByCodeAndCompanyId(code,companyId);
    }

6、在企业微服务中的DepartmentDao添加findByCodeAndCompanyId抽象方法

public interface DepartmentDao extends JpaRepository<Department,String> ,JpaSpecificationExecutor<Department> {
    Department findByCodeAndCompanyId(String code, String companyId);
}
(3)、调用企业微服务获取部门数据

因此要进行跨服务调用方法,因此在ihrm_system微服务中的DepartmentFeignClient接口中添加和企业微服务的DepartmentController中findByCode相类似的方法,注意DepartmentFeignClient的@RequestMapping的value值要写全请求地址,千万不要省略

   @RequestMapping(value="/company/department/search",method = RequestMethod.POST)
    Department findByCode(@RequestParam(value="code") String code, @RequestParam(value="companyId") String companyId);

5、POI报表导出

<1>、需求分析

完成当月人事报表的导出:包含当月入职员工信息和离职员工的信息。
在这里插入图片描述

<2>、报表导出
(1)、步骤分析

1、构造Excel表格数据
2、创建工作簿
3、创建sheet
4、创建行对象
5、创建单元格对象
6、填充数据、设置样式
7、下载

(2)、实现

1、在ihrm_common_model中创建返回值对象

package com.ihrm.domain.employee.response;

import com.ihrm.domain.employee.EmployeeResignation;
import com.ihrm.domain.employee.UserCompanyPersonal;
import com.ihrm.domain.poi.ExcelAttribute;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.BeanUtils;

@Getter
@Setter
@NoArgsConstructor
@ToString
public class EmployeeReportResult {

    private String userId;
    private String username;
    private String departmentName;
    private String mobile;
    private String timeOfEntry;
    private String companyId;
    private String sex;
    /**
     * 出生日期
     */
    private String dateOfBirth;
    /**
     * 最高学历
     */
    private String theHighestDegreeOfEducation;
    /**
     * 国家地区
     */
    private String nationalArea;
    /**
     * 护照号
     */
    private String passportNo;
    /**
     * 身份证号
     */
    private String idNumber;
    /**
     * 身份证照片-正面
     */
    private String idCardPhotoPositive;
    /**
     * 身份证照片-背面
     */
    private String idCardPhotoBack;
    /**
     * 籍贯
     */
    private String nativePlace;
    /**
     * 民族
     */
    private String nation;
    /**
     * 英文名
     */
    private String englishName;
    /**
     * 婚姻状况
     */
    private String maritalStatus;
    /**
     * 员工照片
     */
    private String staffPhoto;
    /**
     * 生日
     */
    private String birthday;
    /**
     * 属相
     */
    private String zodiac;
    /**
     * 年龄
     */
    private String age;
    /**
     * 星座
     */
    private String constellation;
    /**
     * 血型
     */
    private String bloodType;
    /**
     * 户籍所在地
     */
    private String domicile;
    /**
     * 政治面貌
     */
    private String politicalOutlook;
    /**
     * 入党时间
     */
    private String timeToJoinTheParty;
    /**
     * 存档机构
     */
    private String archivingOrganization;
    /**
     * 子女状态
     */
    private String stateOfChildren;
    /**
     * 子女有无商业保险
     */
    private String doChildrenHaveCommercialInsurance;
    /**
     * 有无违法违纪行为
     */
    private String isThereAnyViolationOfLawOrDiscipline;
    /**
     * 有无重大病史
     */
    private String areThereAnyMajorMedicalHistories;
    /**
     * QQ
     */
    private String qq;
    /**
     * 微信
     */
    private String wechat;
    /**
     * 居住证城市
     */
    private String residenceCardCity;
    /**
     * 居住证办理日期
     */
    private String dateOfResidencePermit;
    /**
     * 居住证截止日期
     */
    private String residencePermitDeadline;
    /**
     * 现居住地
     */
    private String placeOfResidence;
    /**
     * 通讯地址
     */
    private String postalAddress;
    /**
     * 联系手机
     */
    private String contactTheMobilePhone;
    /**
     * 个人邮箱
     */
    private String personalMailbox;
    /**
     * 紧急联系人
     */
    private String emergencyContact;
    /**
     * 紧急联系电话
     */
    private String emergencyContactNumber;
    /**
     * 社保电脑号
     */
    private String socialSecurityComputerNumber;
    /**
     * 公积金账号
     */
    private String providentFundAccount;
    /**
     * 银行卡号
     */
    private String bankCardNumber;
    /**
     * 开户行
     */
    private String openingBank;
    /**
     * 学历类型
     */
    private String educationalType;
    /**
     * 毕业学校
     */
    private String graduateSchool;
    /**
     * 入学时间
     */
    private String enrolmentTime;
    /**
     * 毕业时间
     */
    private String graduationTime;
    /**
     * 专业
     */
    private String major;
    /**
     * 毕业证书
     */
    private String graduationCertificate;
    /**
     * 学位证书
     */
    private String certificateOfAcademicDegree;
    /**
     * 上家公司
     */
    private String homeCompany;
    /**
     * 职称
     */
    private String title;
    /**
     * 简历
     */
    private String resume;
    /**
     * 有无竞业限制
     */
    private String isThereAnyCompetitionRestriction;
    /**
     * 前公司离职证明
     */
    private String proofOfDepartureOfFormerCompany;
    /**
     * 备注
     */
    private String remarks;

    /**
     * 离职时间
     */
    private String resignationTime;
    /**
     * 离职类型
     */
    private String typeOfTurnover;
    /**
     * 申请离职原因
     */
    private String reasonsForLeaving;

    public EmployeeReportResult(UserCompanyPersonal personal, EmployeeResignation resignation) {
        BeanUtils.copyProperties(personal,this);
        if(resignation != null) {
            BeanUtils.copyProperties(resignation,this);
        }
    }
}

2、在DAO层添加方法

	@Query(value="select new com.ihrm.domain.employee.response.EmployeeReportResult(a,b) from UserCompanyPersonal a " +
            "LEFT JOIN EmployeeResignation b on a.userId=b.userId where a.companyId=?1 and a.timeOfEntry like?2 or (" +
            "b.resignationTime like ?2)")
    List<EmployeeReportResult> findByReport(String companyId,String month);

3、Service层

	public List<EmployeeReportResult> findByReport(String companyId,String month) {
        return userCompanyPersonalDao.findByReport(companyId,month+"%");
    }

4、Controller层

	/**
     * 当月人事报表导出
     *  参数:
     *      年月-月(2018-02%)
     */
    @RequestMapping(value = "/export/{month}", method = RequestMethod.GET)
    public void export(@PathVariable String month) throws Exception {
        //1.获取报表数据
        List<EmployeeReportResult> list = userCompanyPersonalService.findByReport(companyId,month);
        //2.构造Excel
        //创建工作簿
        //SXSSFWorkbook : 百万数据报表
        //Workbook wb = new XSSFWorkbook();
        SXSSFWorkbook wb = new SXSSFWorkbook(100); //阈值,内存中的对象数量最大数量
        //构造sheet
        Sheet sheet = wb.createSheet();
        //创建行
        //标题
        String [] titles = "编号,姓名,手机,最高学历,国家地区,护照号,籍贯,生日,属相,入职时间,离职类型,离职原因,离职时间".split(",");
        //处理标题

        Row row = sheet.createRow(0);

        int titleIndex=0;
        for (String title : titles) {
            Cell cell = row.createCell(titleIndex++);
            cell.setCellValue(title);
        }

        int rowIndex = 1;
        Cell cell = null;
        for (EmployeeReportResult employeeReportResult : list) {
            row = sheet.createRow(rowIndex++);
            // 编号,
            cell = row.createCell(0);
            cell.setCellValue(employeeReportResult.getUserId());
            // 姓名,
            cell = row.createCell(1);
            cell.setCellValue(employeeReportResult.getUsername());
            // 手机,
            cell = row.createCell(2);
            cell.setCellValue(employeeReportResult.getMobile());
            // 最高学历,
            cell = row.createCell(3);
            cell.setCellValue(employeeReportResult.getTheHighestDegreeOfEducation());
            // 国家地区,
            cell = row.createCell(4);
            cell.setCellValue(employeeReportResult.getNationalArea());
            // 护照号,
            cell = row.createCell(5);
            cell.setCellValue(employeeReportResult.getPassportNo());
            // 籍贯,
            cell = row.createCell(6);
            cell.setCellValue(employeeReportResult.getNativePlace());
            // 生日,
            cell = row.createCell(7);
            cell.setCellValue(employeeReportResult.getBirthday());
            // 属相,
            cell = row.createCell(8);
            cell.setCellValue(employeeReportResult.getZodiac());
            // 入职时间,
            cell = row.createCell(9);
            cell.setCellValue(employeeReportResult.getTimeOfEntry());
            // 离职类型,
            cell = row.createCell(10);
            cell.setCellValue(employeeReportResult.getTypeOfTurnover());
            // 离职原因,
            cell = row.createCell(11);
            cell.setCellValue(employeeReportResult.getReasonsForLeaving());
            // 离职时间
            cell = row.createCell(12);
            cell.setCellValue(employeeReportResult.getResignationTime());
        }
        
        //3.完成下载
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        wb.write(os);
        new DownloadUtils().download(os,response,month+"人事报表.xlsx");
    }

5、DownloadUtils工具类

package com.ihrm.common.utils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class DownloadUtils {
    public void download(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, String returnName) throws IOException {
        response.setContentType("application/octet-stream");
        returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));			//保存的文件名,必须和页面编码一致,否则乱码
        response.addHeader("content-disposition","attachment;filename=" + returnName);
        response.setContentLength(byteArrayOutputStream.size());
        ServletOutputStream outputstream = response.getOutputStream();	//取得输出流
        byteArrayOutputStream.writeTo(outputstream);					//写到输出流
        byteArrayOutputStream.close();									//关闭
        outputstream.flush();											//刷数据
    }
}

现在就可以实现将员工的数据以Excel表格的形式导出。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值