读取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. 用eclipse开发需要准备什么?

    1.到eclipse的官网上,https://www.eclipse.org/  下载好eclipse,安装好eclipse,修改eclipse.ini文件,把内存改大点,避免出现内存溢出的情况. [ ...

  2. FROM_UNIXTIME()时间戳转换函数

    前几天,工作用到了将时间戳转化成具体的时间(年月日 时:分:秒),出了一点问题,先看一下下面的sql语句: select *,FROM_UNIXTIME(created_at,'%Y-%m-%d %H ...

  3. laravel门面与服务提供者区别

    laravel门面模式与服务提供者区别 以 Laravel 自带的文件系统为例,在 config/app.php 的配置文件的 providers 数组中,注册了一个服务提供者: Illuminate ...

  4. mysql启动报错 "unknown variable 'defaults-file=/etc/my.cnf"

    使用指定的my.cnf,而不用默认的/etc/my.cnf文件,可以在启动时,在mysqld_safe后加上参数--default-file=/usr/local/server/mysql2/etc/ ...

  5. IntelliJ IDEA启动一个普通的java web项目的配置

    文:朱季谦 这是我很久以前刚开始用IntelliJ IDEA时记录的笔记,正好赶上最近离职了,可以有比较多的时间把以前的记录整理一下,可以让刚接触到IntelliJ IDEA的童鞋学习如何在Intel ...

  6. kafka controller脑裂(多个controller)问题

    问题:情况一:创建topic成功,但是produce的时候,却报unknown partition的错误,但zk上却显示了每个partition的leader信息:情况二: 给某个topic增加分区, ...

  7. AnimationClip压缩-动画文件压缩

    动画压缩方法一.常用方法1. Rig->Animation Type:改为Generic2. Animations->Anim.Compression:Optimal二.高级方法1. 去掉 ...

  8. [Windows] - DNS防污染工具Pcap_DNSProxy

    最近试过非常多的DNS防污染工具(包括:dnsforwarder.dnsforwarder.dnscrypt-proxy.SimpleDNSCrypt等),感觉这个Pcap_DNSProxy简单.快捷 ...

  9. Java自学-面向对象 方法

    Java类的方法 在LOL中,一个英雄可以做很多事情,比如超神,超鬼,坑队友 能做什么在类里面就叫做方法 示例 1 : 什么是方法 比如队友残血正在逃跑,你过去把路给别人挡住了,导致他被杀掉. 这就是 ...

  10. Java 8 in Action

    https://www.cnblogs.com/HelloDeveloper/p/11404523.html /** * @param args */public static void main(S ...