一般在公司写项目,会有这样的应用场景,即:在前台页面的文件上传入口上传本地的Excel文件到后台,后台收到Excel文件后进行解析并做对应的业务操作;
我们现在以 Apache POI 4.0.1版本读取普通Excel文件(兼容 xls 和 xlsx)(一) https://www.cnblogs.com/weigy/p/12905857.html 做一些修改。
代码编写前准备-》
添加POI 4.0.1 maven依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springbootemaildemo</groupId> <artifactId>springboot-email-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-email-demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.41</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.8.3</version> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency> <!--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> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
example-01.xlsx 文件 ,excel数据准备:
上代码:
DataVo(封装数据VO类)
package com.springbootemaildemo.excel.b; /** * 读取Excel时,封装读取的每一行的数据 */ public class DataVo { /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
ExcelReader(主要读取excel文件代码类)
修改部分加了红色字体
package com.springbootemaildemo.excel.b; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; 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.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; /** * 读取Excel内容 */ public class ExcelReader { private static final Logger logger = LoggerFactory.getLogger(ExcelReader.class); private static final String XLS = "xls"; private static final String XLSX = "xlsx"; /** * 根据文件后缀名类型获取对应的工作簿对象 * * @param inputStream 读取文件的输入流 * @param fileType 文件后缀名类型(xls或xlsx) * @return 包含文件数据的工作簿对象 * @throws IOException */ public static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException { Workbook workbook = null; if (fileType.equalsIgnoreCase(XLS)) { workbook = new HSSFWorkbook(inputStream); } else if (fileType.equalsIgnoreCase(XLSX)) { workbook = new XSSFWorkbook(inputStream); } return workbook; } /** * 读取Excel文件内容 * * @param file 上传的Excel文件 * @return 读取结果列表,读取失败时返回null */ public static List<DataVo> readExcel(MultipartFile file) { Workbook workbook = null; try { // 获取Excel后缀名 String fileName = file.getOriginalFilename(); if (fileName == null || fileName.isEmpty() || fileName.lastIndexOf(".") < 0) { logger.warn("解析Excel失败,因为获取到的Excel文件名非法!"); return null; } String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()); // 获取Excel工作簿 workbook = getWorkbook(file.getInputStream(), fileType); // 读取excel中的数据 List<DataVo> resultDataList = parseExcel(workbook); return resultDataList; } catch (Exception e) { logger.warn("解析Excel失败,文件名:" + file.getOriginalFilename() + " 错误信息:" + e.getMessage()); return null; } finally { try { if (null != workbook) { workbook.close(); } } catch (Exception e) { logger.warn("关闭数据流出错!错误信息:" + e.getMessage()); return null; } } } /** * 解析Excel数据 * * @param workbook Excel工作簿对象 * @return 解析结果 */ private static List<DataVo> parseExcel(Workbook workbook) { List<DataVo> resultDataList = new ArrayList<>(); // 解析sheet int numberOfSheets = workbook.getNumberOfSheets(); for (int sheetNum = 0; sheetNum < numberOfSheets; sheetNum++) { Sheet sheet = workbook.getSheetAt(sheetNum); // 校验sheet是否合法 if (sheet == null) { continue; } // 获取第一行数据 int firstRowNum = sheet.getFirstRowNum(); Row firstRow = sheet.getRow(firstRowNum); if (null == firstRow) { logger.warn("解析Excel失败,在第一行没有读取到任何数据!"); } // 解析每一行的数据,构造数据对象 int rowStart = firstRowNum + 1; int rowEnd = sheet.getPhysicalNumberOfRows(); for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) { Row row = sheet.getRow(rowNum); if (null == row) { continue; } DataVo resultData = convertRowToData(row); if (null == resultData) { logger.warn("第 " + row.getRowNum() + "行数据不合法,已忽略!"); continue; } resultDataList.add(resultData); } } return resultDataList; } /** * 将单元格内容转换为字符串 * * @param cell * @return */ private static String convertCellValueToString(Cell cell) { if (cell == null) { return null; } String returnValue = null; switch (cell.getCellType()) { case NUMERIC: //数字 Double doubleValue = cell.getNumericCellValue(); // 格式化科学计数法,取一位整数 DecimalFormat df = new DecimalFormat("0"); returnValue = df.format(doubleValue); break; case STRING: //字符串 returnValue = cell.getStringCellValue(); break; case BOOLEAN: //布尔 Boolean booleanValue = cell.getBooleanCellValue(); returnValue = booleanValue.toString(); break; case BLANK: // 空值 break; case FORMULA: // 公式 returnValue = cell.getCellFormula(); break; case ERROR: // 故障 break; default: break; } return returnValue; } /** * 提取每一行中需要的数据,构造成为一个结果数据对象 * <p> * 当该行中有单元格的数据为空或不合法时,忽略该行的数据 * * @param row 行数据 * @return 解析后的行数据对象,行数据错误时返回null */ private static DataVo convertRowToData(Row row) { DataVo resultData = new DataVo(); Cell cell; int cellNum = 0; // 获取姓名 cell = row.getCell(cellNum++); String name = convertCellValueToString(cell); resultData.setName(name); // 获取年龄 cell = row.getCell(cellNum++); String ageStr = convertCellValueToString(cell); if (StringUtils.isEmpty(ageStr)) { // 年龄为空 resultData.setAge(null); } else { resultData.setAge(Integer.parseInt(ageStr)); } return resultData; } }
Controller类,请求接口
package com.springbootemaildemo.excel.b; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.util.Date; import java.util.List; @Slf4j @RestController @RequestMapping("/excel/b") @Api("读取Excel") public class ExcelFileController { private static final Logger logger = LoggerFactory.getLogger(ExcelFileController.class); @PostMapping("/uploadExcel") @ApiOperation("uploadFile") public ResponseEntity<?> uploadFile(MultipartFile file) { // 检查前台数据合法性 if (null == file || file.isEmpty()) { logger.warn("上传的Excel商品数据文件为空!上传时间:" + new Date()); return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } try { // 解析Excel List<DataVo> readResult = ExcelReader.readExcel(file); //TODO 可以写相应的业务 if (CollectionUtils.isNotEmpty(readResult)) { readResult.stream().forEach(dataVo -> { System.out.println(dataVo.getName() + "-" + dataVo.getAge()); }); } return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { logger.warn("上传的Excel商品数据文件为空!上传时间:" + new Date()); return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } } }
结果: