读取Excel

思路:先读取整个Excel,即工作簿,再依次读取其中的每个工作表Sheet,最后读取工作表内的表格。

一、读取工作簿
利用流读取指定目录中的工作簿,并写入内存。

   /**
* Constructs a XSSFWorkbook object, by buffering the whole stream into memory
* and then opening an {@link OPCPackage} object for it.
*
* <p>Using an {@link InputStream} requires more memory than using a File, so
* if a {@link File} is available then you should instead do something like
* <pre><code>
* OPCPackage pkg = OPCPackage.open(path);
* XSSFWorkbook wb = new XSSFWorkbook(pkg);
* // work with the wb object
* ......
* pkg.close(); // gracefully closes the underlying zip file
* </code></pre>
*/
public XSSFWorkbook(InputStream is) throws IOException {
super(PackageHelper.open(is)); beforeDocumentRead(); // Build a tree of POIXMLDocumentParts, this workbook being the root
load(XSSFFactory.getInstance()); // some broken Workbooks miss this...
if(!workbook.isSetBookViews()) {
CTBookViews bvs = workbook.addNewBookViews();
CTBookView bv = bvs.addNewWorkbookView();
bv.setActiveTab(0);
}
}

针对源码,先生产InputStream,再读取:

InputStream is = new FileInputStream(filePath);
XSSFWorkbook workbook = new XSSFWorkbook(is);

二、读取工作薄中工作表,依次读取,先要知道到底有几个? 此处,需要对XSSFWorkbook类有基本的了解。(建议看一下源码)

int countSheet = workbook.getNumberOfSheets();

for循环读取每个工作表。
思考:需要怎样的数据结构才能优雅的存放其中的数据?
思考一下工作表中存放的数据:主流的是表格和表格下的数据。
进一步思考这个表格的数据用什么样的数据结构?
表格进一步分析,表格有表头和非表头数据组成,由于表头需要对应实体映射,需要单独处理。
因此表头采用Map存储(此处下面需要继续分析),同样一行数据也用Map处理,多行数据放入List
至此:工作表的数据结构清晰了。

表头:Map<String,object>;
非数据多行:List<Map,Object>;

工作表名称:String;

/**
* Excel解析后相关的Excel
* <一句话功能简述>
* <功能详细描述>
*
* @author
* @version [版本号, 2019年6月26日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class ExcelSheetStruct { /**
* sheet页名称
*/
private String sheetName; /**
* 列表表头
*/
private Map<String,String> headerMap; /**
* 列表数据
*/
private List<Map<String,Object>> data;
// 省略get和set
}

三、工作表的数据读取

for (int numSheet = 0; numSheet < countSheet; numSheet++) {
// 获取Sheet,创建Sheet数据结构
XSSFSheet xssfSheet = workbook.getSheetAt(numSheet);
ExcelSheetStruct excelSheetStruct = new ExcelSheetStruct();
excelSheetStruct.setSheetName(xssfSheet.getSheetName());
}

再获取表格数据,先得获取有效区域。
思考:到底是先从行开始,还是先从列开始,即第一维度是行还是列?
此处先从行开始,因为行在Sheet中是数字。(注:有效行是当前行数字减1)

//处理有数据区域的表格
int firstRowNum = xssfSheet.getFirstRowNum();
int lastRowNum = xssfSheet.getLastRowNum();
// 处理表头和非表头,第一维度“行”
for (int row = firstRowNum; row <= lastRowNum; row++) {}

再for循环内,获取列号(第二维度),就能唯一定位到数据,进行获取。
这边先获取表头

    /**
* 根据所给的首行,生成具体的数据结构
* <一句话功能简述>
* <功能详细描述>
* @param xssfRow
* @return
* @see [类、类#方法、类#成员]
* @author
*/
public static Map<String, String> generateHeadLine(XSSFRow xssfRow) {
Map<String, String> headerMap = new HashMap<>();
// 获取开始列和结束列
int firstCellNum = xssfRow.getFirstCellNum();
int lastCellNum = xssfRow.getLastCellNum();
for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++) {
Cell cell = xssfRow.getCell(cellNum, XSSFRow.CREATE_NULL_AS_BLANK);
// key——列号,value——数据
headerMap.put(String.valueOf(cellNum), cell.getStringCellValue());
}
return headerMap;
}

