package com.haiyisoft.iecp.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
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.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
* excel读取数据
*
* @author 白亚龙
*
* <p>
* 2018-04-19 白亚龙 新建
* </p>
*/

public class ReadExceTool {

/**
* 导出Excel文件的信息 形式为:List<List<Object>> 支持格式为 : xlsx,xls
* 第一层list为文件sheet信息 第二层list为一个sheet页面的信息 第三层为sheet内容某一行的信息
* 文件信息由上自下由左自右查找
* 分数数据暂时只能读取成小数保存
* @param File 输入文件
* @param String 文件后缀
* @return List<List<Object>> (最内层object为一个List<Object>数组)
*/
public List<List<Object>> readExcel(File file, String extension) {
List<List<Object>> fileObject = new java.util.ArrayList<List<Object>>();
Workbook wb = null;
// 读取文件格式判断,如果是excel文件则返回Workbook实例
wb = readFile(file, extension);
if(wb != null){
// 循环sheet页面,添加第一层list
for(int numSheet = 0; numSheet < wb.getNumberOfSheets(); numSheet++){
Sheet sheet = wb.getSheetAt(numSheet);
if(sheet == null){
continue;
}
/**
* column: sheet页面最大列数;
* 根据 sheet页最大行,最大列对页面进行循环处理
*/
List<Object> sheetObjects = new ArrayList<Object>();
// 获取数据最小列数
int startColumn = getFirstColNum(sheet, sheet.getLastRowNum());
// 获取数据最大列数
int endColumn = getLastColNum(sheet, sheet.getLastRowNum());
// 根据最大行数进行循环,将行数据数据放入第二层list
for(int i =0; i <= sheet.getLastRowNum(); i++){
Row row = sheet.getRow(i);
List<Object> rowValues = new ArrayList<Object>();
// 空行忽略
if(row == null){
continue;
}else {
// 每行内根据最大列数循环,将单元数据数据放入第三层list
for(int j = startColumn; j < endColumn; j++){
Cell cell = row.getCell(j);
// 空单元忽略
String cellValue = null;
if(cell == null) continue;
// 判断是否为合并单元格
if(isMergedRegion(sheet, i, j)){
// 合并单元格取值(所有单元格取第一个单元格的值,跨列合并单元格 只取第一个数据)
cellValue = getMergedValue(sheet, i, j);
}else{
// 单元格取值
cellValue = getValue(cell);
}
// 如果是跨列合并单元格 只取第一个数据
if(cellValue != null && cellValue.equals("ignoredData"))continue;
else rowValues.add(cellValue);
}
if (rowValues.size()>0) {
sheetObjects.add(rowValues);
}
}
}
if (sheetObjects.size()>0) {
fileObject.add(sheetObjects);
}
}
/*//遍历解析出来的list (数据验证)
for (List<Object> sheetObjects : fileObject) {
for (Object rowObjects : sheetObjects) {
List<Object> cellValues = (List<Object>) rowObjects;
for (int i = 0; i < cellValues.size(); i++) {
System.out.print(cellValues.get(i) + ",");
}
System.out.println();
}
System.out.println();
}*/
}
return fileObject;
}

/**
* 求Excel某一工作簿0~某行内的最小列数
* @param sheet 工作簿
* @param rowNum 行数
* @return
*/
private static int getFirstColNum(Sheet sheet, int lastRowNum) {
if(sheet == null){
return 0;
}
// 初始值设置为一个较大的值
int firstCol = 1000;
Row row = null;
// 根据行循环,取第一个非空值的最小下标
for(int i = 0; i <= lastRowNum; i++){
row = sheet.getRow(i);
if(row != null){
for(int j = 0; j < row.getLastCellNum(); j++){
if(row.getCell(j) != null){
if(firstCol > j){
firstCol = j;
break;
}
}
}
}
}
return firstCol;
}

/**
* 求Excel某一工作簿0~某行内的最大列数
* @param sheet 工作簿
* @param rowNum 行数
* @return
*/
private static int getLastColNum(Sheet sheet, int rowNum) {
if(sheet == null ){
return 0;
}
int lastCol = 0;
Row row = null;
for(int i = 0; i <= rowNum; i++){
row = sheet.getRow(i);
if(row != null){
int temp = row.getLastCellNum();
if(temp > lastCol){
lastCol = temp;
}
}
}
return lastCol;
}

/**
* 获取合并单元格的值
* @param sheet 工作簿
* @param rowNum 单元行
* @param columnIndex 单元列
* @return Object 单元值
*/
private static String getMergedValue(Sheet sheet, int rowNum,
int columnIndex) {
// 获取合并单元格个数
int mergeNum = sheet.getNumMergedRegions();
String value = null;
// 循环判断单元格所在合并单元格,合并单元格内所有单元格赋相同的值
for(int i = 0; i < mergeNum; i++){
CellRangeAddress range = sheet.getMergedRegion(i);
// 数据依次为合并单元格的第一列、最后一列、第一行、最后一行
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
// 判断是否在次单元格区间内
if(rowNum >= firstRow && rowNum <= lastRow){
// 所有单元格取第一个单元格的值,跨列合并单元格 只取第一个数据
if(columnIndex == firstColumn){
value = getValue(sheet.getRow(firstRow).getCell(firstColumn));
}else if(columnIndex > firstColumn && columnIndex <= lastColumn){
value = "ignoredData";
}
}
}
return value;
}

/**
* 判断是不是合并单元格
* @param sheet Excel工作簿
* @param rowNum 单元格行下标
* @param columnIndex 单元格列下标
* @return
*/
private static boolean isMergedRegion(Sheet sheet, int rowNum,
int columnIndex) {
// 获取合并单元格个数
int sheetMergedNum = sheet.getNumMergedRegions();
for(int i = 0; i < sheetMergedNum; i++){
CellRangeAddress range = sheet.getMergedRegion(i);
// 数据依次为合并单元格的第一列、最后一列、第一行、最后一行
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
// 判断是否在次单元格区间内,如果是则返回true
if(rowNum >= firstRow && rowNum <= lastRow){
if(columnIndex >= firstColumn && columnIndex <= lastColumn){
return true;
}
}
}
// 如果不在所有的合并单元格内则返回false
return false;
}

/**
* 读取文件类型,如果是excel则返回对象实例, 如果不是则返回null
* @param filePath 文件路径
* @return Workbook实例
*/
private static Workbook readFile(File file, String extension) {
Workbook wb = null;
if(file != null && extension != null && !extension.equals("")){
try {
InputStream inputStream = null;
inputStream = new FileInputStream(file);
if(extension.equals("xls")){
wb = new HSSFWorkbook(inputStream);
}else if(extension.equals("xlsx")){
wb = new XSSFWorkbook(inputStream);
}else{
wb = null;
}
} catch (FileNotFoundException e) {
System.out.println("未找到文件位置!");
e.printStackTrace();
} catch (IOException e) {
System.out.println("文件类型不正确,请重新选择!");
e.printStackTrace();
}
}
return wb;
}

/**
* 获取单元格的值,并格式化 日期格式不变 其他格式转换为字符串类型
* @param cell 单元格
* @return
*/
private static String getValue(Cell cell){
String cellValue = null;
// 格式化数据对象
DecimalFormat df = new DecimalFormat("0.######");
if(cell != null){
// 获取单元格数据类型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
DateFormat formater = null;
Date d = cell.getDateCellValue();
if(cell.getCellStyle().getDataFormat() == 31){
formater = new SimpleDateFormat("yyyy年MM月dd日");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 58){
formater = new SimpleDateFormat("MM月dd日");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 14){
formater = new SimpleDateFormat("yyyy-MM-dd");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 57){
formater = new SimpleDateFormat("yyyy年MM月");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 20){
formater = new SimpleDateFormat("HH:mm");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 32){
formater = new SimpleDateFormat("HH时mm分");
cellValue = formater.format(d);
}else if(cell.getCellStyle().getDataFormat() == 9){
cellValue = df.format(cell.getNumericCellValue()*100) + "%";
}else if(DateUtil.isCellDateFormatted(cell)){
formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cellValue = formater.format(d);
}else{
cellValue = df.format(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_FORMULA:
try {
cellValue = df.format(cell.getNumericCellValue());
} catch (Exception e) {
cellValue = cell.getCellFormula();
}
break;
case Cell.CELL_TYPE_STRING:
cellValue = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_ERROR:
break;
default:
cellValue = "";
break;
}
}
return cellValue;
}
}

使用poi读取Excel文件数据的更多相关文章

