一、基于eventusermodel的excel解析工具类

这一部分和网上大部分的差不多,变化在二和三
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;public class ImportantUtil{private static final Logger logger = LogManager.getLogger(ImportantUtil.class);public ImportantUtil(ISheetContentHandler handler) {contentHandler=handler;}/*** 表格默认处理器*/private ISheetContentHandler contentHandler = null;/*** 读取数据*/private List<Object[]> data=new ArrayList<Object[]>();/*** 转换表格,默认为转换第一个表格* @param stream* @return* @throws InvalidFormatException* @throws IOException* @throws ParseException*/public List<Object[]> parse(InputStream stream)throws InvalidFormatException, IOException, ParseException {return parse(stream, 1);}/**** @param stream* @param sheetId:为要遍历的sheet索引,从1开始* @return* @throws InvalidFormatException* @throws IOException* @throws ParseException*/public synchronized List<Object[]> parse(InputStream stream, int sheetId)throws InvalidFormatException, IOException, ParseException {// 每次转换前都清空数据data.clear();// 打开表格文件输入流OPCPackage pkg = OPCPackage.open(stream);try {// 创建表阅读器XSSFReader reader;try {reader = new XSSFReader(pkg);} catch (OpenXML4JException e) {logger.error("读取表格出错");throw new ParseException(e.fillInStackTrace());}// 转换指定单元表InputStream sheetStream = reader.getSheet("rId"+sheetId);try {InputSource sheetSource = new InputSource(sheetStream);StylesTable styles = reader.getStylesTable();ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);getContentHandler().init(data);// 设置读取出的数据// 获取转换器XMLReader parser = getSheetParser(styles, strings);parser.parse(sheetSource);} catch (SAXException e) {logger.error("读取表格出错");throw new ParseException(e.fillInStackTrace());} finally {sheetStream.close();}} finally {pkg.close();}return data;}/*** 获取表格读取数据,获取数据前,需要先转换数据<br>* 此方法不会获取第一行数据** @return 表格读取数据*/public List<Object[]> getData() {return data;}/*** 获取读取表格的转换器** @return 读取表格的转换器* @throws SAXException* SAX错误*/protected XMLReader getSheetParser(StylesTable styles, ReadOnlySharedStringsTable strings) throws SAXException {XMLReader parser = XMLReaderFactory.createXMLReader();parser.setContentHandler(new XSSFSheetXMLHandler(styles, strings, getContentHandler(), false));return parser;}public  ISheetContentHandler getContentHandler(){return contentHandler;}public void setContentHandler(ISheetContentHandler contentHandler) {this.contentHandler = contentHandler;}/*** 表格转换错误*/public class ParseException extends Exception {private static final long serialVersionUID = -2451526411018517607L;public ParseException(Throwable t) {super("表格转换错误", t);}}
}

二、为了方便开发使用,下面新增一个接口和一个abstract类

import java.util.List;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;public interface ISheetContentHandler extends SheetContentsHandler {/*** 设置转换后的数据集,用于存放转换结果* @param datas*    转换结果*/public void init(List<Object []> datas);
}

之所以创建这么一个abstract类,就是为了方便在以后的开发的时候可以不用重复添加这些属性和方法,只抛出 cell 方法让子类去继承实现就行了。
其中,fieldsMap是我个人使用的一个用来翻译后台字段和前台展示字段的一个map集合,大家可按自己的需求删减。

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.springframework.beans.BeanUtils;public abstract class SheetContentHandler implements ISheetContentHandler {protected List<Object[]> data=null;protected ArrayList<String> columns = new ArrayList<String>();protected Map<String,String> fieldsMap;protected Object [] readRow=null;protected int columsLength;protected int rowIndex;public SheetContentHandler(Map<String,String> fieldsMap) {this.fieldsMap=fieldsMap;}@Overridepublic void init(List<Object []> datas) {this.data=datas;}@Overridepublic void startRow(int rowNum) {rowIndex=rowNum;
//      logger.info("开始解析第"+rowNum+"行。");
//      readRow=null;if (rowNum != 0) {readRow=new Object[columsLength];}}@Overridepublic void endRow(int rowNum) {//      System.out.println("第"+rowNum+"行解析结束。");if (rowNum == 0) {//表头 列columsLength=columns.size();}else {Object [] row=new Object[columsLength];BeanUtils.copyProperties(readRow, row);data.add(row);}readRow = null;}@Overridepublic void cell(String cellReference, String formattedValue, XSSFComment comment) {int colIndex = getCellIndex(cellReference);//转换A1,B1,C1等表格位置为真实索引位置handleCell(rowIndex,colIndex,formattedValue);}public abstract void handleCell(int rowIndex,int cellIndex, String cellValue);@Overridepublic void headerFooter(String text, boolean isHeader, String tagName) {}/*** 转换表格引用为列编号** @param cellReference*    列引用* @return 表格列位置,从0开始算*/protected int getCellIndex(String cellReference) {String ref = cellReference.replaceAll("\\d+", "");int num = 0;int result = 0;for (int i = 0; i < ref.length(); i++) {char ch = cellReference.charAt(ref.length() - i - 1);num = (int) (ch - 'A' + 1);num *= Math.pow(26, i);result += num;}return result - 1;}}

三、实现abstract类和最终调用

import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.poi.xssf.usermodel.XSSFComment;
import com.anjubao.advert.manage.utils.CommonUtil;public class Test {public static void main(String[] args) {Test test=new Test();test.test();}public void test() {try {String date1=CommonUtil.getFormat("yyyy-MM-dd HH:mm:ss").format(new Date());String filePath = "F:\\20210624XXX.xlsx";File file = new File(filePath);//  log.info("需要读取的文件fileName:{}", file.getName());FileInputStream inputStream = new FileInputStream(file);Map<String, String> fieldsMap=null;ImportantUtil util=new ImportantUtil(new TestSheetHandler(fieldsMap));List<Object []> datas=util.parse(inputStream);String date2=CommonUtil.getFormat("yyyy-MM-dd HH:mm:ss").format(new Date());System.out.println("开始时间:"+date1+"\t结束时间:"+date2+"\t读取行数:"+datas.size());} catch (Exception e) {e.printStackTrace();}}class TestSheetHandler extends SheetContentHandler{public TestSheetHandler(Map<String, String> fieldsMap) {super(fieldsMap);}@Overridepublic void handleCell(int rowIndex, int cellIndex, String cellValue) {String field=null;try {String colName=columns.get(cellIndex);if(colName!=null) {if(fieldsMap!=null) {field=fieldsMap.get(colName);}else {field=colName;}}if(readRow!=null) {//在这里可以开始处理数据了,符合要求的可以添加到data里面,不符合的可以在ResourcesSheetHandler添加集合收集起来另行处理}else {columns.set(cellIndex, field);}} catch (IndexOutOfBoundsException e) {int size = columns.size();for (int i = cellIndex - size+1;i>0;i--){columns.add(null);}columns.set(cellIndex,field);
//              logger.info(e.getMessage()+" "+e.getCause());}}}
}

做好上面的步骤之后,就可以在需要导入EXCEL文件的地方进行简单调用了,data的数据类型大家可以自行调节。

执行结果

开始时间:2021-06-24 17:50:54 结束时间:2021-06-24 17:51:36    读取行数:564780

如果这篇文章对你有用,可以点个赞再走吗。

使用POI读取EXCEL大文件时,在解析数据的过程中对数据完成处理转换相关推荐

  1. java读取excel大文件

    在读取excel大文件的时候就不能再使用poi包下面的Workbook类,会造成OOM等问题. 我们常见的excel分为xlsx格式和csv格式.分别实现一下. xlsx格式处理. 需要的pom依赖: ...

  2. 记录POI读取excel表格文件,空行校验

    如题,前几天在使用poi读取excel表时,有效数据行数只有几百行,但表格行数有几千行,结果调用sheet.getLastNum时空行也算在内了!本来解析读取就慢,现在更是浪费时间.查了一下终于看到一 ...

  3. POI读取excel百万级-SAX方式解析

    一. 简介 在excel解析的时候,采用SAX方方式会将excel转换为xml进行解析避免了内存溢出. 速度在3秒1W的数据写入,100W条记录,大概50M的数据,耗时大概4分半(如果不需要校验,可能 ...

  4. 用python的xlsxwriter库写EXCEL大文件时,内存占用过高

    用python的xlsxwriter库创建较大的Excel文件时,会占用过高的内存.很容易导致程序异常结束. 设置constant_memory属性后,就可以避免这个问题. 例: workbook = ...

  5. php 读取excel大文件,php 如何读大excel

    phper需要处理excel的时候基本上都会考虑PhpSpreadsheet,但是用过这个库的人都知道,这个库所需要的内存很大,关键是随着文件的增大,所需要的内存不断增大.测试过,导入2M的文exce ...

  6. golang 读取excel(xlsx文件) 时间格式解析

    问题起源 最近在写一个读取xlsx文件,并解析其中数据的项目,在所有的数据都就绪之后,却遇到了时间格式获取不正确的问题 时间格式 我查询到的结果 我的代码 func main() {f, err := ...

  7. POI事件模式读取Excel 2003文件

    一.概述 1. Excel 2003文件(即后缀为xls)是二进制文件,存储结构为复合文档,POI读取xls文件有两种方式 用户模式(usermodel):一次性将xls文件读入到内存,创建dom结构 ...

  8. java poi读取excel文件(xlsx)

    读取excel文件的方法有许多种,这篇文章主要描述通过poi读取excel文件. 先maven导入jar包 <dependency><groupId>org.apache.po ...

  9. Java使用POI读取Excel文件

    上篇文章记录了简单的POI创建Excel文件,依赖导入可参考上篇 POI读取excel中公式 @Testpublic void testRead() throws Exception {//读取文件的 ...

最新文章

  1. [转]设计模式(22)-Strategy Pattern
  2. C语言实现魔方阵代码及解析
  3. java需求设计_JavaWeb期末设计---需求分析文档. stage1
  4. 三国历史的教训读后感_历史上伟大的创新者的教训,你永远都不会忘记
  5. Objective-C:ARC自动释放对象内存
  6. abview查找范例时说 NI服务器未定位 这是怎么回事?
  7. 用matlab分析系统工程案例,系统工程ISMmatlab代码.doc
  8. DataTable 转换 DataSet
  9. linux虚拟主机用织梦,织梦程序用什么虚拟主机很服务器好
  10. 软件工程之软件概要设计
  11. 总结openstack nuetron网络架构图
  12. matlab评价模型和预测模型
  13. 2、idea热部署插件JRebel+2020年Jrebel激活码+Springboot web开发+Springboot配置文件详解+thymeleaf模板引擎的使用【Springboot】
  14. Eclipse中Outline里各种图标的含义
  15. 在css中sticky定位的特性,CSS定位属性sticky详解
  16. nginx events 模块配置
  17. Java代码实现阿里云视频上传
  18. 《wish官方运营手册》读书笔记
  19. 阿里云视频点播 播放出错啦,请尝试退出重试或刷新code:4400
  20. kdevelop快捷键

热门文章

  1. rj45 千兆接口定义_rj45接口定义,大神教你秒懂rj45的接线方法【详细方法】
  2. 敢不敢挑战,半年学好英语。
  3. 前端 100 问:能搞懂80%的请把简历给我
  4. 【MQ笔记】聊一聊空间(线性空间、赋范空间、度量空间、内积空间、欧氏空间、酉空间)
  5. mysql 按月和年累加_2020年5月播出的电视剧汇总,按时间先后顺序排列
  6. 一级市场二级化:区块链正在颠覆风险投资
  7. solidworks导出obj模型和mtl材质
  8. Train for kirara 总结
  9. php layui弹出修改功能,非常好用的弹出层 layer,常用功能demo,快速上手!
  10. Linux虚拟机增加sda容量