java的POI操作Excel文件

              微軟在桌面系統(tǒng)上的成功,令我們不得不大量使用它的辦公產(chǎn)品,如:WordExcel。時(shí)至今日,它的源代碼仍然不公開(kāi)已封鎖了我們的進(jìn)一步應(yīng)用和開(kāi)發(fā)。然而在要求更高的服務(wù)器領(lǐng)域,微軟本身的產(chǎn)品移植性不好, 

              性能不佳。在我們實(shí)際的開(kāi)發(fā)中,表現(xiàn)層的解決方案雖然有多樣,但是Ie瀏覽器已成為最多人使用的瀏覽器,因?yàn)榇蠹叶加?/font>Windows。在企業(yè)辦公系統(tǒng)中,常常有客戶(hù)這樣子要求:你要把我們的報(bào)表直接用Excel打開(kāi)。或者是:我們已經(jīng)習(xí)慣用Excel打印。這樣子如果用.net開(kāi)發(fā)是沒(méi)有問(wèn)題的,但是有j2ee這個(gè)比.net更有前途的開(kāi)放式的開(kāi)發(fā)環(huán)境,難道我為了解決打印的要求去另寫(xiě)客戶(hù)端的控件?或者在服務(wù)器端使用本地代碼?第一種方案的問(wèn)題是關(guān)鍵數(shù)據(jù)的處理有時(shí)候不能在客戶(hù)端做,第2種方案的問(wèn)題是犧牲了代碼的可移植性和穩(wěn)定性。如果讓客戶(hù)端只負(fù)責(zé)處理生成好的報(bào)表,那將是一種誘人的選擇。

              ApacheJakata項(xiàng)目的POI子項(xiàng)目,目標(biāo)是處理ole2對(duì)象。目前比較成熟的是HSSF接口,處理MS Excel97-2002)對(duì)象。它不象我們僅僅是用csv生成的沒(méi)有格式的可以由Excel轉(zhuǎn)換的東西,而是真正的Excel對(duì)象,你可以控制一些屬性如sheet,cell等等。這是一個(gè)年輕的項(xiàng)目,所以象HDF這樣直接支持Word對(duì)象的好東西仍然在設(shè)計(jì)中。其它支持word格式的純java方案還有itext,不過(guò)也是仍在奮斗中。但是HSSF已經(jīng)成熟到能夠和足夠我們使用了。另外,無(wú)錫永中Office的實(shí)現(xiàn)方案也是純java的解決方案,不過(guò)那也是完全商業(yè)的產(chǎn)品,并不是公開(kāi)代碼項(xiàng)目。其實(shí),從開(kāi)發(fā)歷史的角度講,在80年代中期starOffice的原作者在德國(guó)成立了StarOffice suite公司,然后到1999年夏天starOfficesun收購(gòu),再到20006starOffice5.2的發(fā)布;并且從starOffice6.0開(kāi)始,starOffice建立在OpenOfficeapi的基礎(chǔ)上,這個(gè)公開(kāi)代碼的office項(xiàng)目已經(jīng)進(jìn)行了很長(zhǎng)的時(shí)間。雖然那是由C++寫(xiě)的,但是POI的代碼部分也是由openOffice改過(guò)來(lái)的。所以,應(yīng)該對(duì)POI充滿(mǎn)足夠的信心。國(guó)內(nèi)已經(jīng)有部分公司在他們的辦公自動(dòng)化等Web項(xiàng)目中使用poi了,如日恒的ioffice,海泰的HTOffice等。

              java當(dāng)初把核心處理設(shè)成Unicode,帶來(lái)的好處是另代碼適應(yīng)了多語(yǔ)言環(huán)境。然而由于老外的英語(yǔ)只有26個(gè)字母,有些情況下,一些程序員用8位的byte處理,一不小心就去掉了CJK的高位。或者是由于習(xí)慣在程序中采用硬編碼,還有多種原因,使得許多java應(yīng)用在CJK的處理上很煩惱。還好在POI HSSF中考慮到這個(gè)問(wèn)題,可以設(shè)置encoding為雙字節(jié)。

              POI可以到www.apache.org下載到。編譯好的jar主要有這樣4個(gè):poi,poi Browser,poi hdf,poi hssf例程包。實(shí)際運(yùn)行時(shí),需要有poi包就可以了。如果用Jakarta ant編譯和運(yùn)行,下載apache Jakarta POIrelease中的src包,它里面已經(jīng)為你生成好了build文件了。只要運(yùn)行ant就可以了(ant 的安裝和使用在此不說(shuō)了)。如果是用Jbuilder 運(yùn)行,請(qǐng)?jiān)谛陆ǖ捻?xiàng)目中加入poi包。以Jbuilder6為例,選擇Tools菜單項(xiàng)的config libraries...選項(xiàng),新建一個(gè)lib。在彈出的菜單中選擇poi包,如這個(gè)jakarta-poi-1.5.1-final-20020820.jar,把poi添加到jbuilder中。然后,右鍵點(diǎn)擊你的項(xiàng)目,在projectproperties菜單中pathrequired Libraries中,點(diǎn)add,添加剛才加入到jbuilder中的poi到你現(xiàn)在的項(xiàng)目中。如果你僅僅是為了熟悉POI hssf的使用,可以直接看POIsamples包中的源代碼,并且運(yùn)行它。hssf的各種對(duì)象都有例程的介紹。hssf提供的例程在org.apache.poi.hssf.usermodel.examples包中,共有14個(gè),生成的目標(biāo)xls都是workbook.xls。如果你想看更多的例程,可以參考hssfJunit test cases,在poi的包的源代碼中有。hssf都有測(cè)試代碼。

              這里只對(duì)部分例程的實(shí)現(xiàn)做介紹。

              HSSF提供給用戶(hù)使用的對(duì)象在org.apache.poi.hssf.usermodel包中,主要部分包括Excell對(duì)象,樣式和格式,還有輔助操作。有以下幾種對(duì)象:

                  HSSFWorkbook excell的文檔對(duì)象

                  HSSFSheet excell的表單

                  HSSFRow excell的行

                  HSSFCell excell的格子單元

                  HSSFFont excell字體

                  HSSFName 名稱(chēng)

                  HSSFDataFormat 日期格式

              在poi1.7中才有以下2項(xiàng):

                  HSSFHeader sheet

                  HSSFFooter sheet

              和這個(gè)樣式

                  HSSFCellStyle cell樣式

              輔助操作包括

                  HSSFDateUtil 日期

                  HSSFPrintSetup 打印

                  HSSFErrorConstants 錯(cuò)誤信息表

              仔細(xì)看org.apache.poi.hssf包的結(jié)構(gòu),不難發(fā)現(xiàn)HSSF的內(nèi)部實(shí)現(xiàn)遵循的是MVC模型。

              這里我用Roseorg.apache.poi.hssf.usermodel包中的對(duì)象反向?qū)氩⒏鶕?jù)相互關(guān)系作了整理。從中不難可以發(fā)現(xiàn)每一個(gè)基本對(duì)象都關(guān)聯(lián)了一個(gè)Record對(duì)象。Record對(duì)象是一個(gè)參考Office格式的相關(guān)記錄。

              HSSFWorkbook即是一個(gè)Excell對(duì)象。這幅類(lèi)圖體現(xiàn)的是HSSFWorkbook和基本對(duì)象的相互關(guān)系。可見(jiàn),許多對(duì)象中也建立了Workbook的引用。還需要注意的是在HSSFWorkbookHSSFSheet中建立了log機(jī)制POILogger,而且POILogger也是使用apache Log4J實(shí)現(xiàn)的。

              先看poiexamples包中提供的最簡(jiǎn)單的例子,建立一個(gè)空xls文件。

              

           1import org.apache.poi.hssf.usermodel.HSSFWorkbook;
           2
           3import java.io.FileOutputStream;
           4
           5import java.io.IOException;
           6
           7public class NewWorkbook{
           8
           9public static void main(String[] args) throws IOException{
          10
          11        HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對(duì)象
          12
          13        FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          14
          15        wb.write(fileOut);//把Workbook對(duì)象輸出到文件workbook.xls中
          16
          17        ileOut.close();
          18
          19    }

          20}

              

              通過(guò)這個(gè)例子,我們建立的是一個(gè)空白的xls文件(不是空文件)。在此基礎(chǔ)上,我們可以進(jìn)一步看其它的例子。

           1import org.apache.poi.hssf.usermodel.*;
           2
           3import java.io.FileOutputStream;
           4
           5import java.io.IOException;
           6
           7public class CreateCells
           8
           9{
          10
          11    public static void main(String[] args)
          12
          13    throws IOException
          14
          15    {
          16
          17        HSSFWorkbook wb = new HSSFWorkbook();// 建立新HSSFWorkbook對(duì)象
          18
          19        HSSFSheet sheet = wb.createSheet("new sheet");// 建立新的sheet對(duì)象
          20
          21        // Create a row and put some cells in it. Rows are 0 based.
          22
          23        HSSFRow row = sheet.createRow((short0);// 建立新行
          24
          25        // Create a cell and put a value in it.
          26
          27        HSSFCell cell = row.createCell((short0);// 建立新cell
          28
          29        cell.setCellValue(1);// 設(shè)置cell的整數(shù)類(lèi)型的值
          30
          31        // Or do it on one line.
          32
          33        row.createCell((short1).setCellValue(1.2);// 設(shè)置cell浮點(diǎn)類(lèi)型的值
          34
          35        row.createCell((short2).setCellValue("test");// 設(shè)置cell字符類(lèi)型的值
          36
          37        row.createCell((short3).setCellValue(true);// 設(shè)置cell布爾類(lèi)型的值
          38
          39        HSSFCellStyle cellStyle = wb.createCellStyle();// 建立新的cell樣式
          40
          41        cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));// 設(shè)置cell樣式為定制的日期格式
          42
          43        HSSFCell dCell = row.createCell((short4);
          44
          45        dCell.setCellValue(new Date());// 設(shè)置cell為日期類(lèi)型的值
          46
          47        dCell.setCellStyle(cellStyle); // 設(shè)置該cell日期的顯示格式
          48
          49        HSSFCell csCell = row.createCell((short5);
          50
          51        csCell.setEncoding(HSSFCell.ENCODING_UTF_16);// 設(shè)置cell編碼解決中文高位字節(jié)截?cái)?/span>
          52
          53        csCell.setCellValue("中文測(cè)試_Chinese Words Test");// 設(shè)置中西文結(jié)合字符串
          54
          55        row.createCell((short6).setCellType(HSSFCell.CELL_TYPE_ERROR);// 建立錯(cuò)誤cell
          56
          57        // Write the output to a file
          58
          59        FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          60
          61        wb.write(fileOut);
          62
          63        fileOut.close();
          64
          65    }

          66
          67}


              我稍微修改了原來(lái)的examples包中的CreateCells類(lèi)寫(xiě)了上面的功能測(cè)試類(lèi)。通過(guò)這個(gè)例子,我們可以清楚的看到xls文件從大到小包括了HSSFWorkbook HSSFSheet HSSFRow HSSFCell這樣幾個(gè)對(duì)象。我們可以在cell中設(shè)置各種類(lèi)型的值。尤其要注意的是如果你想正確的顯示非歐美的字符時(shí),尤其象中日韓這樣的語(yǔ)言,必須設(shè)置編碼為16位的即是HSSFCell.ENCODING_UTF_16,才能保證字符的高8位不被截?cái)喽鹁幋a失真形成亂碼。

              其他測(cè)試可以通過(guò)參考examples包中的測(cè)試?yán)诱莆?/font>poi的詳細(xì)用法,包括字體的設(shè)置,cell大小和低紋的設(shè)置等。需要注意的是POI是一個(gè)仍然在完善中的公開(kāi)代碼的項(xiàng)目,所以有些功能正在不斷的擴(kuò)充。如HSSFSheetgetFooter() getHeader()setFooter(HSSFFooter hsf) setHeader(HSSFHeader hsh)是在POI1.7中才有的,而POI1.5中就沒(méi)有。運(yùn)行測(cè)試熟悉代碼或者使用它做項(xiàng)目時(shí)請(qǐng)注意POI的版本。

              另外需要注意的是HSSF也有它的對(duì)xls基于事件的解析。可以參考例程中的EventExample.java。它通過(guò)實(shí)現(xiàn)HSSFListener完成從普通流認(rèn)知Xls中包含的內(nèi)容,在apache Cocoon中的org.apache.cocoon.serialization.HSSFSerializer中用到了這個(gè)解析。因?yàn)?/font>Cocoon2是基于事件的,所以POI為了提供快速的解析也提供了相應(yīng)的事件。當(dāng)然我們自己也可以實(shí)現(xiàn)這個(gè)事件接口。

          因?yàn)?font face="Times New Roman">POI還不是一個(gè)足夠成熟的項(xiàng)目,所以有必要做進(jìn)一步的開(kāi)發(fā)和測(cè)試。但是它已經(jīng)為我們用純java操作ole2對(duì)象提供了可能,而且克服了ole對(duì)象調(diào)用的缺陷,提供了服務(wù)器端的Excel解決方案。

              

              為了保證示例程序的運(yùn)行,必須安裝Java 2 sdk1.4.0 Jakarta POIJakarta POIWeb站點(diǎn)是: http://jakarta.apache.org/poi/

              
              示例1將演示
              如何利用
          Jakarta POI API 創(chuàng)建Excel 文檔。
             

           1import org.apache.poi.hssf.usermodel.HSSFWorkbook;
           2import org.apache.poi.hssf.usermodel.HSSFSheet;
           3import org.apache.poi.hssf.usermodel.HSSFRow;
           4import org.apache.poi.hssf.usermodel.HSSFCell;
           5import java.io.FileOutputStream;
           6public class CreateXL {
           7 /** Excel 文件要存放的位置,假定在D盤(pán)JTest目錄下*/
           8 public static String outputFile="D:/JTest/ gongye.xls";
           9 public static void main(String argv[]){
          10     try{
          11      // 創(chuàng)建新的Excel 工作簿
          12      HSSFWorkbook workbook = new HSSFWorkbook();
          13      // 在Excel工作簿中建一工作表,其名為缺省值
          14      // 如要新建一名為"效益指標(biāo)"的工作表,其語(yǔ)句為:
          15      // HSSFSheet sheet = workbook.createSheet("效益指標(biāo)");
          16      HSSFSheet sheet = workbook.createSheet();
          17      // 在索引0的位置創(chuàng)建行(最頂端的行)
          18      HSSFRow row = sheet.createRow((short)0);
          19      //在索引0的位置創(chuàng)建單元格(左上端)
          20      HSSFCell cell = row.createCell((short0);
          21      // 定義單元格為字符串類(lèi)型
          22      cell.setCellType(HSSFCell.CELL_TYPE_STRING);
          23      // 在單元格中輸入一些內(nèi)容
          24      cell.setCellValue("增加值");
          25      // 新建一輸出文件流
          26      FileOutputStream fOut = new FileOutputStream(outputFile);
          27      // 把相應(yīng)的Excel 工作簿存盤(pán)
          28      workbook.write(fOut);
          29      fOut.flush();
          30      // 操作結(jié)束,關(guān)閉文件
          31      fOut.close();
          32      System.out.println("文件生成");
          33    
          34    
          35     }
          catch(Exception e) {
          36      System.out.println("已運(yùn)行 xlCreate() : " + e );
          37     }

          38    }

          39}


          讀取Excel文檔中的數(shù)據(jù)
            示例2將演示如何讀取Excel文檔中的數(shù)據(jù)。假定在D盤(pán)JTest目錄下有一個(gè)文件名為gongye.xlsExcel文件。

            示例2程序如下:

           

           1import org.apache.poi.hssf.usermodel.HSSFWorkbook;
           2import org.apache.poi.hssf.usermodel.HSSFSheet;
           3import org.apache.poi.hssf.usermodel.HSSFRow;
           4import org.apache.poi.hssf.usermodel.HSSFCell;
           5import java.io.FileInputStream;
           6public class ReadXL {
           7 /** Excel文件的存放位置。注意是正斜線*/
           8 public static String fileToBeRead="D:/JTest/ gongye.xls";
           9 public static void main(String argv[])
          10 try{
          11  // 創(chuàng)建對(duì)Excel工作簿文件的引用
          12  HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(fileToBeRead));
          13  // 創(chuàng)建對(duì)工作表的引用。
          14  // 本例是按名引用(讓我們假定那張表有著缺省名"Sheet1")
          15  HSSFSheet sheet = workbook.getSheet("Sheet1");
          16  // 也可用getSheetAt(int index)按索引引用,
          17  // 在Excel文檔中,第一張工作表的缺省索引是0,
          18  // 其語(yǔ)句為:HSSFSheet sheet = workbook.getSheetAt(0);
          19  // 讀取左上端單元
          20  HSSFRow row = sheet.getRow(0);
          21  HSSFCell cell = row.getCell((short)0);
          22  // 輸出單元內(nèi)容,cell.getStringCellValue()就是取所在單元的值
          23  System.out.println("左上端單元是: " + cell.getStringCellValue()); 
          24 }
          catch(Exception e) {
          25  System.out.println("已運(yùn)行xlRead() : " + e );
          26 }

          27}

           設(shè)置單元格格式

            在這里,我們將只介紹一些和格式設(shè)置有關(guān)的語(yǔ)句,我們假定workbook就是對(duì)一個(gè)工作簿的引用。在Java中,第一步要做的就是創(chuàng)建和設(shè)置字體和單元格的格式,然后再應(yīng)用這些格式:

              

              1、創(chuàng)建字體,設(shè)置其為紅色、粗體:

          1HSSFFont font = workbook.createFont();
          2font.setColor(HSSFFont.COLOR_RED);
          3font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

           

              2、創(chuàng)建格式

          1HSSFCellStyle cellStyle= workbook.createCellStyle();
          2cellStyle.setFont(font);

           
              3、應(yīng)用格式 

           

          1HSSFCell cell = row.createCell((short0);
          2cell.setCellStyle(cellStyle);
          3cell.setCellType(HSSFCell.CELL_TYPE_STRING);
          4cell.setCellValue("標(biāo)題 ");

           

              總之,如本篇文章所演示的一樣,Java程序員不必?fù)?dān)心Excel工作表中的數(shù)據(jù)了,利用Jakarta POI API我們就可以輕易的在程序中存取Excel文檔。

           

              總結(jié)說(shuō)說(shuō)現(xiàn)在我所知道的Java編輯Excel文件的兩大開(kāi)源工具:

              jakarta POIJavaExcelAPI(簡(jiǎn)稱(chēng)JXL),這兩套工具我都試用了一這段時(shí)間,感覺(jué)各有優(yōu)劣吧。POI在某些細(xì)節(jié)有些小Bug并且不支持寫(xiě)入圖片,其他方面都挺不錯(cuò)的;

          JXL就慘了,除了支持寫(xiě)入圖片外,我暫時(shí)看不到它比POI好的地方,我碰到的主要的問(wèn)題就是對(duì)公式支持不是很好,很多帶有公式的Excel文件用JXL打開(kāi)后,公式就丟失了(比如now(),today()),在網(wǎng)上看到其他大蝦評(píng)論說(shuō)JXL寫(xiě)入公式也有問(wèn)題,另外,JXL操作Excel文件的效率比POI低一點(diǎn)。經(jīng)過(guò)比較后,我選擇了POI開(kāi)發(fā)我的項(xiàng)目。

          posted on 2011-07-04 16:10 何智 閱讀(8308) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): Java Util

          評(píng)論

          # re: java的POI操作Excel文件 2013-10-17 17:54 八腳豬子

          cell21.setEncoding(HSSFCell.ENCODING_UTF_16);
          成功解決導(dǎo)出亂碼問(wèn)題..非常非常感謝  回復(fù)  更多評(píng)論   

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導(dǎo)航

          統(tǒng)計(jì)

          留言簿(1)

          文章分類(lèi)

          文章檔案

          搜索

          最新評(píng)論

          主站蜘蛛池模板: 永丰县| 锡林郭勒盟| 东光县| 晋江市| 营口市| 汉川市| 建平县| 彰化县| 紫阳县| 明水县| 西林县| 高陵县| 府谷县| 昌都县| 庄浪县| 晋州市| 阿瓦提县| 页游| 台东县| 葫芦岛市| 安泽县| 霍州市| 桃园市| 蓝田县| 兴仁县| 周口市| 巴东县| 永清县| 嘉禾县| 灌南县| 平利县| 满洲里市| 阿拉尔市| 丹巴县| 江华| 淮安市| 宜春市| 溆浦县| 东明县| 江北区| 略阳县|