栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot实现Excel读取的实例教程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot实现Excel读取的实例教程

前言

这是本人写的一个SpringBoot对Excel读取的方法,实测能用,待提升的地方有很多,有不足之处请多多指点。

Excel2003版(后缀为.xls)最大行数是65536行,最大列数是256列。

Excel2007以上的版本(后缀为.xlsx)最大行数是1048576行,最大列数是16384列。

提供2种方法读取:

1.根据指定的开始和结束行数读取返回结果,结果格式为List>

2.根据指定的开始和结束行数读取返回结果,结果格式为List

请根据实际内存堆可用大小进行读取,太多可进行分段读取(类似分页的原理)

读取Excel所需要的几个类

1.在pom.xml加上依赖

 
  org.apache.poi
  poi
  4.0.1
 
 
  org.apache.poi
  poi-ooxml
  4.0.1
 

2.ExcelPOJO实体类
package com.cly.utils.Excel;



public class ExcelPOJO {
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getPasswork() {
 return passwork;
 }
 public void setPasswork(String passwork) {
 this.passwork = passwork;
 }
 public String getLook() {
 return look;
 }
 public void setLook(String look) {
 this.look = look;
 }
 
 @excelRescoure(value = "XM")
 private String name;
 @excelRescoure(value = "SFZH")
 private String passwork;
 @excelRescoure()
 private String look;
 
 @Override
 public String toString(){
 return "name:"+this.getName()+",passwork:"+this.getPasswork()+",look:"+this.getLook();
 }
 public ExcelPOJO() {}
}
3.@interface自定义注解(用于实体类读取)
package com.cly.utils.Excel;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface excelRescoure {
 String value() default "";//默认为空
}
4.excelRead类(读取Excel数据类)有很多冗余的代码,可抽离出来
package com.cly.utils.Excel;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
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 javax.xml.transform.Source;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.*;
import java.text.DecimalFormat;
import java.util.*;


