springboot + poi 导入导出(excel)表格

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_39150374/article/details/102660737

前言

最近在项目中有一个需求对企业列表批量导入或生成excel表格,在过程中遇到了很多坑,今天和大家分享一下。springboot 1.5.x版本

pom文件

需要引入的jar包

<!-- poi操作excel -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.8</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.8</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.8</version>
		</dependency>

工具类

package com.sinoyd.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Desc excel读取工具类
 */
public class ExcelUtil {
    private static int totalRows = 0;// 总行数

    private static int totalCells = 0;// 总列数

    private static String errorInfo;// 错误信息

    /**
     * 无参构造方法
     */
    public ExcelUtil() {
    }

    public static int getTotalRows() {
        return totalRows;
    }

    public static int getTotalCells() {
        return totalCells;
    }

    public static String getErrorInfo() {
        return errorInfo;
    }

    /**
     * 根据流读取Excel文件
     *
     * @param inputStream
     * @param isExcel2003
     * @return
     * @see [类、类#方法、类#成员]
     */
    public List<List<String>> read(InputStream inputStream, boolean isExcel2003)
            throws IOException {

        List<List<String>> dataLst = null;

        /** 根据版本选择创建Workbook的方式 */
        Workbook wb = null;

        if (isExcel2003) {
            wb = new HSSFWorkbook(inputStream);
        } else {
            wb = new XSSFWorkbook(inputStream);
        }
        dataLst = readData(wb);

        return dataLst;
    }

    /**
     * 读取数据
     *
     * @param wb
     * @return
     * @see [类、类#方法、类#成员]
     */
    private List<List<String>> readData(Workbook wb) {

        List<List<String>> dataLst = new ArrayList<List<String>>();

        /** 得到第一个shell */
        Sheet sheet = wb.getSheetAt(0);

        /** 得到Excel的行数 */
        totalRows = sheet.getPhysicalNumberOfRows();

        /** 得到Excel的列数 */
        if (totalRows >= 1 && sheet.getRow(0) != null) {
            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }

        /** 循环Excel的行 */
        for (int r = 0; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                continue;
            }

            List<String> rowLst = new ArrayList<String>();

            /** 循环Excel的列 */
            for (int c = 0; c < getTotalCells(); c++) {

                Cell cell = row.getCell(c);
                String cellValue = "";

                if (null != cell) {
                    // 以下是判断数据的类型
                    switch (cell.getCellType()) {
                        case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                            cellValue = cell.getNumericCellValue() + "";
                            break;

                        case HSSFCell.CELL_TYPE_STRING: // 字符串
                            cellValue = cell.getStringCellValue();
                            break;

                        case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                            cellValue = cell.getBooleanCellValue() + "";
                            break;

                        case HSSFCell.CELL_TYPE_FORMULA: // 公式
                            cellValue = cell.getCellFormula() + "";
                            break;

                        case HSSFCell.CELL_TYPE_BLANK: // 空值
                            cellValue = "";
                            break;

                        case HSSFCell.CELL_TYPE_ERROR: // 故障
                            cellValue = "非法字符";
                            break;

                        default:
                            cellValue = "未知类型";
                            break;
                    }
                }

                rowLst.add(cellValue);
            }

            /** 保存第r行的第c列 */
            dataLst.add(rowLst);
        }

        return dataLst;
    }

    /**
     * 根据Excel表格中的数据判断类型得到值
     *
     * @param cell
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static String getCellValue(Cell cell) {
        String cellValue = "";
        if (null != cell) {
            // 以下是判断数据的类型
            switch (cell.getCellType()) {
                case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                        Date theDate = cell.getDateCellValue();
                        SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd");
                        cellValue = dff.format(theDate);
                    } else {
                        DecimalFormat df = new DecimalFormat("0");
                        cellValue = df.format(cell.getNumericCellValue());
                    }
                    break;
                case HSSFCell.CELL_TYPE_STRING: // 字符串
                    cellValue = cell.getStringCellValue();
                    break;

                case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                    cellValue = cell.getBooleanCellValue() + "";
                    break;

                case HSSFCell.CELL_TYPE_FORMULA: // 公式
                    cellValue = cell.getCellFormula() + "";
                    break;

                case HSSFCell.CELL_TYPE_BLANK: // 空值
                    cellValue = "";
                    break;

                case HSSFCell.CELL_TYPE_ERROR: // 故障
                    cellValue = "非法字符";
                    break;

                default:
                    cellValue = "未知类型";
                    break;
            }

        }
        return cellValue;
    }

    /**
     * 根据路径或文件名选择Excel版本
     *
     * @param filePathOrName
     * @param in
     * @return
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public static Workbook chooseWorkbook(String filePathOrName, InputStream in)
            throws IOException {
        /** 根据版本选择创建Workbook的方式 */
        Workbook wb = null;
        boolean isExcel2003 = ExcelVersionUtil.isExcel2003(filePathOrName);

        if (isExcel2003) {
            wb = new HSSFWorkbook(in);
        } else {
            wb = new XSSFWorkbook(in);
        }

        return wb;
    }

    static class ExcelVersionUtil {

        /**
         * 是否是2003的excel,返回true是2003
         *
         * @param filePath
         * @return
         * @see [类、类#方法、类#成员]
         */
        public static boolean isExcel2003(String filePath) {
            return filePath.matches("^.+\\.(?i)(xls)$");

        }

        /**
         * 是否是2007的excel,返回true是2007
         *
         * @param filePath
         * @return
         * @see [类、类#方法、类#成员]
         */
        public static boolean isExcel2007(String filePath) {
            return filePath.matches("^.+\\.(?i)(xlsx)$");

        }
    }
}

这个工具类主要是针对导入excel表格,个人觉得导入比较难。

service层关键代码

/**
*  导入excel表格
* post方法
*/
@Transactional
    public String upload(MultipartFile file) throws Exception {
        if (file == null || file.isEmpty()) {
            throw new Exception("导入文件不能为空");
        }

        // 获取文件名
        String fileName = file.getOriginalFilename();

        int len = fileName.lastIndexOf(".");
        if (len <= 0) {
            throw new Exception("文件类型有误,请确认!");
        }

        String fileType = fileName.substring(len + 1).toLowerCase();
        if (!fileType.equals("xls") && !fileType.equals("xlsx")) {
            throw new Exception("只允许上传xls、xlsx");
        }
        InputStream in = file.getInputStream();
        Workbook wb = ExcelUtil.chooseWorkbook(fileName, in);

        List<Company> companies = getCompaniesFromExcel(wb);
        List<String> creditCodes = companies.stream().map(Company::getCreditCode).collect(Collectors.toList());
        List<Company> exists = companyRepository.findCompaniesByCreditCodeIn(creditCodes);
        if (exists != null && !exists.isEmpty()) {
            throw new ResException("信用代码为" + com.sinoyd.common.util.StringExtendUtil.join(creditCodes, ",") + "的企业已存在");
        }
        companyRepository.save(companies);
        
        return "企业导入成功!";
    }

