先来回顾下通常把java对Excel的操作分为以下功能:1、生成模板,导出模板;2、填充模板,录入数据;3;读取数据库数据,导出数据;在上一篇博文中,我简单记录了模板生成和导出,在这篇博文中,主要来记录--Excel文件导入,数据录入(仍然是以jsp+servlet为例)

  既然要解决这个问题,那首先来分析下我们需要面对的有哪些需求需要实现:

  1、Excel文件导入(这是最基础的,巧妇难为无米之炊,导入环节也是查了好久才完成的);

  2、Excel文件中数据的格式判定,你要读取文件,如果文件中其实没有数据怎么办,程序会报错么;

  3、Excel文件中数据的数值判定,“编号”啊,“身份证号”啊之类是不是需要有一定的规范才说明数值是正确的,否则录入毫无意义,数据库中可能还会报错;

  4、Excel文件中数据判定完成后,判定全部正确的,全部录入数据库,录入成功显示录入成功,录入不成功则修改录入环节;

                 判定如果存在错误,将所有出现错误的列汇总,返回界面提示所有出错的列;

 首先,我们来完成导入功能,实现如下效果:

相信这个上传效果,很多人都能实现,<input type="file">如是而已嘛,但是实现它后我们如何进行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();var realPath=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、如果以上所有的判定都满足,则将数据进行录入数据库操作,(数据录入数据库,相信都不会陌生了吧)

  如果存在问题,则应该返回界面进行相应的提示操作。