java通过POI技术操作Excel(2)----模板读取,录⼊数据
先来回顾下通常把java对Excel的操作分为以下功能:1、⽣成模板,导出模板;2、填充模板,录⼊数据;3;读取数据库数据,导出数据;在上⼀篇博⽂中,我简单记录了模板⽣成和导出,在这篇博⽂中,主要来记录--Excel⽂件导⼊,数据录⼊(仍然是以jsp+servlet为例) 既然要解决这个问题,那⾸先来分析下我们需要⾯对的有哪些需求需要实现:
1、Excel⽂件导⼊(这是最基础的,巧妇难为⽆⽶之炊,导⼊环节也是查了好久才完成的);
2、Excel⽂件中数据的格式判定,你要读取⽂件,如果⽂件中其实没有数据怎么办,程序会报错么;
3、Excel⽂件中数据的数值判定,“编号”啊,“⾝份证号”啊之类是不是需要有⼀定的规范才说明数值是正确的,否则录⼊毫⽆意义,数据库中可能还会报错; 4、Excel⽂件中数据判定完成后,判定全部正确的,全部录⼊数据库,录⼊成功显⽰录⼊成功,录⼊不成功则修改录⼊环节; 判定如果存在错误,将所有出现错误的列汇总,返回界⾯提⽰所有出错的列; ⾸先,我们来完成导⼊功能,实现如下效果:
相信这个上传效果,很多⼈都能实现,如是⽽已嘛,但是实现它后我们如何进⾏excel数据操作呢?通常我们想到的有如下两种⽅法:1、将excel⽂件传上去,然后对传上的⽂件进⾏操作,因为我们传到哪了我们知道,可以直接获取路径;2、我们可以直接获取想要上传的⽂件在电脑上的路径,然后我们通过路径直接对⽂件进⾏操作;这⾥我主要来介绍下我实现的第⼆种⽅法,(以ie浏览器为例,其它浏览器暂不讨论)
1 function upLoad(){
2 var myFile=document.getElementById(\"myFile\"); 3 myFile.select();
4 var realPath=document.selection.createRange().text; 5 var len=realPath.length;
6 var path=realPath.substr(len-4); 7 if(path==\".xls\"){
document.getElementById(\"myForm\").action=\"upLoad?path=\"+realPath; 8 document.getElementById(\"myForm\").submit(); 9 }else{
10 alert(\"请输⼊excel格式的⽂件\");11 } 12 }
通常情况下,在ie7之前我们可以通过document.getElementById('file_upl').value 直接获取⽂本的本地路径,但是在ie8之后,处于安全性考虑,上传时获取以上value值则会以“C:\\fakepath\\”来代替了,这个时候我们就需要 上⽂中出现的var myFile=document.getElementById(\"myFile\"); myFile.select();varrealPath=document.selection.createRange().text;这三步来进⾏完成了。
这样在ie浏览器下就可以获取到⽂件的本地路径了,从⽽继续接下来的⽂本读取⼯作。其次,我们来解决接下来的问题,既然找到⽂件了,那就开始对⽂件进⾏操作,
(这⾥我们只考虑,对某个单个⽂件的直接读取,不考虑多⽂件优化等问题)我们通过如下步骤来进⾏数据读取:a、java对excel的数据读取,原理上是将excel上的数据复制到hssfworkbook⼯作簿上,然后对⼯作簿进⾏操作
1 File file=new FileInputStream(String path)
2 BufferedInputStream bis=new BufferedInputStream(file);3 POIFSFileSystem pfs=new POIFSFileSystem(bis);
b、复制完成后就是对hssfworkbook⼯作簿上数据的处理,是从页、⾏、列依次进⾏开始读取
1 //每⼀页每⼀页的进⾏数据处理
2 HSSFWorkbook book=new HSSFWorkbook(pfs); 3 for (int k = 0; k < book.getNumberOfSheets(); k++) { 4 HSSFSheet sheet=book.createSheet(); 5 //每⼀⾏每⼀⾏的进⾏处理
6 for (int i = 0; i < sheet.getLastRowNum(); i++) { 7 HSSFRow row=sheet.createRow(i); 8 if(row==null){continue;}
9 String[] values = new String[i];10 Arrays.fill(values, \"\");
11 for (int j = 0; j < row.getLastCellNum()+1; j++) {12 String value=\"\";
13 HSSFCell cell=row.createCell(j);
c、在进⾏每⼀个单元格读取的时候,我们需要根据不同的数据,⽤不同的获取⽅法,避免读取过程出现异常
1 switch (cell.getCellType()) {
2 case HSSFCell.CELL_TYPE_STRING: 3 value = cell.getStringCellValue(); 4 break;
5 case HSSFCell.CELL_TYPE_NUMERIC:
6 if (HSSFDateUtil.isCellDateFormatted(cell)) { 7 Date date = cell.getDateCellValue(); 8 if (date != null) {
9 value = new SimpleDateFormat(\"yyyy-MM-dd\").format(date);10 } else {
11 value = \"\";12 }
13 } else {
14 value = newDecimalFormat(\"0\").format(cell.getNumericCellValue());15 }
16 break;
17 case HSSFCell.CELL_TYPE_FORMULA:
18 // 导⼊时如果为公式⽣成的数据则⽆值19 if (!cell.getStringCellValue().equals(\"\")) {20 value = cell.getStringCellValue();21 } else {
22 value = cell.getNumericCellValue() + \"\";23 }24 break;
25 case HSSFCell.CELL_TYPE_BLANK:26 value=\"\";27 break;
28 case HSSFCell.CELL_TYPE_ERROR:29 value = \"\";30 break;
31 case HSSFCell.CELL_TYPE_BOOLEAN:
32 value = (cell.getBooleanCellValue() == true ? \"Y\":\"N\");33 break;34 default:
35 value = \"\";36 }
如上是对不同数据类型不同的读取,java的poi读取中,通常⽤到的数据类型为:CELL_TYPE_BLANK 空值
CELL_TYPE_BOOLEAN 布尔型 CELL_TYPE_ERROR 错误
CELL_TYPE_FORMULA 公式型 CELL_TYPE_STRING 字符串型 CELL_TYPE_NUMERIC 数值型
d、接下来就是对于不同的数据判定结果,进⾏的操作不同,在这⾥我们判定如果正确列直接录⼊数据库,如果不正确的则返回界⾯(当然实际应⽤中应当是全部正确才能录⼊,如果存在不正确的数据,整个⽂件都不能录⼊)
1 if (i == 0 && value.trim().equals(\"\")) { 2 break; 3 }
4 values[i] = value; 5 } 6 } 7 } 8 }
9 //进⾏判定全局变量boolean值all,如果为true,则说明已经数据完全正确,则取值向数据库中进⾏存取,如果为false则存在错误信息,将得到的错误信息直接返回,不再向数据库发送存取请求 10 }
11 return returnArray;12 }
最后⾯这部分写的略微有些凌乱,这样我们来回顾⼀下读取步骤:1、获取⽂件地址;
2、根据⽂件地址,读取⽂件;
(这⾥应该是读取全部数据,可以先进⾏基本数据的判定,如果存在不对的数据类型,则记录并返回提⽰,如果正确了再进⾏下⼀步);3、如果判定之前的数据类型设定都正确了,则进⾏判定数据的具体规格,例如:编号前⼏位必须为http,⾝份证号码共18位等;4、如果以上所有的判定都满⾜,则将数据进⾏录⼊数据库操作,(数据录⼊数据库,相信都不会陌⽣了吧) 如果存在问题,则应该返回界⾯进⾏相应的提⽰操作。