/**
     * 导出excel表格
     *  get方法
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public String export(HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<Company> companies = companyRepository.findAll();
        HSSFWorkbook wb = new HSSFWorkbook();//创建Excel文件
        HSSFSheet sheet = wb.createSheet("企业信息表");
        String sheetName = sheet.getSheetName();
        wb.setSheetName(0, sheetName);
        sheet.setDefaultRowHeight((short) (20 * 20));
        CellStyle style = wb.createCellStyle();
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        HSSFRow row = sheet.createRow(0);
        row.createCell(0).setCellValue("企业名称");//为第一个单元格设值
        row.createCell(1).setCellValue("社会信用代码");//为第二个单元格设值
        row.createCell(2).setCellValue("联系人");//为第三个单元格设值
        row.createCell(3).setCellValue("联系电话");//为第三个单元格设值
        row.createCell(4).setCellValue("法人");//为第三个单元格设值
        row.createCell(5).setCellValue("地址");
        row.createCell(6).setCellValue("行业");
        row.createCell(7).setCellValue("创建日期");
        row.createCell(8).setCellValue("开业日期");
        row.createCell(9).setCellValue("员工数");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (companies != null && companies.size() > 0) {
            int i = 0;
            for (Company company : companies) {
                i++;
                row = sheet.createRow(i);
                row.createCell(0).setCellValue(company.getName());
                row.createCell(1).setCellValue(company.getCreditCode());
                row.createCell(2).setCellValue(company.getContactName());
                row.createCell(3).setCellValue(company.getContactPhone());
                row.createCell(4).setCellValue(company.getCorporation());
                row.createCell(5).setCellValue(company.getAddress());
                row.createCell(6).setCellValue(company.getIndustryName());

                String establishedDate = company.getEstablishedDate() != null ? sdf.format(company.getEstablishedDate()) : "";
                row.createCell(7).setCellValue(establishedDate);
                String openedDate = company.getOpenedDate() != null ? sdf.format(company.getOpenedDate()) : "";
                row.createCell(8).setCellValue(openedDate);
                Integer staffNum = company.getStaffNum() == null ? 0 : company.getStaffNum();
                row.createCell(9).setCellValue(staffNum);
            }
        }

        //列宽自适应
        for (int i = 0; i <= 9; i++) {
            sheet.autoSizeColumn(i);
        }

        // 针对IE或者以IE为内核的浏览器:
        String userAgent = request.getHeader("User-Agent").toLowerCase();
        String fileName = sheetName + ".xlsx";
        if (userAgent.contains("msie") || userAgent.contains("trident")) {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            // 非IE浏览器的处理:
            fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("success", "true");
        OutputStream os = response.getOutputStream();
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);//默认Excel名称

        wb.write(os);
        os.flush();
        os.close();

        return "导出企业信息成功";
    }

    private Integer getRowNum(Sheet sheet) {
        int totalRows = sheet.getPhysicalNumberOfRows();
        for (int r = 1; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                return r;
            }
            String companyName = ExcelUtil.getCellValue(row.getCell(0));
            String creditCode = ExcelUtil.getCellValue(row.getCell(1));
            if (companyName.trim().equals("") && creditCode.trim().equals("")) {
                return r;
            }
        }
        return totalRows;
    }

    private List<Company> getCompaniesFromExcel(Workbook wb) throws Exception {
        List<Company> companies = new ArrayList<>();
        /** 得到第一个shell */
        Sheet sheet = wb.getSheetAt(0);
        /** 得到Excel的行数 */
        int totalRows = getRowNum(sheet);
        List<String> creditCodes = new ArrayList<>();
        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
        /** 循环Excel的行 */
        for (int r = 1; r < totalRows; r++) {
            Company company = new Company();
            Row row = sheet.getRow(r);
            if (row == null) {
                continue;
            }

            String cellValue = ExcelUtil.getCellValue(row.getCell(0));
            if (cellValue.trim().equals("")) {
                throw new Exception("企业名称不能为空,请确认!");
            }
            company.setName(cellValue);
            cellValue = ExcelUtil.getCellValue(row.getCell(1));
            if (cellValue.trim().equals("")) {
                throw new Exception("企业信用代码不能为空,请确认!");
            }
            if (creditCodes.contains(cellValue)) {
                throw new Exception("有重复的企业信用代码" + cellValue + ",请确认!");
            }
            creditCodes.add(cellValue);
            company.setCreditCode(cellValue);
            cellValue = ExcelUtil.getCellValue(row.getCell(2));
            if (cellValue.trim().length() > 0) {
                company.setContactName(cellValue);
            }
            cellValue = ExcelUtil.getCellValue(row.getCell(3));
            if (cellValue.trim().length() > 0) {
                company.setContactPhone(cellValue);
            }
            cellValue = ExcelUtil.getCellValue(row.getCell(4));
            company.setCorporation(cellValue);
            cellValue = ExcelUtil.getCellValue(row.getCell(5));
            if (Helpers.isNotNullAndEmpty(cellValue)) {
                if (!Validator.isEmail(cellValue)) {
                    throw new Exception("邮箱格式不正确" + cellValue + ",请确认!");
                }
                company.setEmail(cellValue);
            }
            cellValue = ExcelUtil.getCellValue(row.getCell(6));
            if (Helpers.isNotNullAndEmpty(cellValue)) {
                if (!Validator.isFax(cellValue)) {
                    throw new Exception("传真格式不正常" + cellValue + ",请确认!");
                }
                company.setFax(cellValue);
            }
            cellValue = ExcelUtil.getCellValue(row.getCell(7));
            company.setAddress(cellValue);
            cellValue = ExcelUtil.getCellValue(row.getCell(8));
            Double area = cellValue.equals("") ? 0 : Double.valueOf(cellValue);
            if (area < 0) {
                throw new Exception("占地面积不能为负数" + cellValue + ",请确认!");
            }
            company.setFloorArea(area);
  
            companies.add(company);
        }
        List<Company> companyList = companyRepository.findCompaniesByCreditCodeIn(creditCodes);
        if (companyList != null && companyList.size() > 0) {
            List<String> list = companyList.stream().map(Company::getCreditCode).collect(Collectors.toList());
            throw new Exception("以下信用代码已存在:" + String.join(",", list));
        }
        return companies;
    }

关键代码都已经贴出来了,实体类和Controller层就不放出来了。

猜你喜欢

转载自blog.csdn.net/qq_39150374/article/details/102660737