这篇文章主要为大家详细介绍了java如何读取Excel简单模板,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
场景:对于经常需要导入excel模板或数据来解析后加以应用的,使用频率非常之高,做了一个比较稳定的版本,体现在这些地方
工具:org.apache.poi
使用前必须了解这些:
1、要解析,那肯定先判断是不是excel
2、xls后缀的excel,是03版及以前的用hssfworkbook类
xlsx后缀的excel,是07版及以后的用xssfworkbook解析
3、getworkbook这个方法是我自己乱造各种excel数据不断测试搜索修正得出的结果,其他的像简单的判断后缀xls还是xlsx来决定用hssh还是xssf是不保险的,比如你可能没遇过org.apache.poi.openxml4j.exceptions.invalidformatexception这样的异常,当然这个异常仍然是因为excel类型导致获取workbook时出错,然而我查到的结果是,excel最底层是xml实现的,类型问题出在这儿,看异常的描述也可以稍微看出来openxml4j.exceptions
4 、可能出现空行,空的单元格,或者单元格值为空的情况,这些情况,在我的readexcel()方法里都考虑到了,为什么我不用迭代器,或者加强的for each循环?就是因为这些坑爹的空单元格或者空行啊,迭代器内部在取cell单元格对象时跳过这些空的对象,who knows why?我也不知道,反正我测试过,跳过去了,本来5个单元格,一个空的,结果就只得到4个数据,即使用cell.isempty()和cell!=null来判断,也没卵用,因为遍历的时候直接跳过去了,都没有判断的机会
5、取单元格数据,这个就比较简单了,判断单元格类型,根据类型做相应的处理取出来,但是我觉得我这个getcellvalue()的方法应该有漏洞,先这么用着
下面上代码,简单描述下关键部位import java.io.file;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.ioexception;
import java.io.inputstream;
import java.io.pushbackinputstream;
import java.util.arraylist;
import java.util.hashmap;
import java.util.map;
import java.util.list;
import org.apache.poi.poixmldocument;
import org.apache.poi.openxml4j.exceptions.invalidformatexception;
import org.apache.poi.openxml4j.opc.opcpackage;
import org.apache.poi.poifs.filesystem.poifsfilesystem;
import org.apache.poi.ss.usermodel.cell;
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.xssf.usermodel.xssfworkbook;
import org.apache.poi.hssf.usermodel.hssfcell;
import org.apache.poi.hssf.usermodel.hssfworkbook;
import org.apache.xmlbeans.impl.piccolo.io.fileformatexception;
/**
*yanbiao 2016.10.25
*/
public class excelutil {
private static final string extension_xls = "xls";
private static final string extension_xlsx = "xlsx";
/**
* 文件检查
*/
private void prereadcheck(string filepath) throws filenotfoundexception, fileformatexception {
file file = new file(filepath);
if (!file.exists()) {
throw new filenotfoundexception("导入的文件不存在:" + filepath);
}
if (!(filepath.endswith(extension_xls) || filepath.endswith(extension_xlsx))) {
throw new fileformatexception("传入的文件不是excel");
}
}
/**
* 取得workbook对象
* xls:hssfworkbook,03版
* xlsx:xssfworkbook,07版
*/
private workbook getworkbook(string filepath) throws ioexception, invalidformatexception {
//直接判断后缀来返回相应的workbook对象多数情况没问题,但是这个更保险,第3条已经说明
workbook wb = null;
inputstream is = new fileinputstream(filepath);
if (!is.marksupported()) {
is = new pushbackinputstream(is, 8);
}
if (poifsfilesystem.haspoifsheader(is)) {
return new hssfworkbook(is);
}
if (poixmldocument.hasooxmlheader(is)) {
return new xssfworkbook(opcpackage.open(is));
}
throw new illegalargumentexception("您的excel版本目前不支持poi解析");
}
/**
* 读取excel文件内容
*/
public map<integer, list<string>> readexcel(string filepath) throws filenotfoundexception, fileformatexception {
// 检查和获取workbook对象
this.prereadcheck(filepath);
workbook wb = null;
map<integer,list<string>> map = new hashmap<integer, list<string>>();
try {
wb = this.getworkbook(filepath);
// 默认只读取第一个sheet
sheet sheet = wb.getsheetat(0);
int rowcount = sheet.getlastrownum();//逻辑行,包括空行
int cellcount = sheet.getrow(0).getlastcellnum();//第一行(将来作为字段的行)有多少个单元格
for (int i=0;i<rowcount;i++) { //这里用最原始的for循环来保证每行都会被读取
list<string> list = new arraylist<string>();
row row = sheet.getrow(i);
if(null!=row){
for (int j=0;j<cellcount;j++) {
list.add(getcellvalue(row.getcell(j))); //这里也是用for循环,用cell c:row这样的遍历,空单元格就被抛弃了
}
system.out.println("第"+(row.getrownum()+1)+"行数据:"+list.tostring());
map.put(row.getrownum(), list);
}else{
for (int j=0;j<cellcount;j++) {
list.add("无数据");
}
system.out.println("第"+(i+1)+"行数据:"+list.tostring());
map.put(i, list);
}
}
} catch (exception e) {
system.out.println("读取excel异常:"+e.getmessage());
e.printstacktrace();
} finally {
if (wb != null) {
try {
wb.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
return map;
}
/**
* 取单元格的值
*/
private string getcellvalue(cell c) {
if (c == null) {
return "无数据";
}
string value = "";
switch (c.getcelltype()){
case hssfcell.cell_type_numeric://数字
value = c.getnumericcellvalue()+"";
break;
case hssfcell.cell_type_string://字符串
value = c.getstringcellvalue();
break;
case hssfcell.cell_type_boolean://boolean
value = c.getbooleancellvalue()+"";
break;
case hssfcell.cell_type_formula://公式
value = c.getcellformula()+"";
break;
case hssfcell.cell_type_blank://空值
value= "无数据";
break;
case hssfcell.cell_type_error:
value = "非法字符";
break;
default:
value= "未知类型";
break;
}
return value;
}
} 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家。
原文链接:https://www.cnblogs.com/yb38156/p/9821804.html
|