SpringBoot 2.1.x整合POI实现Excel读写示例

资源相关

  • boot-poi项目结构图
    SpringBoot 2.1.x整合POI实现Excel读写示例_第1张图片
  • boot-poi源码链接【推荐】

核心代码展示

  • pom.xml依赖相关
 
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.apache.poi
            poi
            3.9
        

        
        
            org.apache.poi
            poi-ooxml
            3.9
        

        
        
            joda-time
            joda-time
            2.10.1
        
        
            org.apache.commons
            commons-lang3
        


        
        
            io.springfox
            springfox-swagger2
            2.9.2
        
        
            io.springfox
            springfox-swagger-ui
            2.9.2
        

        
        
            org.projectlombok
            lombok
            true
        
    
  • SalaryDetail .java
package com.hf.poi.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiParam;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
 * @Copyright (C), 2017-2019
 * @FileName: Person
 * @Author: hf
 * @Date: 2019/9/25 0:31
 * @Description: 薪资明细实体
 */
@Getter
@Setter
@Accessors(chain = true)
@ApiModel("POI测试【薪资明细实体】")
@ToString
public class SalaryDetail implements Serializable {

    @ApiParam(name = "no", value = "序号")
    private String no;

    @ApiParam(name = "id", value = "ID标识")
    private String id;

    @ApiParam(name = "name", value = "姓名")
    private String name;

    @ApiParam(name = "status", value = "人员状态")
    private boolean status;

    @ApiParam(name = "card", value = "卡号")
    private String card;

    @ApiParam(name = "position", value = "职位")
    private String position;

    @ApiParam(name = "okDay", value = "出勤天数")
    private String okDay;

    @ApiParam(name = "basePay", value = "基本工资")
    private double basePay;

    @ApiParam(name = "meritPay", value = "绩效工资")
    private double meritPay;

    @ApiParam(name = "deduction", value = "代扣款")
    private double deduction;

    @ApiParam(name = "salary", value = "实际工资")
    private double salary;

    @ApiParam(name = "outTime",value = "月份")
    private String outTime;
}

  • POIService.java接口方法定义
package com.hf.poi.service;

import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

/**
 * @Copyright (C), 2017-2019
 * @FileName: POIService
 * @Author: hf
 * @Date: 2019/9/25 0:32
 * @Description: POI服务接口层
 */
public interface POIService {

    /**
     * 功能描述:
     * 〈
     * 03版Excel 大数据写入【优点:速度快,缺点:最大支持写入65536行、超过则抛出异常】
     * 07版Excel 大数据写【优点:可以写较大的数据,缺点:特别耗费内存、且慢、可能会发生内存溢出】
     * 〉
     *
     * @className: POIService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 0:55
     * @param: [is03Version【是否是03版本】 path 输出路径 count 数据量]
     * @return: void
     */
    void write03OR07Excel(boolean is03Version, String path, int count);

    /**
     * 功能描述:
     * 〈
     * 优化 03 07版Excel大数据写入数据
     * 【优点:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存】
     * 【
     * 缺点:
     * 1.过程中会产生临时文件,需要清理临时文件
     * 2.默认由100条记录被保存在内存中,如果超过过这数量,则最前面的数据被写入临时文件
     * 3.如果想自定义内存中数据的数量,可以使用new SXSSFWorkbook(数量)
     * 】
     * 〉
     *
     * @className: POIService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 0:55
     * @param: [is03Version【是否是03版本】 path 输出路径 count 数据量]
     * @return: void
     */
    void write03OR07SXSSFBigDataExcel(boolean is03Version, String path, int count);

    /**
     * 功能描述:
     * 〈
     * 03或07版本Excel读取
     * 〉
     *
     * @className: POIService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 0:59
     * @param: file 文件流]
     * @return: map
     */
    Map<String, Object> read03OR07Excel(MultipartFile file);

}

  • POIServiceImpl.java接口方法实现
package com.hf.poi.service.impl;

import com.hf.poi.entity.SalaryDetail;
import com.hf.poi.service.POIService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Copyright (C), 2017-2019
 * @FileName: POIServiceImpl
 * @Author: hf
 * @Date: 2019/9/25 0:33
 * @Description: POI服务接口实现层
 */
