POI使用:用poi接口不区分xls/xlsx格式解析Excel文档(41种日期格式解析方法,5种公式结果类型解析方法,3种常用数值类型精度控制办法)
一、使用poi解析excel文档
1、打开excel文件
/**
* 解析excel文档(支持xls、xlsx格式)
* @param path - 文件路径
* @param formula - 是否获取公式结果
* @param sdf - 日期格式
* @return List - 结果表
* @throws Exception - 打开文件失败
*/
public List<Map> parse(String path, boolean formula, SimpleDateFormat sdf)
throws Exception
{
path = this.getClass().getResource("/").getPath() + path;
File file = new File(path);
List<Map>list=null;
if (file.isFile())
{
Workbook wb = createWorkbook(file);
System.out.println("当前活动sheet" + wb.getActiveSheetIndex());
System.out.println("当前几个文档"+wb.getNumberOfSheets());
list=new ArrayList<Map>();
int max=wb.getNumberOfSheets();
for(int sheetNum=0;sheetNum<max;sheetNum++){
list.add(getSheet(wb, sheetNum, formula, sdf));//解析sheet表
}
}
else
{
throw new Exception("文件不存在");
}
return list;
}
2、解析sheet表
/**
* 获取sheet表内容
* @param wb - 文档
* @param sheetNum - 打开那张sheet表
* @param formula - 是否获得公式结果
* @param sdf - 日期格式
* @return Map - 结果表
*/
public Map<Integer, Map<Integer, String>> getSheet(Workbook wb, int sheetNum, boolean formula, SimpleDateFormat sdf)
{
String sheetName = wb.getSheetName(sheetNum);
System.out.println("打开了sheet表:" + sheetName);
Sheet sheet = wb.getSheet(sheetName);
Map<Integer, Map<Integer, String>> map=getRowAndCell(sheet, formula, sdf);//解析所有单元格
return map; }
3、解析单元格内容
/**
* 从sheet表中获取每行每列的值
* @param sheet - sheet表
* @param formula - 是否获取公式结果
* @param sdf - 日期格式
* @return Map - 结果表
*/
public Map<Integer, Map<Integer, String>> getRowAndCell(Sheet sheet, boolean formula, SimpleDateFormat sdf)
{
Map<Integer,Map<Integer,String>>rowMap=null;
int firstRowNum = sheet.getFirstRowNum();
int lastRowNum = sheet.getLastRowNum(); if(lastRowNum>0){
rowMap=new HashMap<Integer,Map<Integer,String>>(); // 遍历行
for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++ )
{
Row row = sheet.getRow(rowNum);
int firstCellNum = row.getFirstCellNum();
int lastCellNum = row.getLastCellNum();
Map<Integer,String> cellMap=new HashMap<Integer,String> ();
// 遍历列
for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++ )
{
Cell cell = row.getCell(cellNum);
int type = cell.getCellType();
String data=getValue(cell, formula, sdf);//根据单元格具体类型获得内容
System.out.println("第" + rowNum + "行,第" + cellNum + "列,类型是" + type +",内容是:"+data);
cellMap.put(cellNum, data);
}
rowMap.put(rowNum, cellMap);
}
}
return rowMap;
}
4、判断单元格类型并获取内容
/**
* 判断数值类型自动解析日期格式等其他特殊类型
*
* @param data - 存放数据
* @param cell - 单元格
* @param sdf - 日期格式
* @return String - 结果
*/
private String parseDate(Cell cell, SimpleDateFormat sdf)
{
System.out.println("是否是有效的日期格式:"+DateUtil.isCellDateFormatted(cell));
//poi的日期判断仅适用于欧美日期格式,对中文日期不支持,另外增加两个方法判断中文格式日期
if (DateUtil.isCellDateFormatted(cell)||isReserved(cell.getCellStyle().getDataFormat())||isDateFormat(cell.getCellStyle().getDataFormatString()))
{
return sdf.format(cell.getDateCellValue());
}
System.out.println("格式:"+cell.getCellStyle().getDataFormatString()+",类型"+cell.getCellStyle().getDataFormat());
Double d=cell.getNumericCellValue();
if(cell.getCellStyle().getDataFormat()==0)
{
DecimalFormat dfs = new DecimalFormat("0");
return dfs.format(d);
}
return String.valueOf(d); }
/**
* 获取单元格内容
* @param cell - 单元格
* @param sdf - 日期格式
* @param formula - 是否得出公式结果
* @return String - 单元格内容
*/
private String getValue(Cell cell, boolean formula, SimpleDateFormat sdf)
{
String data = null;
switch (cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC: // 数字
data = parseDate(cell, sdf);
break;
case Cell.CELL_TYPE_STRING: // 字符串 data = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN: // Boolean
data = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: // 公式
// 解析公式
data = parseFormula(cell, formula);
break;
case Cell.CELL_TYPE_BLANK: // 空格
System.out.println("遇到一个空格");
data = null;
break;
case Cell.CELL_TYPE_ERROR:// 错误
System.out.println("遇到一个错误");
data = null;
break;
default:
data = null;
}
return data;
}
二、poi的6种基本类型
Cell.CELL_TYPE_STRING: // 字符串
Cell.CELL_TYPE_BOOLEAN: // Boolean
Cell.CELL_TYPE_FORMULA: // 公式
Cell.CELL_TYPE_BLANK: // 空格
Cell.CELL_TYPE_ERROR:// 错误
三、41种日期格式解析方法
注意:看着好像有几个是重复的,但是它们的日期格式是不一样的(比如yyyy-m-d与yyyy-mm-dd同样都是显示:2015-12-13)
日期表(1-41):
1 2015-12-13
2 2015年12月
3 2015年12月15日
4 十二月十六日
5 二〇一五年十二月
6 二〇一五年十二月十八日
7 12月13日
8 2015-12-13 12:00 AM
9 2015-12-14 0:00
10 15-12-15
11 12-16
12 12-17-15
13 12-18-15
14 19-Dec
15 20-Dec-15
16 21-Dec-15
17 Dec-15
18 December-15
19 D
20 D-15
21 2015年12月26日
22 2015年12月
23 二〇一五年十二月二十七日
24 二〇一五年十二月
25 十二月二十九日
26 12月30日
27 星期四
28 五
29 2016-1-2
30 2016-1-3 12:00 AM
31 2016-1-4 0:00
32 16-1-5
33 1-6
34 1-7-16
35 01-08-16
36 9-Jan
37 10-Jan-16
38 Jan-16
39 January-16
40 J
41 J-16
2、日期对应的类型(0-40对应上面日期表1-41)
序号=类型
0=14,
1=27,
2=31,
3=176,
4=177,
5=178,
6=28,
7=179,
8=22,
9=180,
10=181,
11=30,
12=182,
13=16,
14=15,
15=183,
16=17,
17=184,
18=185,
19=186,
20=187,
21=188,
22=189,
23=190,
24=191,
25=192,
26=193,
27=194,
28=195,
29=196,
30=197,
31=198,
32=199,
33=200,
34=201,
35=202,
36=203,
37=204,
38=205,
39=206,
40=207
3、对应的日期格式(0-40,同上):
0=m/d/yy,
1=reserved-0x1b,
2=reserved-0x1f,
3=[DBNum1][$-804]m"月"d"日",
4=[DBNum1][$-804]yyyy"年"m"月",
5=[DBNum1][$-804]yyyy"年"m"月"d"日",
6=reserved-0x1c,
7=yyyy/m/d\ h:mm\ AM/PM,
8=m/d/yy h:mm,
9=yy/m/d,
10=m/d,
11=reserved-0x1e,
12=mm/dd/yy,
13=d-mmm,
14=d-mmm-yy,
15=dd/mmm/yy,
16=mmm-yy,
17=mmmm/yy,
18=mmmmm,
19=mmmmm/yy,
20=yyyy"年"m"月"d"日";@,
21=yyyy"年"m"月";@,
22=[DBNum1][$-804]yyyy"年"m"月"d"日";@,
23=[DBNum1][$-804]yyyy"年"m"月";@,
24=[DBNum1][$-804]m"月"d"日";@,
25=m"月"d"日";@,
26=[$-804]aaaa;@,
27=[$-804]aaa;@,
28=yyyy/m/d;@,
29=[$-409]yyyy/m/d\ h:mm\ AM/PM;@,
30=yyyy/m/d\ h:mm;@,
31=yy/m/d;@,
32=m/d;@,
33=m/d/yy;@,
34=mm/dd/yy;@,
35=[$-409]d/mmm;@,
36=[$-409]d/mmm/yy;@,
37=[$-409]mmm/yy;@,
38=[$-409]mmmm/yy;@,
39=[$-409]mmmmm;@,
40=[$-409]mmmmm/yy;@
根据上述的格式进行单独判断就可以正确解析所有日期格式。下面是我的实现方式,可能效率不高,如果有其它高效的方法可以提出来,欢迎一起交流
4、解析数值类型中的日期:
/**
* 判断数值类型自动解析日期格式等其他特殊类型
*
* @param data - 存放数据
* @param cell - 单元格
* @param sdf - 日期格式
* @return String - 结果
*/
private String parseDate(Cell cell, SimpleDateFormat sdf)
{
System.out.println("是否是有效的日期格式:"+DateUtil.isCellDateFormatted(cell));
//poi的日期判断仅适用于欧美日期格式,对中文日期不支持,另外增加两个方法判断中文格式日期
if (DateUtil.isCellDateFormatted(cell)||isReserved(cell.getCellStyle().getDataFormat())||isDateFormat(cell.getCellStyle().getDataFormatString()))
{
return sdf.format(cell.getDateCellValue());
}
System.out.println("格式:"+cell.getCellStyle().getDataFormatString()+",类型"+cell.getCellStyle().getDataFormat());
Double d=cell.getNumericCellValue();
if(cell.getCellStyle().getDataFormat()==0)
{
DecimalFormat dfs = new DecimalFormat("0");
return dfs.format(d);
}
return String.valueOf(d); }
<span style="font-size:18px;"> /**
* 是否是日期格式保留字段
* @return boolean<ul><li>true - 是保留字段</li><li>false - 不是</li></ul>
*/
private boolean isReserved(short reserv)
{
if(reserv>=27&&reserv<=31)
{
return true;
}
return false;
}
/**
* 判断是否是中文日期格式
* @param isNotDate
* @return boolean<ul><li>true - 是日期格式</li><li>false - 不是</li></ul>
*/
private boolean isDateFormat(String isNotDate)
{
if(isNotDate.contains("年")||isNotDate.contains("月")||isNotDate.contains("日"))
{
return true;
}
else if(isNotDate.contains("aaa;")||isNotDate.contains("AM")||isNotDate.contains("PM"))
{
return true;
} return false;
}</span>
四、5种公式类型及结果解析方法
1、公式只有一种,结果分为5种
2、解析5种公式
<span style="font-size:18px;"> /**
* 解析公式
*
* @param data - 存放数据
* @param cell - 单元格
* @param formula - 是否计算公式结果
* @return String - 结果
*/
private String parseFormula(Cell cell, boolean formula)
{
String data = null;
if (formula)
{
switch (cell.getCachedFormulaResultType())
{
case 0:
if (0 == cell.getCellStyle().getDataFormat())
{
DecimalFormat df = new DecimalFormat("0");
data = df.format(cell.getNumericCellValue());
}
else
{
data = String.valueOf(cell.getNumericCellValue());
}
break;
case 1:
data = String.valueOf(cell.getRichStringCellValue());
break;
case 4:
data = String.valueOf(cell.getBooleanCellValue());
break;
case 5:
data = String.valueOf(cell.getErrorCellValue());
break;
default:
data = cell.getCellFormula();
}
}
else
{
data = cell.getCellFormula();
}
return data;
}</span>
五、3种数值类型(货币,浮点、整数)精度控制(正确解析整数型数值)
POI使用:用poi接口不区分xls/xlsx格式解析Excel文档(41种日期格式解析方法,5种公式结果类型解析方法,3种常用数值类型精度控制办法)的更多相关文章
- 1、关于python第三方工具操作xls和xlsx格式的excel文档选型的吐血经历
首先,最近看了python的一本书,其中第7章是关于文章操作的,就计划把python操作excel,word,txt,xml,html,json等格式的文档做个总结,并实现一些功能,但是,第一步就要把 ...
- poi做Excel数据驱动,支持.xls和.xlsx格式的excel文档,比起jxl强大不少
import java.io.FileInputStream;import java.io.InputStream;import java.util.Iterator;import java.util ...
- Java使用poi包读取Excel文档
项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org. ...
- struts2中利用POI导出Excel文档并下载
1.项目组负责人让我实现这个接口,因为以前做过类似的,中间并没有遇到什么太困难的事情.其他不说,先上代码: package com.tydic.eshop.action.feedback; impor ...
- POI 读取Excel文档中的数据——兼容Excel2003和Excel2007
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. HSSF - 提供读写Microsoft Exce ...
- Java之Poi导出Excel文档
一.Poi简介 在后台管理系统中,我们经常要做的导出操作,通常导出为Excel文档的形式,而Poi则提供了这种需要的支持. 二.Workbook/HSSFWorkbook/XSSFWorkbook 1 ...
- Java下使用Apache POI生成具有三级联动下拉列表的Excel文档
使用Apache POI生成具有三级联动下拉列表的Excel文档: 具体效果图与代码如下文. 先上效果图: 开始贴代码,代码中部分测试数据不影响功能. 第一部分(核心业务处理): 此部分包含几个方面: ...
- poi 读取使用 Strict Open XML 保存的 excel 文档
poi 读取使用 Strict Open XML 保存的 excel 文档 某项目有一个功能需要读取 excel 报表内容,使用poi读取时报错: 具体错误为: org.apache.poi.POIX ...
- POI加dom4j将数据库的数据按一定格式生成word文档
一:需求:将从数据库查处来的数据,生成word文档,并有固定的格式.(dom4j的jar包+poi的jar包) 二:解决:(1)先建立固定格式的word文档(2007版本以上),另存成为xml文件,作 ...
随机推荐
- phpcms 制作简单企业站的常用标签
标题 title 关键字 keywords 描述 description 来源 copyfrom 允许访问 allow_visitor==1 thumb 缩略图 {template "con ...
- python——模块
一.导入模块 Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入.导入模块有一下几种方法: 1 import module 2 fr ...
- IBM GPFS并行文件系统
原文地址:http://www.hqschina.com/Show.aspx?info_lb=283&info_id=751&flag=103 IBM GPFS文件系统是一种专门为群集 ...
- 2017云计算开源峰会 你是想听Linux谈开源还是想听OpenStack谈开源?
2017年,善于把握机遇的企业们不是正在开源,就是走在去开源的路上-- 开源是不是就意味着免费? 开源企业就是要当"活雷锋"? 开源项目究竟如何运作?如何参与开源社区? 如何获得最 ...
- JS常用方法【私房菜-笔记】-持续整理中
//记录一下前端开发中 JS常用的方法等,持续收集整理中 ---------------------------------------------------------- //处理键盘事件 禁止后 ...
- JavaScript ,Python,java,Go系列算法之选择排序
常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 用一张图概括: 选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是O(n2) ...
- Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)
横看成岭侧成峰,远近高低各不同.不识庐山真面目,只缘身在此山中. --苏轼 这一块儿学的是云里雾里,咱们先从简单的入手.逐渐的拨开迷雾见太阳.本次先做List集合的三个实现类的学习笔记 List特点: ...
- Python数据类型和变量
一.数据类型1.整型整型类型比较简单,就是我们数学中的正整数(1,2,520..).负整数(-2,-9..);与java不同的是,python中的整数可以无限大,而java的整数类型int为四个字节, ...
- SQLite 之 C#版 System.Data.SQLite 使用
简介 SQLite简介 SQLite,是一款轻型的关系型数据库.它的设计目标是嵌入式. 它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 C++.C ...
- RabbitMQ 3.6.1集群搭建
MQ的集群首先需要搭建erlang集群1.把cat /root/.erlang.cookie 内容改为一致 cat /root/.erlang.cookie 2.更改cookie文件权限 chmod ...