1.工具方法:
package com.visy.utils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.*;
import java.util.function.Function;
/**
* @author visy.wang
* @description: 基于poi的Excel读取器
* @date 2023/2/16 15:09
*/
public class ExcelReader {
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static List<Map<String,Object>> readToMapList(File file){
return readToList(file, null, null);
}
public static List<Map<String,Object>> readToMapList(File file, Integer sheetIndex){
return readToList(file, sheetIndex, null);
}
public static List<Map<String,Object>> readToMapList(File file, String sheetName){
return readToList(file, null, sheetName);
}
public static <T> List<T> readToEntityList(File file, Class<T> clazz){
return readToList(file, null, null, clazz);
}
public static <T> List<T> readToEntityList(File file, Integer sheetIndex, Class<T> clazz){
return readToList(file, sheetIndex, null, clazz);
}
public static <T> List<T> readToEntityList(File file, String sheetName, Class<T> clazz){
return readToList(file, null, sheetName, clazz);
}
public static List<Map<String,Object>> readToMapList(MultipartFile file){
return readToList(file, null, null);
}
public static List<Map<String,Object>> readToMapList(MultipartFile file, Integer sheetIndex){
return readToList(file, sheetIndex, null);
}
public static List<Map<String,Object>> readToMapList(MultipartFile file, String sheetName){
return readToList(file, null, sheetName);
}
public static <T> List<T> readToEntityList(MultipartFile file, Class<T> clazz){
return readToList(file, null, null, clazz);
}
public static <T> List<T> readToEntityList(MultipartFile file, Integer sheetIndex, Class<T> clazz){
return readToList(file, sheetIndex, null, clazz);
}
public static <T> List<T> readToEntityList(MultipartFile file, String sheetName, Class<T> clazz){
return readToList(file, null, sheetName, clazz);
}
private static List<Map<String,Object>> readToList(File file, Integer sheetIndex, String sheetName){
try (InputStream inputStream = getInputStream(file)){
String fileName = file.getName();//文件名
if (isExcelFile(fileName)) {
return readToList(isXlsx(fileName), inputStream, sheetIndex, sheetName);
}
System.out.println("文件格式不正确");
return Collections.emptyList();
}catch (IOException e){
System.out.println("文件读取失败:"+e.getMessage());
return Collections.emptyList();
}
}
private static <T> List<T> readToList(File file, Integer sheetIndex, String sheetName, Class<T> clazz){
try (InputStream inputStream = getInputStream(file)){
String fileName = file.getName();//文件名
if (isExcelFile(fileName)) {
return readToList(isXlsx(fileName), inputStream, sheetIndex, sheetName, clazz);
}
System.out.println("文件格式不正确");
return Collections.emptyList();
}catch (IOException e){
System.out.println("文件读取失败:"+e.getMessage());
return Collections.emptyList();
}
}
private static List<Map<String,Object>> readToList(MultipartFile file, Integer sheetIndex, String sheetName){
try (InputStream inputStream = getInputStream(file)){
String fileName = file.getOriginalFilename();
if (isExcelFile(fileName)) {
return readToList(isXlsx(fileName), inputStream, sheetIndex, sheetName);
}
System.out.println("文件格式不正确");
return Collections.emptyList();
}catch (IOException e){
System.out.println("文件读取失败:"+e.getMessage());
return Collections.emptyList();
}
}
private static <T> List<T> readToList(MultipartFile file, Integer sheetIndex, String sheetName, Class<T> clazz){
try (InputStream inputStream = getInputStream(file)){
String fileName = file.getOriginalFilename();
if (isExcelFile(fileName)) {
return readToList(isXlsx(fileName), inputStream, sheetIndex, sheetName, clazz);
}
System.out.println("文件格式不正确");
return Collections.emptyList();
}catch (IOException e){
System.out.println("文件读取失败:"+e.getMessage());
return Collections.emptyList();
}
}
private static List<Map<String,Object>> readToList(boolean isXlsx, InputStream inputStream,
Integer sheetIndex, String sheetName){
return readToList(isXlsx, inputStream, sheetIndex, sheetName, Function.identity());
}
private static <T> List<T> readToList(boolean isXlsx, InputStream inputStream,
Integer sheetIndex, String sheetName, Class<T> clazz){
return readToList(isXlsx, inputStream, sheetIndex, sheetName, mp -> mapToEntity(mp, clazz));
}
/**
* 通过输入流读取Excel
* @param inputStream 输入流
* @param sheetIndex sheet下标(从0开始,优先级高于“sheetName”)
* @param sheetName sheet名称 sheetIndex和sheetName都为空时读取所有的Sheet
* @param f 将行数据映射为一个实体的转换器函数
* @return 数据列表
* @param <T> 行数据实体类型
*/
private static <T> List<T> readToList(boolean isXlsx, InputStream inputStream,
Integer sheetIndex, String sheetName, Function<Map<String,Object>,T> f){
try(Workbook wb = isXlsx ? (new XSSFWorkbook(inputStream)) : (new HSSFWorkbook(inputStream))){
int numberOfSheets = wb.getNumberOfSheets();
if(Objects.nonNull(sheetIndex)){
if(sheetIndex<0 || sheetIndex>=numberOfSheets){
return Collections.emptyList();
}
return readSheet(wb.getSheetAt(sheetIndex), f);
}else if(StringUtils.isNotBlank(sheetName)){
return readSheet(wb.getSheet(sheetName), f);
}else {
List<T> list = new ArrayList<>();
for(int i=0; i<numberOfSheets; i++){
list.addAll(readSheet(wb.getSheetAt(i), f));
}
return list;
}
}catch (IOException e){
System.out.println("Excel读取出错:"+ e.getMessage());
return Collections.emptyList();
}
}
private static <T> List<T> readSheet(Sheet sheet, Function<Map<String,Object>,T> f){
List<T> list = new ArrayList<>();
if(Objects.isNull(sheet)){
return list;
}
System.out.println("正在读取Sheet: "+sheet.getSheetName());
Row titles = sheet.getRow(0);
for (int rowIndex=1; rowIndex<sheet.getPhysicalNumberOfRows(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (Objects.isNull(row)){
continue;
}
Map<String,Object> item = new HashMap<>();
for(int colIndex=0; colIndex<titles.getPhysicalNumberOfCells(); colIndex++){
String colName = titles.getCell(colIndex).getStringCellValue();
Cell cell = row.getCell(colIndex);
Object cellVal = readCellVal(cell);
item.put(colName, cellVal);
}
list.add(f.apply(item));
}
return list;
}
//读取单元格的值,写得比较简单,可进一步修改
//建议cell.setCellType(CellType.STRING);
//然后统一按String读取:cell.getStringCellValue();
private static Object readCellVal(Cell cell){
if(Objects.isNull(cell)){
return null;
}
CellType type = cell.getCellTypeEnum();
if(CellType.STRING.equals(type)){
return cell.getStringCellValue();
}else if(CellType.NUMERIC.equals(type)){
return cell.getNumericCellValue();
//return cell.getDateCellValue();
}else if (CellType.BOOLEAN.equals(type)){
return cell.getBooleanCellValue();
}else if (CellType.BLANK.equals(type)){
return null;
}else if (CellType.FORMULA.equals(type)){
return cell.getCellFormula();
}else if (CellType.ERROR.equals(type)){
return cell.getErrorCellValue();
}else {
return null;
}
}
private static boolean isExcelFile(String fileName){
return fileName.endsWith(".xls") || fileName.endsWith(".xlsx");
}
private static InputStream getInputStream(File file) throws IOException {
return Files.newInputStream(file.toPath());
}
private static InputStream getInputStream(MultipartFile file) throws IOException {
return file.getInputStream();
}
private static boolean isXlsx(String fileName){
return Objects.nonNull(fileName) && fileName.endsWith(".xlsx");
}
private static <T> T mapToEntity(Map<String,Object> mp, Class<T> clazz){
//实际使用也可以:
//自定义注解添加到类T的字段上
//通过clazz反射及注解生成T的实体并写入字段值
//反射可考虑缓存中间量
//此处直接使用JSON工具,字段名需和表格标题名对应,不一样需注解标注
return objectMapper.convertValue(mp, clazz);
}
}
2.测试类:
package com.visy.utils.test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.visy.utils.ExcelReader;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author visy.wang
* @description:
* @date 2023/2/17 15:27
*/
public class ExcelReaderTest {
public static void main(String[] args) throws IOException {
//excel存在“id”,“address”, "flag"等标题的列
String path = "E:\\test\\data.xlsx";
File file = new File(path);
//读取第一个sheet的数据到Map列表
List<Map<String,Object>> mapList = ExcelReader.readToMapList(file, 0);
//List<Map<String,Object>> mapList = ExcelReader.readToMapList(file, "Sheet1");
System.out.println("mapList记录数:"+mapList.size());
mapList.forEach(System.out::println);
System.out.println("-----------------------------------");
//读取第一个sheet的数据到Entity实体列表
List<Entity> entityList = ExcelReader.readToEntityList(file, 0, Entity.class);
//List<Entity> entityList = ExcelReader.readToEntityList(file, "Sheet1", Entity.class);
System.out.println("entityList记录数:"+entityList.size());
entityList.forEach(System.out::println);
}
static class Entity{
private Long id;
private String address;
@JsonProperty("flag") //标注别名
private Integer flaggg;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getFlaggg() {
return flaggg;
}
public void setFlaggg(Integer flaggg) {
this.flaggg = flaggg;
}
@Override
public String toString() {
return "Entity{" +
"address='" + address + '\'' +
", id=" + id +
", flaggg=" + flaggg +
'}';
}
}
}
3.打印:
略。