在美团实习的过程中,马上要做的功能有一项是前台上传文件后台获取文件对excel文件进行解析。之前做过后台从DB获取数据按照模板将查询的数据填入xls并返回给前台提供下载的功能,最后会给出一个工具类,里面包含这个功能的实现。
实现对excel文件的读写,比较主流的做法是使用Apache POI提供的各种类和方法,对Apache POI的理解可以参照这篇文章:POI基础
在对POI有足够的认识和理解后,可以预想对前台上传的文件进行解析,实际上就是在服务器端打开该文件,遍历里面的数据,将Excel里面存储的数据按照合适的对应关系存入正确的data object的field。接下来想做什么都可以了,不管是存储数据到DB或者进行相应的计算的都可以。感觉其实excel文件的结构通过POI提供的类来组织的话还比较简单,宏观的看其实一个Excel文件就是一个HSSFWorkbook类的实例,文件里的多个sheet各自对应HSSFSheet实例,每个sheet里面的一行行记录对应HSSFRow,一个个单元格就是一个个HSSFCell。
那么下面我将自己认为最主要的代码实现,在网上看到的,我做了一些修改。粘贴如下:
解析excel文件核心代码
public
class
PoiExcelParser {
private
Sheet sheet;
//表格类实例
LinkedList[] result;
//保存每个单元格的数据 ,是容器就好,看需求吧
//读取excel文件,创建表格实例
private
void
loadExcel(String filePath) {
FileInputStream inStream =
null
;
try
{
inStream =
new
FileInputStream(
new
File(filePath));
Workbook workBook = WorkbookFactory.create(inStream);
sheet = workBook.getSheetAt(
0
);
//注意sheet以0开始计数
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
try
{
if
(inStream!=
null
){
inStream.close();
//关闭stream
}
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
//获取某个单元格的值,统一以字符串形式返回
private
String getCellValue(Cell cell) {
String cellValue =
""
;
DataFormatter formatter =
new
DataFormatter();
if
(cell !=
null
) {
//判断单元格数据的类型,不同类型调用不同的方法
switch
(cell.getCellType()) {
//数值类型
case
Cell.CELL_TYPE_NUMERIC:
//进一步判断 ,单元格格式是日期格式
if
(DateUtil.isCellDateFormatted(cell)) {
cellValue = formatter.formatCellValue(cell);
}
else
{
//数值
double
value = cell.getNumericCellValue();
int
intValue = (
int
) value;
cellValue = value - intValue ==
0
? String.valueOf(intValue) : String.valueOf(value);
}
break
;
case
Cell.CELL_TYPE_STRING:
cellValue = cell.getStringCellValue();
break
;
case
Cell.CELL_TYPE_BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break
;
//判断单元格是公式格式,需要做一种特殊处理来得到相应的值
case
Cell.CELL_TYPE_FORMULA:
try
{
cellValue = String.valueOf(cell.getNumericCellValue());
}
catch
(IllegalStateException e){
cellValue = String.valueOf(cell.getRichStringCellValue());
}
break
;
case
Cell.CELL_TYPE_BLANK:
cellValue =
""
;
break
;
case
Cell.CELL_TYPE_ERROR:
cellValue =
""
;
break
;
default
:
cellValue = cell.toString().trim();
break
;
}
}
return
cellValue.trim();
}
//初始化表格中的每一行,并得到每一个单元格的值
public
void
getData(){
int
rowNum = sheet.getLastRowNum() +
1
;
result =
new
LinkedList[rowNum];
for
(
int
i=
0
;i<rowNum;i++){
Row row = sheet.getRow(i);
//每有新的一行,创建一个新的LinkedList对象
result[i] =
new
LinkedList();
for
(
int
j=
0
;j<row.getLastCellNum();j++){
Cell cell = row.getCell(j);
//获取单元格的值
String str = getCellValue(cell);
//将得到的值放入链表中,实际的使用过程中,也可以保存在dataobject里
result[i].add(str);
}
}
}
}
|
这段代码在实际工程中使用需谨慎,确保可用性,可能会做出相应的修改以适应工程的实际需要。
Update:
1.发现一个问题,就是作为解析前台上传的文件,控制用户上传的文件格式有一定难度,而前面用hssf实现的功能只对xls格式支持,如果万一用户上传的是xlsx就有问题。。。而这个问题,在很久之前就被很好的利用多态解决了,帖子链接如下:通过POI统一读取Excel文件(兼容97-2003和2007+两种格式)