public class excelRead {
 //日志输出
 private static Logger logger = LoggerFactory.getLogger(excelRead.class);
 //定义excel类型
 private static final String XLS = "xls";
 private static final String XLSX = "xlsx";

 
 private static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {
 //用自带的方法新建工作薄
 Workbook workbook = WorkbookFactory.create(inputStream);
 //后缀判断有版本转换问题
 //Workbook workbook = null;
 //if (fileType.equalsIgnoreCase(XLS)) {
 // workbook = new HSSFWorkbook(inputStream);
 //} else if (fileType.equalsIgnoreCase(XLSX)) {
 // workbook = new XSSFWorkbook(inputStream);
 //}
 return workbook;
 }


 
 private static String convertCellValueToString(Cell cell) {
 if (cell == null) {
  return null;
 }
 String returnValue = null;
 switch (cell.getCellType()) {
  case NUMERIC: //数字
  Double doublevalue = cell.getNumericCellValue();
  // 格式化科学计数法,取一位整数,如取小数,值如0.0,取小数点后几位就写几个0
  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;
 }

 
 private static List> HandleData(Workbook workbook, int StatrRow, int EndRow, boolean ExistTop) {
 //声明返回结果集result
 List> result = new ArrayList<>();
 //声明一个Excel头部函数
 ArrayList top = new ArrayList<>();
 //解析sheet(sheet是Excel脚页)
 
 for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
  Sheet sheet = workbook.getSheetAt(sheetNum);
  // 校验sheet是否合法
  if (sheet == null) {
  continue;
  }
  //如存在头部,处理头部数据
  if (ExistTop) {
  int firstRowNum = sheet.getFirstRowNum();
  Row firstRow = sheet.getRow(firstRowNum);
  if (null == firstRow) {
   logger.warn("解析Excel失败,在第一行没有读取到任何数据!");
  }
  for (int i = 0; i < firstRow.getLastCellNum(); i++) {
   top.add(convertCellValueToString(firstRow.getCell(i)));
  }
  }
  //处理Excel数据内容
  int endRowNum;
  //获取结束行数
  if (EndRow == -1) {
  endRowNum = sheet.getPhysicalNumberOfRows();
  } else {
  endRowNum = EndRow <= sheet.getPhysicalNumberOfRows() ? EndRow : sheet.getPhysicalNumberOfRows();
  }
  //遍历行数
  for (int i = StatrRow - 1; i < endRowNum; i++) {
  Row row = sheet.getRow(i);
  if (null == row) {
   continue;
  }
  Map map = new HashMap<>();
  //获取所有列数据
  for (int y = 0; y < row.getLastCellNum(); y++) {
   if (top.size() > 0) {
   if (top.size() >= y) {
    map.put(top.get(y), convertCellValueToString(row.getCell(y)));
   } else {
    map.put(String.valueOf(y + 1), convertCellValueToString(row.getCell(y)));
   }
   } else {
   map.put(String.valueOf(y + 1), convertCellValueToString(row.getCell(y)));
   }
  }
  result.add(map);
  }
 }
 return result;
 }

 
 public static List> ReadExcelByRC(String fileName, int StatrRow, int EndRow, boolean ExistTop) {
 //判断输入的开始值是否少于等于结束值
 if (StatrRow > EndRow && EndRow != -1) {
  logger.warn("输入的开始行值比结束行值大,请重新输入正确的行数");
  List> error = null;
  return error;
 }
 //声明返回的结果集
 List> result = new ArrayList<>();
 //声明一个工作薄
 Workbook workbook = null;
 //声明一个文件输入流
 FileInputStream inputStream = null;
 try {
  // 获取Excel后缀名,判断文件类型
  String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
  // 获取Excel文件
  File excelFile = new File(fileName);
  if (!excelFile.exists()) {
  logger.warn("指定的Excel文件不存在!");
  return null;
  }
  // 获取Excel工作簿
  inputStream = new FileInputStream(excelFile);
  workbook = getWorkbook(inputStream, fileType);
  //处理Excel内容
  result = HandleData(workbook, StatrRow, EndRow, ExistTop);
 } catch (Exception e) {
  logger.warn("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage());
 } finally {
  try {
  if (null != workbook) {
   workbook.close();
  }
  if (null != inputStream) {
   inputStream.close();
  }
  } catch (Exception e) {
  logger.warn("关闭数据流出错!错误信息:" + e.getMessage());
  return null;
  }
 }
 return result;
 }




 
 public static List ReadExcelByPOJO(String fileName, int StatrRow, int EndRow, Class t) throws InvocationTargetException, IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException {
 //判断输入的开始值是否少于等于结束值
 if (StatrRow > EndRow && EndRow != -1) {
  logger.warn("输入的开始行值比结束行值大,请重新输入正确的行数");
  List error = null;
  return error;
 }
 //声明返回的结果集
 List result = new ArrayList<>();
 //声明一个工作薄
 Workbook workbook = null;
 //声明一个文件输入流
 FileInputStream inputStream = null;
 try {
  // 获取Excel后缀名,判断文件类型
  String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
  // 获取Excel文件
  File excelFile = new File(fileName);
  if (!excelFile.exists()) {
  logger.warn("指定的Excel文件不存在!");
  return null;
  }
  // 获取Excel工作簿
  inputStream = new FileInputStream(excelFile);
  workbook = getWorkbook(inputStream, fileType);
  //处理Excel内容
  result = HandleDataPOJO(workbook, StatrRow, EndRow, t);
 } catch (Exception e) {
  logger.warn("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage());
 } finally {
  try {
  if (null != workbook) {
   workbook.close();
  }
  if (null != inputStream) {
   inputStream.close();
  }
  } catch (Exception e) {
  logger.warn("关闭数据流出错!错误信息:" + e.getMessage());
  return null;
  }
 }
 return result;
 }


 
 private static  List HandleDataPOJO(Workbook workbook, int StatrRow, int EndRow, Class t) throws IntrospectionException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException {
 //声明返回的结果集
 List result = new ArrayList();
 //解析sheet(sheet是Excel脚页)
 for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
  Sheet sheet = workbook.getSheetAt(sheetNum);
  // 校验sheet是否合法
  if (sheet == null) {
  continue;
  }
  //获取头部数据
  //声明头部数据数列对象
  ArrayList top = new ArrayList<>();
  //获取Excel第一行数据
  int firstRowNum = sheet.getFirstRowNum();
  Row firstRow = sheet.getRow(firstRowNum);
  if (null == firstRow) {
  logger.warn("解析Excel失败,在第一行没有读取到任何数据!");
  return null;
  }
  for (int i = 0; i < firstRow.getLastCellNum(); i++) {
  top.add(convertCellValueToString(firstRow.getCell(i)));
  }
  //获取实体类的成原变量
  Map POJOfields = getPOJOFieldAndValue(t);
  //判断所需要的数据列
  Map exceltoPOJO = new HashMap<>();
  for (int i = 0; i < top.size(); i++) {
  if (POJOfields.get(top.get(i)) != null && !"".equals(POJOfields.get(top.get(i)))) {
   exceltoPOJO.put(String.valueOf(i), POJOfields.get(top.get(i)));
  }
  }
  
  int endRowNum;
  //获取结束行数
  if (EndRow == -1) {
  endRowNum = sheet.getPhysicalNumberOfRows();
  } else {
  endRowNum = EndRow <= sheet.getPhysicalNumberOfRows() ? EndRow : sheet.getPhysicalNumberOfRows();
  }
  List> mapList = new ArrayList<>();
  //遍历行数
  for (int i = StatrRow - 1; i < endRowNum; i++) {
  Row row = sheet.getRow(i);
  if (null == row) {
   continue;
  }
  //获取需要的列数据
  t texcel = (t) t.newInstance();
  for (Map.Entry map : exceltoPOJO.entrySet()) {
   //获取Exceld对应列的数据
   String celldata = convertCellValueToString(row.getCell(Integer.parseInt(map.getKey())));
   //使用发射
   //获取实体类T中指定成员变量的对象
   PropertyDescriptor pd = new PropertyDescriptor((String) map.getValue(), texcel.getClass());
   //获取成员变量的set方法
   Method method = pd.getWriteMethod();
   //判断成员变量的类型
   Field field = texcel.getClass().getDeclaredField((String) map.getValue());
   String object = field.getGenericType().getTypeName();
   if (object.endsWith("String")) {
   //执行set方法
   method.invoke(texcel, celldata);
   }
   if (object.endsWith("Double")) {
   Double middata = Double.valueOf(celldata);
   //执行set方法
   method.invoke(texcel, middata);
   }
   if (object.endsWith("Float")) {
   Float middata = Float.valueOf(celldata);
   //执行set方法
   method.invoke(texcel, middata);
   }
   if (object.endsWith("Integer")) {
   Integer middata = Integer.parseInt(celldata);
   //执行set方法
   method.invoke(texcel, middata);
   }
  }
  result.add(texcel);
  }
 }
 return result;
 }

 
 private static Map getPOJOFieldAndValue(Class T) {
 //声明返回结果集
 Map result = new HashMap<>();
 Field[] fields = T.getDeclaredFields();//获取属性名
 if (fields != null) {
  for (Field field : fields) {
  excelRescoure Rescoure = field.getAnnotation(excelRescoure.class);
  if (Rescoure.value() != null && !"".equals(Rescoure.value())) {
   result.put(Rescoure.value(), field.getName());
  }
  }
 } else {
  logger.warn("实体类:" + T + "不存在成员变量");
  return null;
 }
 return result;
 }
}


5.测试类

package com.cly.utils.Excel;

import java.util.*;



public class Readtest {
public static void main(String[] args) throws Exception {
 
 List> result =excelRead.ReadExcelByRC("D:.xls",2,10,false);
 System.out.println(result.size());
 System.out.println(result);

 
 List result2 = excelRead.ReadExcelByPOJO("D:.xls",2,10,ExcelPOJO.class);
 System.out.println(result2.size());
 System.out.println(result2);
 }
}
 


6.运行结果和说明

exce表格数据

方法一的运行结果

1.ture:key为列名

2.false:key为第几列列数

方法二的运行结果

实体类的所有成员变量一定要加上自定义注释@excelRescoure,不然会报错


还有很多不足的地方,请多多指点,希望能给你带来帮助。

SpringBoot实现内存数据导出成Excel在另一篇文章 文章地址:https://www.jb51.net/article/202767.htm

总结

到此这篇关于SpringBoot实现Excel读取的文章就介绍到这了,更多相关SpringBoot实现Excel读取内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号