同理,获取非表头。此处把表头和下面列的数据进行关联。即Map<String,Object> = HashMap<"表头","表头当前列下面的一个数据(当前cell的值)">

    /**
* 对数据行的处理,根据头行数据,将数据与行列表结合起来
* <一句话功能简述>
* <功能详细描述>
* @param xssfRow
* @return
* @see [类、类#方法、类#成员]
* @author
*/
public static Map<String, Object> generateDataLine(XSSFRow xssfRow, Map<String, String> headerLine) {
Map<String, Object> mapDate = new HashMap<>();
// 此处也是读取列,用上面有不同之处,这边不是顺序读取,是按照表头存储的数据的key(列号)
for (String key : headerLine.keySet()) {
Cell cell = xssfRow.getCell(Integer.parseInt(key), XSSFRow.CREATE_NULL_AS_BLANK);
cell.setCellType(Cell.CELL_TYPE_STRING);
// HashMap<"表头的值","当前的值">
mapDate.put(headerLine.get(key), cell.getStringCellValue());
}
return mapDate;
}

读取完一行非表头数据需要继续读取,最后添加到非标头数据结构中List<Map>;

//循环处理该sheet页中的单行数据
for (int row = firstRowNum; row <= lastRowNum; row++) {
XSSFRow xssfRow = xssfSheet.getRow(row);
if (row == firstRowNum) {
// 处理完表头数据,把它添加到Sheet中
excelSheetStruct.setHeaderMap(generateHeadLine(xssfRow));
continue;
}
Map<String, Object> dateLine = generateDataLine(xssfRow, excelSheetStruct.getHeaderMap());
// 整合非表头数据
dataList.add(dateLine);
}
// 处理完非表头数据,把它添加到Sheet中
allDataList.add(excelSheetStruct);

至此数据单个Sheet处理完毕,回顾代码:

/**
* 读取Excel生成相应的数据集
* <一句话功能简述>
* <功能详细描述>
* @param filePath
* @return
* @throws IOException
* @see [类、类#方法、类#成员]
* @author
*/
public static List<ExcelSheetStruct> readXlsx(String filePath)
throws IOException { List<ExcelSheetStruct> allDataList = new ArrayList<>();
XSSFWorkbook workbook = null;
InputStream is = new FileInputStream(filePath);
workbook = new XSSFWorkbook(is);
int countSheet = workbook.getNumberOfSheets(); for (int numSheet = 0; numSheet < countSheet; numSheet++) {
ExcelSheetStruct excelSheetStruct = new ExcelSheetStruct();
List<Map<String, Object>> dataList = new ArrayList<>();
excelSheetStruct.setData(dataList); XSSFSheet xssfSheet = workbook.getSheetAt(numSheet);
excelSheetStruct.setSheetName(xssfSheet.getSheetName()); //处理有数据区域的表格
int firstRowNum = xssfSheet.getFirstRowNum();
int lastRowNum = xssfSheet.getLastRowNum(); if (lastRowNum == 0) {
continue;
} //循环处理该sheet页中的单行数据
for (int row = firstRowNum; row <= lastRowNum; row++) {
XSSFRow xssfRow = xssfSheet.getRow(row);
if (row == firstRowNum) {
excelSheetStruct.setHeaderMap(generateHeadLine(xssfRow));
continue;
}
Map<String, Object> dateLine = generateDataLine(xssfRow, excelSheetStruct.getHeaderMap());
dataList.add(dateLine);
}
allDataList.add(excelSheetStruct);
}
workbook.close();
is.close();
return allDataList; }