@Service
public class POIServiceImpl implements POIService {

    @Override
    public void write03OR07Excel(boolean is03Version, String path, int count) {
        try {
            // 默认创建 03版本 Excel工作簿
            Workbook workbook = new HSSFWorkbook();

            //07 版
            if (!is03Version) {
                workbook = new XSSFWorkbook();
            }

            //03版或者07版数据写入
            write03OR07Data(workbook, count, is03Version, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void write03OR07SXSSFBigDataExcel(boolean is03Version, String path, int count) {

        try {
            //创建一个SXSSFWorkbook
            SXSSFWorkbook workbook = new SXSSFWorkbook();

            //大数据写
            write03OR07Data(workbook, count, is03Version, path);

            //清除临时文件
            workbook.dispose();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public Map read03OR07Excel(MultipartFile file) {

        Map map = new HashMap<>();
        try {
            //获取文件流
            InputStream is = file.getInputStream();

            //获取文件后缀
            String original = file.getOriginalFilename();
            String suffix = original.substring(original.lastIndexOf("."));

            //创建工作薄
            Workbook workbook = StringUtils.equals(".xsl", suffix) ? new HSSFWorkbook(is) : new XSSFWorkbook(is);

            //获取工作薄
            Sheet sheet = workbook.getSheetAt(0);

            //获取所有行
            int totalSize = sheet.getPhysicalNumberOfRows();

            ArrayList titleList = new ArrayList<>();
            ArrayList sdList = new ArrayList<>();

            for (int i = 0; i < totalSize; i++) {
                //获取一行
                Row row = sheet.getRow(i);
                //获取列数
                int cells = row.getPhysicalNumberOfCells();

                if (i == 0) {
                    //标题行
                    for (int j = 0; j < cells; j++) {
                        titleList.add(row.getCell(j).getStringCellValue());
                    }
                    //加入Map
                    map.put("titleList", titleList);
                } else {
                    SalaryDetail sd = new SalaryDetail();
                    //数据行
                    for (int j = 0; j < cells; j++) {

                        switch (j) {
                            case 0:
                                sd.setNo(row.getCell(j).getStringCellValue());
                                break;
                            case 1:
                                sd.setId(row.getCell(j).getStringCellValue());
                                break;
                            case 2:
                                sd.setName(row.getCell(j).getStringCellValue());
                                break;
                            case 4:
                                sd.setCard(row.getCell(j).getStringCellValue());
                                break;
                            case 5:
                                sd.setPosition(row.getCell(j).getStringCellValue());
                                break;
                            case 6:
                                sd.setOkDay(row.getCell(j).getStringCellValue());
                                break;
                            case 11:
                                sd.setOutTime(row.getCell(j).getStringCellValue());
                                break;
                            case 3:
                                //boolean
                                sd.setStatus(row.getCell(j).getBooleanCellValue());
                                break;
                            case 7:
                                sd.setBasePay(row.getCell(j).getNumericCellValue());
                                break;
                            case 8:
                                sd.setMeritPay(row.getCell(j).getNumericCellValue());
                                break;
                            case 9:
                                sd.setDeduction(row.getCell(j).getNumericCellValue());
                                break;
                            case 10:
                                sd.setSalary(row.getCell(j).getNumericCellValue());
                                break;
                        }
                    }

                    //添加到集合
                    sdList.add(sd);
                }
            }
            map.put("sdList", sdList);

            // 操作结束,关闭文件
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return map;
    }


    /**
     * 功能描述:
     * 〈
     * 存盘整合Excel工作簿信息
     * 〉
     *
     * @className: POIServiceImpl
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 14:04
     * @param: [workbook【03/07版工作蒲】, is03【是否是03版本】, path【输出路径】]
     * @return: void
     */
    private void write03OR07Data(Workbook workbook, int count, boolean is03, String path) throws Exception {

        //创建sheet
        Sheet sheet = workbook.createSheet();

        //创建整合sheet数据集
        createSheetData(sheet, count);

        //文件夹创建
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        // 新建一输出文件流(注意:要先创建文件夹)
        FileOutputStream out = new FileOutputStream(path + "/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "-薪资明细_" + (UUID.randomUUID().toString().replace("-", "")).substring(0, 6).toLowerCase() + (is03 ? "03.xls" : "07.xlsx"));
        // 把相应的Excel 工作簿存盘
        workbook.write(out);
        // 操作结束,关闭文件
        out.close();
    }

    /**
     * 功能描述:
     * 〈
     * 创建Sheet完整工作薄数据信息
     * 〉
     *
     * @className: POIServiceImpl
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 13:58
     * @param: [sheet 【07/03工作蒲】, count【模拟数据量】]
     * @return: void
     */
    private void createSheetData(Sheet sheet, int count) {
        //生成人员薪资信息
        List list = genderData(count);

        for (int x = 0; x < list.size() + 1; x++) {
            Row row = sheet.createRow(x);
            if (x == 0) {
                createExcelTitle(12, row);
            } else {
                createDataRows(12, row, list.get(x - 1));
            }
        }
    }

    /**
     * 功能描述:
     * 〈
     * 生成所需要的数据
     * 〉
     *
     * @className: POIServiceImpl
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 2:00
     * @param: [y【列数】]
     * @return: void
     */
    private void createDataRows(int y, Row row, SalaryDetail sd) {
        for (int i = 0; i < y; i++) {
            switch (i) {
                case 0:
                    row.createCell(i).setCellValue(sd.getNo());
                    break;
                case 1:
                    row.createCell(i).setCellValue(sd.getId());
                    break;
                case 2:
                    row.createCell(i).setCellValue(sd.getName());
                    break;
                case 3:
                    row.createCell(i).setCellValue(Math.random() * 5 > 3);
                    break;
                case 4:
                    row.createCell(i).setCellValue(sd.getCard());
                    break;
                case 5:
                    row.createCell(i).setCellValue(sd.getPosition());
                    break;
                case 6:
                    row.createCell(i).setCellValue(sd.getOkDay() + "");
                    break;
                case 7:
                    row.createCell(i).setCellValue(sd.getBasePay());
                    break;
                case 8:
                    row.createCell(i).setCellValue(sd.getMeritPay());
                    break;
                case 9:
                    row.createCell(i).setCellValue(sd.getDeduction());
                    break;
                case 10:
                    row.createCell(i).setCellValue(sd.getSalary());
                    break;
                case 11:
                    row.createCell(i).setCellValue(sd.getOutTime());
                    break;
            }

        }
    }

    /**
     * 功能描述:
     * 〈
     * 生成Excel第一行标题头
     * 〉
     *
     * @className: POIServiceImpl
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 1:56
     * @param: [row]
     * @return: void
     */
    private void createExcelTitle(int y, Row row) {
        for (int j = 0; j < y; j++) {
            String title = "";
            switch (j) {
                case 0:
                    title = "序号";
                    break;
                case 1:
                    title = "ID标识";
                    break;
                case 2:
                    title = "姓名";
                    break;
                case 3:
                    title = "人员状态";
                    break;
                case 4:
                    title = "卡号";
                    break;
                case 5:
                    title = "职位";
                    break;
                case 6:
                    title = "出勤天数";
                    break;
                case 7:
                    title = "基本工资";
                    break;
                case 8:
                    title = "绩效工资";
                    break;
                case 9:
                    title = "代扣款";
                    break;
                case 10:
                    title = "实际工资";
                    break;
                case 11:
                    title = "月份";
                    break;

            }
            row.createCell(j).setCellValue(title);
        }

    }

    /**
     * 功能描述:
     * 〈
     * 生成薪资明细数据
     * 〉
     *
     * @className: POIServiceImpl
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/25 1:05
     * @param: [count 生成量]
     * @return: java.util.List
     */
    private static List genderData(int count) {
        String[] positionArr = {"架构师", "项目经理", "高级工程师", "运维", "人事专员"};
        String[] nameArr = {"刘一", "陈二", "张三", "李四", "王五"};
        DecimalFormat df = new DecimalFormat("#.00");

        ArrayList list = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            double basePay = Double.parseDouble(df.format(new Random().nextDouble() * 20000));
            double meritPay = Double.parseDouble(df.format(new Random().nextDouble() * 15000));
            double deduction = Double.parseDouble(df.format(new Random().nextDouble() * 1000));

            list.add(
                    new SalaryDetail()
                            .setNo(i + "")
                            .setId((int) (Math.random() * 10000000) + "")
                            .setName(nameArr[(int) (Math.random() * 4)] + "_" + i)
                            .setStatus(((int) (Math.random() * 10) / 2) == 0)
                            .setCard(((int) (Math.random() * 1000000 * Math.random() * 55555)) + "")
                            .setPosition(positionArr[(int) (Math.random() * 4)])
                            .setOkDay((int) (Math.random() * 31) + "")
                            .setBasePay(basePay)
                            .setMeritPay(meritPay)
                            .setDeduction(deduction)
                            .setSalary(Double.parseDouble(df.format(basePay + meritPay - deduction)))
                            .setOutTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
            );

        }


        return list;
    }


}

  • POIController.java
package com.hf.poi.controller;

import com.hf.poi.service.POIService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

/**
 * @Copyright (C), 2017-2019
 * @FileName: POIController
 * @Author: hf
 * @Date: 2019/9/25 0:31
 * @Description: POI前端控制层
 */
@Api(description = "POI相关读写接口测试")
@RestController
@RequestMapping("/poi")
public class POIController {

    @Autowired
    POIService poiService;

    @PostMapping("/read03OR07Excel")
    @ApiOperation(value = "03/07版Excel数据 读取", httpMethod = "POST")
    public Map<String, Object> read03OR07Excel(MultipartFile file) {
        return poiService.read03OR07Excel(file);
    }

    @GetMapping("/write03OR07SXSSFBigDataExcel/{flag}/{path}/{count}")
    @ApiOperation(value = "03/07版Excel【较大数据量写入】", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "flag", value = "版本标识【true 03版  false 07版】", defaultValue = "true"),
            @ApiImplicitParam(name = "path", value = "输出路径", defaultValue = "excel-test"),
            @ApiImplicitParam(name = "count", value = "数据量", defaultValue = "50000")
    })
    public String write03OR07SXSSFBigDataExcel(@PathVariable String flag, @PathVariable String path, @PathVariable String count) {
        try {
            //较大文件写
            poiService.write03OR07SXSSFBigDataExcel(StringUtils.equals("true", flag), "F:\\" + path, Integer.parseInt(count));

            return "write data to Excel Success ! !";
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    @GetMapping("/write03Excel/{flag}/{path}/{count}")
    @ApiOperation(value = "03/07版Excel【普通数据量写入】", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "flag", value = "版本标识【true 03版  false 07版】", defaultValue = "true"),
            @ApiImplicitParam(name = "path", value = "输出路径", defaultValue = "excel-test"),
            @ApiImplicitParam(name = "count", value = "数据量", defaultValue = "2000")
    })
    public String write03Excel(@PathVariable String flag, @PathVariable String path, @PathVariable String count) {
        boolean bool;
        try {
            //大于65535 写07版
            bool = Integer.parseInt(count) > 65535;

            //否则按实际Excel 格式写
            if (!bool) {
                bool = StringUtils.equals("true", flag);
            }

            poiService.write03OR07Excel(bool, "F:\\" + path, Integer.parseInt(count));

            return "write data to Excel Success ! !";
        } catch (Exception e) {

            return e.getMessage();
        }
    }
}

Excel读写测试相关

  • Swagger接口访问
    SpringBoot 2.1.x整合POI实现Excel读写示例_第2张图片

  • 03/07版Excel【普通数据量写入】
    SpringBoot 2.1.x整合POI实现Excel读写示例_第3张图片

  • 03/07版Excel【较大数据量写入】
    SpringBoot 2.1.x整合POI实现Excel读写示例_第4张图片

  • 03/07版Excel数据 读取
    SpringBoot 2.1.x整合POI实现Excel读写示例_第5张图片
    SpringBoot 2.1.x整合POI实现Excel读写示例_第6张图片

你可能感兴趣的:(SpringBoot)