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. python基础--numpy.dot

    # *_*coding:utf-8 *_* # athor:auto import numpy dot = numpy.dot([0.100, 0.200],2.) print(dot) #[ 0.2 ...

  2. Unity iOS Appstore 上架的问题

    之前一直是一个人的名义上架的应用.现在变成:公司的账号就会出现一些莫名的问题: 首先是账号需要新的boulder名字,新建之后下载验证key. 注意:真机测试不发布,选择自动签名就行了:需要发布就取消 ...

  3. No grammar constraints (DTD or XML Schema) referenced in the document.

    问题描述 web.xml 使用 Servlet4.0 版本,No grammar constraints (DTD or XML Schema) referenced in the document. ...

  4. electron Windows和mac 的菜单栏隐藏

    1.Windows隐藏方法 const {electron,Menu,debug} = require('electron'); Menu.setApplicationMenu(null) 2.mac ...

  5. django ajax 及批量插入数据 分页器

    ``` Ajax 前端朝后端发送请求都有哪些方式 a标签href GET请求 浏览器输入url GET请求 form表单 GET/POST请求 Ajax GET/POST请求 前端朝后端发送数据的编码 ...

  6. python的numpy库的学习

    1.创建 array(序列类型).asarray.arange.ones.ones_like.zeros.zeros_like.empty.empty_like.eye.identity 2.运算 两 ...

  7. 当运行docker run -i -t ubuntu /bin/bash时,提示报错Error response from daemon: EOF?

    可能是下载过程中出现错误,重新执行docker pull ubuntu,在执行docker run -i -t ubuntu /bin/bash就OK了.

  8. 初探storm

    Storm入门之Storm示例及UI参数讲解 Storm UI REST API Storm 1.1.0 中文文档 Apache Storm 1.1.0 中文文档 | ApacheCN Storm U ...

  9. WPF自定义仪表盘控件

    闲来无事,分享一个仪表盘 源码: 直接复制代码即可运行,=.=! <Window x:Class="TGP.InstrumentationDemo.MainWindow" x ...

  10. CocosCraetor中图像资源Texture和SpriteFrame的区别

    Texture是保存在GPU缓冲中的一张纹理.是由一张图片创建获得的. SpriteFrame是Texture+Rect,根据一张纹理材质来剪切获得. SpriteFrame是Texture+Rect ...