Java开发项目中经常会碰到处理Excel文件中数据的情况,这里通过一个例子来看一下实现方法:从Excel文件orders.xls中读取订单信息,从中找出2010年1月1日(含)之后,并且SELLERID等于18的订单。找到的数据写入order_result.xls文件。

    Excel文件orders.xls的内容如下:

ORDERID CLIENT SELLERID AMOUNT ORDERDATE

1 UJRNP 17 392 2008/11/2 15:28

2 SJCH 6 4802 2008/11/9 15:28

3 UJRNP 16 13500 2008/11/5 15:28

4 PWQ 9 26100 2008/11/8 15:28

5 PWQ 11 4410 2008/11/12 15:28

6 HANAR 18 6174 2008/11/7 15:28

7 EGU 2 17800 2008/11/6 15:28

8 VILJX 7 2156 2008/11/9 15:28

9 JAYB 14 17400 2008/11/12 15:28

10 JAXE 19 19200 2008/11/12 15:28

11 SJCH 7 13700 2008/11/10 15:28

12 QUICK 11 21200 2008/11/13 15:28

13 HL 12 21400 2008/11/21 15:28

14 JAYB 1 7644 2008/11/16 15:28

15 MIP 16 3234 2008/11/19 15:28

16 AYWYN 4 6566 2008/11/21 15:28


Java程序的编写思路是

1、 Excel文件逐行读入数据保存到List对象sourceList中。

2、 遍历List对象sourceList,如果满足条件就保存到结果List对象resultList中。

3、 遍历reslutList,逐行保存到输出Excel文件中。

其中包含一些处理不同数据类型的语句,具体代码如下:

 

         publicstatic void myExcel() throws Exception {

                   //excel数据

                   HSSFWorkbookworkbook=

newHSSFWorkbook(new FileInputStream(newFile("d:/file/orders.xls")));

       Sheet sheet=workbook.getSheetAt(0);//读取第一个sheet

       List<Map<String,Object>>sourceList= newArrayList<Map<String,Object>>();

                   List<Map<String,Object>>resultList=new ArrayList<Map<String,Object>>();

                   SimpleDateFormatformat = new SimpleDateFormat("yyyy-M-ddHH:mm:ss");

                   for(int i = 1; i <sheet.getPhysicalNumberOfRows(); i++) {//逐行处理excel数据

                       Row row=sheet.getRow(i);

                       Map<String,Object> order=newHashMap<String,Object>();

                       Cell cell0 = row.getCell(0);

                            cell0.setCellType(Cell.CELL_TYPE_STRING);

//整数数据要转为txt,否则会变成浮点数

                            Cellcell1 = row.getCell(1);

                            cell1.setCellType(Cell.CELL_TYPE_STRING);

                            Cellcell2 = row.getCell(2);

                            cell2.setCellType(Cell.CELL_TYPE_STRING);

                            order.put("ORDERID",cell0.toString());

                            order.put("CLIENT",cell1.toString());

                            order.put("SELLERID",cell2.toString());

                            order.put("AMOUNT",row.getCell(3).toString());

                            //处理日期类型的数据

                            order.put("ORDERDATE",

HSSFDateUtil.getJavaDate(row.getCell(4).getNumericCellValue()));

                            sourceList.add(order);

                   }

                   for(int i = 0, len = sourceList.size(); i <len; i++) {//按照条件过滤

                            Map<String,Object>order =(Map<String,Object>) sourceList.get(i); 

                            System.out.println("1order.get(\"SELLERID\")="+order.get("SELLERID"));

                            if( Integer.parseInt(order.get("SELLERID").toString())==18 &&

                            ((Date)order.get("ORDERDATE")).after(format.parse("2009-12-3123:59:59")) )

                            {//判断是否符合条件

                                     resultList.add(order);//符合条件的加入List对象resultList

                            }

                   }

                   //excel文件

                   HSSFWorkbookworkbook1 = new HSSFWorkbook();//创建excel文件对象

                   Sheetsheet1 = workbook1.createSheet();//创建sheet对象

                   Rowrow1;

                   row1= sheet1.createRow(0);//第一行,标题

                   row1.createCell(0).setCellValue("ORDERID");

                   row1.createCell(1).setCellValue("CLIENT");

                   row1.createCell(2).setCellValue("SELLERID");

                   row1.createCell(3).setCellValue("AMOUNT");

                   row1.createCell(4).setCellValue("ORDERDATE");

                   for(int i = 1, len = resultList.size(); i <len; i++) {//循环创建数据行

                            row1= sheet1.createRow(i);

                            row1.createCell(0).setCellValue(resultList.get(i).get("ORDERID").toString());

                            row1.createCell(1).setCellValue(resultList.get(i).get("CLIENT").toString());

                            row1.createCell(2).setCellValue(resultList.get(i).get("SELLERID").toString());

                            row1.createCell(3).setCellValue(resultList.get(i).get("AMOUNT").toString());

                            row1.createCell(4).setCellValue(format.format((Date)resultList.get(i).get("ORDERDATE")));

                   }

FileOutputStreamfos = newFileOutputStream("d:/file/orders_result.xls");  

        workbook1.write(fos);//写文件

fos.close();  

}

    程序执行后生成的excel文件数据如下:

ORDERID CLIENT SELLERID AMOUNT ORDERDATE

432 ERNSH 18 6272.0 2010-1-13 15:28:05

444 SJCH 18 4312.0 2010-1-25 15:28:05

452 HP 18 4312.0 2010-2-01 15:28:05

492 HP 18 27900.0 2010-3-07 15:28:05

512 BTMMU 18 18000.0 2010-3-27 15:28:05

524 PJIPE 18 15600.0 2010-4-09 15:28:05

637 HP 18 9114.0 2010-8-01 15:28:05

638 JOPO 18 294.0 2010-8-01 15:28:05

    myExcel函数中有一多半代码是读写和处理Excel文件和数据类型的,比较复杂。条件过滤的代码虽然不多,但是却不够通用。过滤条件是固定的,如果有变化,就必须要改代码。如果希望变成动态过滤条件,那么就要写动态表达式解析程序了。理论上可以实现类似SQL那样灵活的过滤条件,但是程序比较难写,调试也比较复杂。

    如果考虑采用集算器esProc作为辅助来实现Excel数据的处理,将会使这个程序的开发容易很多。esProc是专门为结构化(半结构化)数据设计的编程语言,可以写出比较简单的Excel文件处理程序。Java程序调用esProc脚本也非常简单。

    程序员可以将条件“2010年1月1日(含)之后,并且SELLERID等于18的订单。”作为参数where传递给esProc程序,如下图:

wKioL1P61B-RpIiKAACnXVFvuas250.jpg

    Where的值是:ORDERDATE>=date(2010,1,1)&& SELLERID==18esProc的程序代码如下:

wKiom1P60wiBO2vOAAEteE7weNU478.jpg

    A1:定义一个file对象,导入数据,第一行是标题。esProc的集成开发环境可以直观的显示出导入的数据,如上图右边部分。如果访问xlsx文件,可以写成=file("D:/file/orders.xlsx").importxls@xt()

    A2:按照条件过滤。这里使用宏来实现动态解析表达式,其中的where就是传入参数。集算器将先计算${…}里的表达式,将计算结果作为宏字符串值替换${…}之后解释执行。这个例子中最终执行的是:=A1.select(ORDERDATE>=date(2010,1,1) && SELLERID==18)

    A3:将符合条件的结果集写入excel文件。

过滤条件发生变化时不用改变程序,只需改变where参数即可。例如,条件变为:201011日(含)之后,并且SELLERID等于18的订单,或者CLIENT等于PWQ的订单Where的参数值可以写为:CLIENT=="PWQ"||ORDERDATE>=date(2010,1,1) && SELLERID==18。执行之后,A2中的结果集如下图:

wKioL1P61CDD7rB-AAC6tcS8RC0217.jpg

我们可以在Java程序中调用这段esProc程序,使用esProc提供的jdbc即可完成。将上述esProc程序保存为test.dfx文件的话,Java调用的代码如下:

          //建立esProcjdbc连接

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");

//调用esProc程序(存储过程),其中testdfx的文件名

com.esproc.jdbc.InternalCStatementst=(com.esproc.jdbc.InternalCStatement)con.createStatement();

    //设置参数

st.setObject(1,"ORDERDATE>=date(2010,1,1)&& SELLERID==18 || CLIENT==\"PWQ\"");//参数就是动态的过滤条件

//执行esProc存储过程

st.execute();

 

对于这种代码较简单的脚本,还可以直接把集算器代码写在调用集算器JDBCJava程序中,而不必专门编写集算器脚本文件(test.dfx):

String where="CLIENT==\"PWQ\"||ORDERDATE>=date(2010,1,1)&& SELLERID==18 ";

String resultpath="D:/file/orders_result.xls ";

String sourcepath=" D:/file/orders.xls";

ResultSet set =st.executeQuery("=file(\""+resultpath+"\").exportxls@t(file(\""+sourcepath+"\").importxls@t().select("+where+"))");

 

这段Java代码直接调用了集算器的一句脚本:从Excel文件中取得数据,并按照指定的条件过滤。结果集写入结果Excel文件。