  1. 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据

    1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...

  2. JAVA使用POI读取EXCEL文件的简单model

    一.JAVA使用POI读取EXCEL文件的简单model 1.所需要的jar commons-codec-1.10.jarcommons-logging-1.2.jarjunit-4.12.jarlo ...

  3. 上传读取Excel文件数据

    /// <summary> /// 上传读取Excel文件数据 /// 来自http://www.cnblogs.com/cielwater /// </summary> // ...

  4. 使用POI 读取 Excel 文件,读取手机号码 变成 1.3471022771E10

    使用POI 读取 Excel 文件,读取手机号码 变成 1.3471022771E10 [问题点数:40分,结帖人xieyongqiu]             不显示删除回复             ...

  5. 使用POI读取excel文件内容

    1.前言 项目中要求读取excel文件内容,并将其转化为xml格式.常见读取excel文档一般使用POI和JExcelAPI这两个工具.这里我们介绍使用POI实现读取excel文档. 2.代码实例: ...

  6. Java实现POI读取Excel文件,兼容后缀名xls和xlsx

    1.引入所需的jar包: maven管理项目的话直接添加以下坐标即可: <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -- ...

  7. spring boot 使用 POI 读取Excel文件

    内容简介 本文主要介绍使用POI进行Excel文件的相关操作,涉及读取文件,获取sheet表格,对单元格内容进行读写操作,以及合并单元格的操作. Excel文件目录 Excel模板文件存了resour ...