导入Excel——解析Excel的更多相关文章

  1. oracle xmltype导入并解析Excel数据--前言

    通常,很多的时候,我们需要导入Excel数据到系统中,但是Excel数据需要我们去各种校验,比如身份证校验,手机号码校验等等. 校验失败的数据,提供Excel导出错误原因,提示给用户. 如此,如果校验 ...

  2. oracle xmltype导入并解析Excel数据 (四)特别说明

    1.Excel导出,此处没有给出 2.错误原因在中间表,T_EXCEL_IMPORT_GENERATION,其中errormsg不为空的数据 3,中间表入库过程: 需要自己实现,为一个存储过程,存储过 ...

  3. oracle xmltype导入并解析Excel数据 (一)创建表与序

    表说明: T_EXCEL_IMPORT_DATASRC: Excel数据存储表,(使用了xmltype存储Excel数据) 部分字段说明: BUSINESSTYPE: Excel模板类型,一个Exce ...

  4. oracle xmltype导入并解析Excel数据 (三)解析Excel数据

    包声明 create or replace package PKG_EXCEL_UTILS is -- Author: zkongbai-- Create at: 2016-07-06-- Actio ...

  5. oracle xmltype导入并解析Excel数据 (二)规则说明

    规则表字段说明如下: 其中RULE_FUNC_CUSTOMIZE表示,用户自己写函数,去判断数据是否合法,存储的是函数的名字 此函数的参数只有一个,该列的值,字段类型是Varchar2, 校验失败的话 ...

  6. 利用 js-xlsx 实现 Excel 文件导入并解析Excel数据成json格式的数据并且获取其中某列数据

    演示效果参考如下:XML转JSON 另一个搭配SQL实现:http://sheetjs.com/sexql/index.html 详细介绍: 1.首先需要导入js <script src=&qu ...

  7. 导入Excel——解析Excel——优化

    package com.it.excel.excelLearn; import java.io.FileInputStream; import java.io.IOException; import ...

  8. oracle xmltype导入并解析Excel数据 (五)中间表数据入库

    此处给出例子,具体根据业务需求 create or replace procedure P_CART_Sheet1(p_id in NUMBER) is--车辆管理功能v_str varchar2(4 ...

  9. Excel解析与导入导出

    第三次结对编程作业 结对成员: 031302610黄志鹏 031302603 陈波 功能分析 1.将初始排课表excel导入系统数据库 2.将系统数据库的排课数据显示在web界面 实现思路 一.实现将 ...

随机推荐

  1. html5 audio标签切换播放音乐的方法

    html5 audio标签切换播放音乐的方法<pre><audio id="music1" preload loop="loop">&l ...

  2. Docker中nginx+tomcat实现负载均衡

    拉取tomcat镜像 docker pull tomcat 运行两个tomcat容器 docker run -d -p 8088:8080 --name tomcat8088 tomcat docke ...

  3. 线程互斥synchronized

    /** * * 线程互斥,采用synchronized关键字可以实现线程与线程之间的互斥,要注意的是在synchronized上的对象要是同一个,才可以 * 保证在同一时刻,只有一个线程可以执行syn ...

  4. [转帖]Kubesphere all-in-one 安装方式.

    All-in-One 模式 对于首次接触 KubeSphere 高级版的用户,想寻找一个最快安装和体验 KubeSphere 高级版核心功能的方式,all-in-one 模式支持一键安装 KubeSp ...

  5. switch/case/default中的雷区

    switch的语法如下: switch(表达式){ case常量表达式1: 语句1;break; case常量表达式2: 语句2;break; - case常量表达式n: 语句n;break; def ...

  6. reactiveX沉思(草稿)

    一.第一性原理 将异步的io.事件解释为observable.并借用observer的一些类概念进行处理. ReactiveX is a library for composing asynchron ...

  7. kubectl rollout回滚和autoscale自动扩容

    系列目录 kubernetes 滚动升级 Kubernetes 中采用ReplicaSet(简称RS)来管理Pod.如果当前集群中的Pod实例数少于目标值,RS 会拉起新的Pod,反之,则根据策略删除 ...

  8. SQL Server 2017 下载及安装详细教程

    SQL Servicer 2017 下载及安装 1)下载安装SQLServer 2)安装SQLServer management Studio. 一.     下载及安装SQLServer 下载链接( ...

  9. python爬虫---scrapy框架爬取图片,scrapy手动发送请求,发送post请求,提升爬取效率,请求传参(meta),五大核心组件,中间件

    # settings 配置 UA USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, l ...

  10. 突破Java面试-Redis集群模式的原理

    1 面试题 Redis集群模式的工作原理说一下?在集群模式下,key是如何寻址的?寻址都有哪些算法?了解一致性hash吗? 2 考点分析 Redis不断在发展-Redis cluster集群模式,可以 ...