  8. 使用jxl,poi读取excel文件

    作用:在java后台添加一个方法,读取导入的excel内容,根据需要返回相应的sql语句,以完成对临时表的插入操作. 使用jxl读取excel文件 package com.sixthf.bi.sapp ...

  9. VC6.0读取Excel文件数据

    啰嗦一下:本人所在公司从事碟式斯特林太阳能发电设备的研发与销售.单台设备图如下: 工作原理如下:整个设备大致可分为五个部分, 1.服务器,负责气象.发电等数据存取,电.网连接等处理: 2.气象站,通过 ...

随机推荐

  1. Django --- Django下载和APP创建 ORM (大概步骤)

    1,下载: 命令行: pip install django == 1.11.15 pip install -i或 源 django == 1.11.15 pycharm settings 解释器 点 ...

  2. JAVA This的简单运用

    package Code426;/*当方法的局部变量和类的成员变量重名时,根据“就近原则”,优先使用局部变量如果需要访问本类当中的成员变量,需要使用 this.成员变量 通过谁调用的方法,谁就是thi ...

  3. CSS --记录

    CSS3与文字渐变光影流动动画效果实现 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/word ...

  4. Mysql配置优化,库表设计

    Mysql 服务器参数类型: 基于参数的作用域: 全局参数:set global autocommit = ON/OFF; 会话参数(会话参数不单独设置则会采用全局参数):set session au ...

  5. openpyxl使用sheet.rows或sheet.columns报TypeError: 'generator' object is not subscriptable解决方式

    解决方案: 因为新版本的openpyxl使用rows或者columns返回一个生成器所以可以使用List来解决报错问题 >>> sheet.columns[0] Traceback ...

  6. loadrunner使用过程遇到的问题(一)

    1.如果log日志出现乱码,如何设置?(对于乱码设置只是对单一脚本有效,并不是全部脚本有效,所以多个脚本出现乱码,需要逐个设置) loadrunner12版本设置方法,在preference里面,设置 ...

  7. System.TimeoutException: The operation requested on PersistentChannel timed out

    这个异常是在使用EasyNetQ时,遇到的问题,找了两个小时. 详细错误 Error:System.TimeoutException: The operation requested on Persi ...

  8. Linux禁止普通用户su至root

    linux系统为了限制权限,有时候需要禁止普通用户su到root用户 为禁止普通用户su至root,需要分别修改/etc/pam.d/su和/etc/login.defs两个配置文件. 二.详细配置 ...

  9. nginx反向代理+tomcat域名绑定

    今天在用nginx做反向代理时,由于一个tomcat下有多个应用,因此要在tomcat做域名绑定.tomcat启动后,通过域名+端口是可以访问到页面的,但是通过nginx转发后就不能访问了,因此tom ...

  10. 迅雷最新bug已被找到!mac不用登录也可以极速下载了!

    想体验迅雷不限速的快感吗?下载这款迅雷Mac(不限速免vip)免登录版吧!拥有了这款迅雷Mac破解版,电影.游戏等所有大文件都不在话下.体验极速的下载功能,尽在迅雷Mac(不限速免vip)破解版!需要 ...