隨筆 - 154  文章 - 60  trackbacks - 0
          <2007年10月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          聲明:

          該blog是為了收集資料,認(rèn)識(shí)朋友,學(xué)習(xí)、提高技術(shù),所以本blog的內(nèi)容除非聲明,否則一律為轉(zhuǎn)載!!

          感謝那些公開(kāi)自己技術(shù)成果的高人們!!!

          支持開(kāi)源,尊重他人的勞動(dòng)!!

          常用鏈接

          留言簿(3)

          隨筆分類(148)

          隨筆檔案(143)

          收藏夾(2)

          其他

          學(xué)習(xí)(技術(shù))

          觀察思考(非技術(shù))

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          今天又用到了excel操作但由于相隔久遠(yuǎn)只好重新復(fù)習(xí),順便整理一下,之前整理了JavaExcelAPI(簡(jiǎn)稱JXL)的,由于POI用的不是很多就把4篇整理到一個(gè)blog中!!

          akata Poi HSSF:純java的Excel解決方案
          2002-10-23 上午 08:52:34

          微軟在桌面系統(tǒng)上的成功,令我們不得不大量使用它的辦公產(chǎn)品,如:Word,Excel。時(shí)至今日,它的源代碼仍然不公開(kāi)已封鎖了我們的進(jìn)一步應(yīng)用和開(kāi)發(fā)。然而在要求更高的服務(wù)器領(lǐng)域,微軟本身的產(chǎn)品移植性不好,
          性能不佳。在我們實(shí)際的開(kāi)發(fā)中,表現(xiàn)層的解決方案雖然有多樣,但是Ie瀏覽器已成為最多人使用的瀏覽器,因?yàn)榇蠹叶加肳indows。在企業(yè)辦公系統(tǒng)中,常常有客戶這樣子要求:你要把我們的報(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)境,難道我為了解決打印的要求去另寫客戶端的控件?或者在服務(wù)器端使用本地代碼?第一種方案的問(wèn)題是關(guān)鍵數(shù)據(jù)的處理有時(shí)候不能在客戶端做,第2種方案的問(wèn)題是犧牲了代碼的可移植性和穩(wěn)定性。如果讓客戶端只負(fù)責(zé)處理生成好的報(bào)表,那將是一種誘人的選擇。

          Apache的Jakata項(xiàng)目的POI子項(xiàng)目,目標(biāo)是處理ole2對(duì)象。目前比較成熟的是HSSF接口,處理MS Excel(97-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年夏天starOffice被sun收購(gòu),再到2000年6月starOffice5.2的發(fā)布;并且從starOffice6.0開(kāi)始,starOffice建立在OpenOffice的api的基礎(chǔ)上,這個(gè)公開(kāi)代碼的office項(xiàng)目已經(jīng)進(jìn)行了很長(zhǎng)的時(shí)間。雖然那是由C++寫的,但是POI的代碼部分也是由openOffice改過(guò)來(lái)的。所以,應(yīng)該對(duì)POI充滿足夠的信心。國(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 POI的release中的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添加到j(luò)builder中。然后,右鍵點(diǎn)擊你的項(xiàng)目,在project的properties菜單中path的required Libraries中,點(diǎn)add,添加剛才加入到j(luò)builder中的poi到你現(xiàn)在的項(xiàng)目中。如果你僅僅是為了熟悉POI hssf的使用,可以直接看POI的samples包中的源代碼,并且運(yùn)行它。hssf的各種對(duì)象都有例程的介紹。hssf提供的例程在org.apache.poi.hssf.usermodel.examples包中,共有14個(gè),生成的目標(biāo)xls都是workbook.xls。如果你想看更多的例程,可以參考hssf的Junit test cases,在poi的包的源代碼中有。hssf都有測(cè)試代碼。

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

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

          HSSFWorkbook excell的文檔對(duì)象

          HSSFSheet excell的表單

          HSSFRow excell的行

          HSSFCell excell的格子單元

          HSSFFont excell字體

          HSSFName 名稱

          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模型。

          這里我用Rose把org.apache.poi.hssf.usermodel包中的對(duì)象反向?qū)氩⒏鶕?jù)相互關(guān)系作了整理,詳見(jiàn)下面兩圖:

          圖1 基本對(duì)象

          從中不難可以發(fā)現(xiàn)每一個(gè)基本對(duì)象都關(guān)聯(lián)了一個(gè)Record對(duì)象。Record對(duì)象是一個(gè)參考Office格式的相關(guān)記錄。

          圖2 HSSFWorkbook

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

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

          import org.apache.poi.hssf.usermodel.HSSFWorkbook;

          import java.io.FileOutputStream;

          import java.io.IOException;

          public class NewWorkbook

          {

          public static void main(String[] args)

          throws IOException

          {

          HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對(duì)象

          FileOutputStream fileOut = new FileOutputStream("workbook.xls");

          wb.write(fileOut);//把Workbook對(duì)象輸出到文件workbook.xls中

          fileOut.close();

          }

          }

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

          import org.apache.poi.hssf.usermodel.*;

          import java.io.FileOutputStream;

          import java.io.IOException;

          public class CreateCells

          {

          public static void main(String[] args)

          throws IOException

          {

          HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對(duì)象

          HSSFSheet sheet = wb.createSheet("new sheet");//建立新的sheet對(duì)象

          // Create a row and put some cells in it. Rows are 0 based.

          HSSFRow row = sheet.createRow((short)0);//建立新行

          // Create a cell and put a value in it.

          HSSFCell cell = row.createCell((short)0);//建立新cell

          cell.setCellValue(1);//設(shè)置cell的整數(shù)類型的值

          // Or do it on one line.

          row.createCell((short)1).setCellValue(1.2);//設(shè)置cell浮點(diǎn)類型的值

          row.createCell((short)2).setCellValue("test");//設(shè)置cell字符類型的值

          row.createCell((short)3).setCellValue(true);//設(shè)置cell布爾類型的值

          HSSFCellStyle cellStyle = wb.createCellStyle();//建立新的cell樣式

          cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));//設(shè)置cell樣式為定制的日期格式

          HSSFCell dCell =row.createCell((short)4);

          dCell.setCellValue(new Date());//設(shè)置cell為日期類型的值

          dCell.setCellStyle(cellStyle); //設(shè)置該cell日期的顯示格式

          HSSFCell csCell =row.createCell((short)5);

          csCell.setEncoding(HSSFCell.ENCODING_UTF_16);//設(shè)置cell編碼解決中文高位字節(jié)截?cái)?/p>

          csCell.setCellValue("中文測(cè)試_Chinese Words Test");//設(shè)置中西文結(jié)合字符串

          row.createCell((short)6).setCellType(HSSFCell.CELL_TYPE_ERROR);//建立錯(cuò)誤cell

          // Write the output to a file

          FileOutputStream fileOut = new FileOutputStream("workbook.xls");

          wb.write(fileOut);

          fileOut.close();

          }

          }

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

          其他測(cè)試可以通過(guò)參考examples包中的測(cè)試?yán)诱莆誴oi的詳細(xì)用法,包括字體的設(shè)置,cell大小和低紋的設(shè)置等。需要注意的是POI是一個(gè)仍然在完善中的公開(kāi)代碼的項(xiàng)目,所以有些功能正在不斷的擴(kuò)充。如HSSFSheet的getFooter() 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)镃ocoon2是基于事件的,所以POI為了提供快速的解析也提供了相應(yīng)的事件。當(dāng)然我們自己也可以實(shí)現(xiàn)這個(gè)事件接口。

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

          利用Java 創(chuàng)建和讀取Excel文檔 

          --------------------------------------------------------------------------------
          源作者:Rubber                   人氣:26748 
             為了保證示例程序的運(yùn)行,必須安裝Java 2 sdk1.4.0 和Jakarta POI,Jakarta POI的Web站點(diǎn)是: http://jakarta.apache.org/poi/

           

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

           

          示例1程序如下:
          import org.apache.poi.hssf.usermodel.HSSFWorkbook;
          import org.apache.poi.hssf.usermodel.HSSFSheet;
          import org.apache.poi.hssf.usermodel.HSSFRow;
          import org.apache.poi.hssf.usermodel.HSSFCell;
          import java.io.FileOutputStream;
          public class CreateXL {
           /** Excel 文件要存放的位置,假定在D盤JTest目錄下*/
           public static String outputFile="D:/JTest/ gongye.xls";
           public static void main(String argv[])
            {
           try
            {
            // 創(chuàng)建新的Excel 工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            // 在Excel工作簿中建一工作表,其名為缺省值
            // 如要新建一名為"效益指標(biāo)"的工作表,其語(yǔ)句為:
            // HSSFSheet sheet = workbook.createSheet("效益指標(biāo)");
            HSSFSheet sheet = workbook.createSheet();
            // 在索引0的位置創(chuàng)建行(最頂端的行)
            HSSFRow row = sheet.createRow((short)0);
            //在索引0的位置創(chuàng)建單元格(左上端)
            HSSFCell cell = row.createCell((short) 0);
            // 定義單元格為字符串類型
            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            // 在單元格中輸入一些內(nèi)容
            cell.setCellValue("增加值");
            // 新建一輸出文件流
            FileOutputStream fOut = new FileOutputStream(outputFile);
            // 把相應(yīng)的Excel 工作簿存盤
            workbook.write(fOut);
            fOut.flush();
            // 操作結(jié)束,關(guān)閉文件
            fOut.close();
            System.out.println("文件生成...");

           

           }catch(Exception e) {
            System.out.println("已運(yùn)行 xlCreate() : " + e );
           }
          }
          }

           

          讀取Excel文檔中的數(shù)據(jù)
            示例2將演示如何讀取Excel文檔中的數(shù)據(jù)。假定在D盤JTest目錄下有一個(gè)文件名為gongye.xls的Excel文件。
            示例2程序如下:
          import org.apache.poi.hssf.usermodel.HSSFWorkbook;
          import org.apache.poi.hssf.usermodel.HSSFSheet;
          import org.apache.poi.hssf.usermodel.HSSFRow;
          import org.apache.poi.hssf.usermodel.HSSFCell;
          import java.io.FileInputStream;
          public class ReadXL {
           /** Excel文件的存放位置。注意是正斜線*/
           public static String fileToBeRead="D:/JTest/ gongye.xls";
           public static void main(String argv[]){
           try{
            // 創(chuàng)建對(duì)Excel工作簿文件的引用
            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(fileToBeRead));
            // 創(chuàng)建對(duì)工作表的引用。
            // 本例是按名引用(讓我們假定那張表有著缺省名"Sheet1")
            HSSFSheet sheet = workbook.getSheet("Sheet1");
            // 也可用getSheetAt(int index)按索引引用,
            // 在Excel文檔中,第一張工作表的缺省索引是0,
            // 其語(yǔ)句為:HSSFSheet sheet = workbook.getSheetAt(0);
            // 讀取左上端單元
            HSSFRow row = sheet.getRow(0);
            HSSFCell cell = row.getCell((short)0);
            // 輸出單元內(nèi)容,cell.getStringCellValue()就是取所在單元的值
            System.out.println("左上端單元是: " + cell.getStringCellValue());
           }catch(Exception e) {
            System.out.println("已運(yùn)行xlRead() : " + e );
           }
          }
          }

           
            設(shè)置單元格格式
            在這里,我們將只介紹一些和格式設(shè)置有關(guān)的語(yǔ)句,我們假定workbook就是對(duì)一個(gè)工作簿的引用。在Java

           中,第一步要做的就是創(chuàng)建和設(shè)置字體和單元格的格式,然后再應(yīng)用這些格式: 

            1、創(chuàng)建字體,設(shè)置其為紅色、粗體:
          HSSFFont font = workbook.createFont();
          font.setColor(HSSFFont.COLOR_RED);
          font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            2、創(chuàng)建格式
          HSSFCellStyle cellStyle= workbook.createCellStyle();
          cellStyle.setFont(font);
            3、應(yīng)用格式
          HSSFCell cell = row.createCell((short) 0);
          cell.setCellStyle(cellStyle);
          cell.setCellType(HSSFCell.CELL_TYPE_STRING);
          cell.setCellValue("標(biāo)題 "); 

            總之,如本篇文章所演示的一樣,Java程序員不必?fù)?dān)心Excel工作表中的數(shù)據(jù)了,利用Jakarta POI API, 

          我們就可以輕易的在程序中存取Excel文檔。

           ==============================================

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

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

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

          現(xiàn)在我要做的東西基本完成啦,我把這段時(shí)間使用POI的一些心得總結(jié)出來(lái),希望能對(duì)和我遇到相同問(wèn)題的朋友有所幫助,至于POI基本的使用方法,自己去看文檔吧。

          1、設(shè)置分頁(yè)符的bug

          POI里的HSSFSheet類提供了setRowBreak方法可以設(shè)置Sheet的分頁(yè)符。

          Bug:如果你要設(shè)置分頁(yè)符的Sheet是本來(lái)就有的,并且你沒(méi)有在里面插入過(guò)分頁(yè)符,那么調(diào)用setRowBreak時(shí)POI會(huì)拋出空指針的異常。

          解決方法:在Excel里給這個(gè)sheet插入一個(gè)分頁(yè)符,用POI打開(kāi)后再把它刪掉,然后你就可以隨意插入分頁(yè)符了。

          如果sheet是由POI生成的則沒(méi)有這個(gè)問(wèn)題。我跟蹤了setRowBreak的源代碼,發(fā)現(xiàn)是Sheet.Java下的PageBreakRecord rowBreaks這個(gè)變量在搞鬼,如果Sheet里原來(lái)沒(méi)有分頁(yè)符,開(kāi)發(fā)這個(gè)模塊的那位兄臺(tái)忘了為這個(gè)對(duì)象new實(shí)例,所以只能我們先手工給Excel插入一個(gè)分頁(yè)符來(lái)觸發(fā)POI為rowBreaks創(chuàng)建實(shí)例。

          2、如何拷貝行

          我在gmane.org的POI用戶論壇翻遍了每個(gè)相關(guān)的帖子,找遍了api,也沒(méi)看到一個(gè)拷貝行的方法,沒(méi)辦法,只能自己寫:

           

          //注:this.fWorkbook是一個(gè)HSSHWorkbook,請(qǐng)自行在外部new
              public void copyRows
              (String pSourceSheetName,
              String pTargetSheetName,
              int pStartRow, int pEndRow,
              int pPosition)
              {
              HSSFRow sourceRow = null;
              HSSFRow targetRow = null;
              HSSFCell sourceCell = null;
              HSSFCell targetCell = null;
              HSSFSheet sourceSheet = null;
              HSSFSheet targetSheet = null;
              Region region = null;
              int cType;
              int i;
              short j;
              int targetRowFrom;
              int targetRowTo;
             
              if ((pStartRow == -1) || (pEndRow == -1))
              {
                return;
              }
              sourceSheet = this.fWorkbook.getSheet(pSourceSheetName);
              targetSheet = this.fWorkbook.getSheet(pTargetSheetName);
              //拷貝合并的單元格
              for (i = 0; i < sourceSheet.getNumMergedRegions(); i++)
              {
              region = sourceSheet.getMergedRegionAt(i);
              if ((region.getRowFrom() >= pStartRow) && (region.getRowTo() <= pEndRow))
              {
              targetRowFrom = region.getRowFrom() - pStartRow + pPosition;
              targetRowTo = region.getRowTo() - pStartRow + pPosition;
              region.setRowFrom(targetRowFrom);
              region.setRowTo(targetRowTo);
              targetSheet.addMergedRegion(region);
              }
              }
              //設(shè)置列寬
              for (i = pStartRow; i <= pEndRow; i++)
              {
              sourceRow = sourceSheet.getRow(i);
              if (sourceRow != null)
              {
              for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)
              {
              targetSheet.setColumnWidth(j, sourceSheet.getColumnWidth(j));
              }
              break;
              }
              }
              //拷貝行并填充數(shù)據(jù)
              for (;i <= pEndRow; i++)
              {
              sourceRow = sourceSheet.getRow(i);
              if (sourceRow == null)
              {
              continue;
              }
              targetRow = targetSheet.createRow(i - pStartRow + pPosition);
              targetRow.setHeight(sourceRow.getHeight());
              for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)
              {
              sourceCell = sourceRow.getCell(j);
              if (sourceCell == null)
              {
              continue;
              }
              targetCell = targetRow.createCell(j);
              targetCell.setEncoding(sourceCell.getEncoding());
              targetCell.setCellStyle(sourceCell.getCellStyle());
              cType = sourceCell.getCellType();
              targetCell.setCellType(cType);
              switch (cType)
              {
              case HSSFCell.CELL_TYPE_BOOLEAN:
              targetCell.setCellValue(sourceCell.getBooleanCellValue());
              break;
              case HSSFCell.CELL_TYPE_ERROR:
              targetCell.setCellErrorValue(sourceCell.getErrorCellValue());
              break;           
              case HSSFCell.CELL_TYPE_FORMULA:
              //parseFormula這個(gè)函數(shù)的用途在后面說(shuō)明
              targetCell.setCellFormula(parseFormula(sourceCell.getCellFormula()));
              break;
              case HSSFCell.CELL_TYPE_NUMERIC:
              targetCell.setCellValue(sourceCell.getNumericCellValue());
              break;
              case HSSFCell.CELL_TYPE_STRING:
              targetCell.setCellValue(sourceCell.getStringCellValue());
              break;
              }
              }
              }
              }
           
          這個(gè)函數(shù)有兩個(gè)問(wèn)題暫時(shí)無(wú)法解決:

          a、只能在同一個(gè)Workbook里面使用,跨Workbook總是拷不過(guò)去,不知道為什么?

          b、由于在拷貝行時(shí)也把行高也拷過(guò)去了,如果往這些單元格里寫入的數(shù)據(jù)長(zhǎng)度超過(guò)單元格長(zhǎng)度,那么他們不會(huì)自動(dòng)調(diào)整行高!

          3、公式的問(wèn)題

          POI對(duì)Excel公式的支持是相當(dāng)好的,但是我發(fā)現(xiàn)一個(gè)問(wèn)題,如果公式里面的函數(shù)不帶參數(shù),比如now()或today(),那么你通過(guò)getCellFormula()取出來(lái)的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)),這樣的值寫入Excel是會(huì)出錯(cuò)的,這也是我上面copyRow的函數(shù)在寫入公式前要調(diào)用parseFormula的原因,parseFormula這個(gè)函數(shù)的功能很簡(jiǎn)單,就是把ATTR(semiVolatile)刪掉,我把它的代碼貼出來(lái):

           

          private String parseFormula(String pPOIFormula)
              {
              final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$
              StringBuffer result = null;
              int index;
             
              result = new StringBuffer();
              index = pPOIFormula.indexOf(cstReplaceString);
              if (index >= 0)
              {
              result.append(pPOIFormula.substring(0, index));
              result.append(pPOIFormula.substring(index + cstReplaceString.length()));
              }
              else
              {
              result.append(pPOIFormula);
              }
             
              return result.toString();
              }
           

          至于為什么會(huì)出現(xiàn)ATTR(semiVolatile),還需要大家的探索精神!

          4、向Excel寫入圖片的問(wèn)題。

          我上POI論壇查相關(guān)帖子,得到兩種結(jié)論:

          1、不支持寫入圖片;

          2、支持寫入圖片,通過(guò)EscherGraphics2d這個(gè)Class實(shí)現(xiàn)。于是我就去查EscherGraphics2d這個(gè)Class,發(fā)現(xiàn)這個(gè)Class提供了N個(gè)drawImage方法,喜出望外的我開(kāi)始寫代碼,結(jié)果調(diào)了一天,一直看不到效果,黔驢技窮的我在萬(wàn)般無(wú)奈下只好跟蹤進(jìn)drawImage這個(gè)函數(shù)內(nèi)部,經(jīng)過(guò)N個(gè)函數(shù)調(diào)用后在最底層函數(shù)發(fā)現(xiàn)了最終答案:


          public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
             int sx2, int sy2, Color bgColor, ImageObserver imageobserver)
             {
             if (logger.check( POILogger.WARN ))
             logger.log(POILogger.WARN,"drawImage() not supported");
             return true;
             }
           

          所以我強(qiáng)烈建議大家,以后使用第三方開(kāi)發(fā)包一定盡量下載它的源代碼,這樣你在碰到問(wèn)題時(shí),看看它的的內(nèi)部是怎么實(shí)現(xiàn)的,很多時(shí)候就可以不必重蹈我的覆轍了。既然POI不能寫入圖片,那我們只能把目光投向JXL,我用JXL寫入圖片功能是實(shí)現(xiàn)了,付出的代價(jià)是now()和today()這些函數(shù)丟失掉了,魚(yú)與熊掌不能兼得吧。

           ==========================jsp操作===============================

          <%@ page contentType="application/msexcel;charset=gb2312" %>
          response.setHeader("Content-disposition","inline; filename=test1.xls");
             //以上這行設(shè)定傳送到前端瀏覽器時(shí)的檔名為test1.xls
             //就是靠這一行,讓前端瀏覽器以為接收到一個(gè)excel檔
          下面正常顯示要轉(zhuǎn)化的表

          --------------------------------------------------------------------------

          介紹:
          Jakarta_POI 使用Java讀寫Excel(97-2002)文件,可以滿足大部分的需要。
          因?yàn)閯偤糜幸粋€(gè)項(xiàng)目使用到了這個(gè)工具,花了點(diǎn)時(shí)間順便翻譯了一下POI本身
          帶的一個(gè)Guide.有一些節(jié)減和修改,希望給使用這個(gè)項(xiàng)目的人一些入門幫助。
          POI 下面有幾個(gè)自項(xiàng)目:HSSF用來(lái)實(shí)現(xiàn)Excel 的讀寫.以下是HSSF的主頁(yè)
          http://jakarta.apache.org/poi/hssf/index.html
          下面的介紹是基于以下地址的翻譯:
          http://jakarta.apache.org/poi/hssf/quick-guide.html
          目前的版本為1.51應(yīng)該是很長(zhǎng)時(shí)間之內(nèi)的一個(gè)穩(wěn)定版,但HSSF提供的Sample不是基于
          1.51所寫,所以使用的時(shí)候需要適當(dāng)?shù)淖⒁?
          其實(shí)POI下面的幾個(gè)子項(xiàng)目側(cè)重不同讀寫 Word 的HDF正在開(kāi)發(fā)當(dāng)中.
          XML下的FOP(http://xml.apache.org/fop/index.html)
          可以輸出pdf文件,也是比較好的一個(gè)工具
          目錄:
          創(chuàng)建一個(gè)workbook
          創(chuàng)建一個(gè)sheet
          創(chuàng)建cells
          創(chuàng)建日期cells
          設(shè)定單元格格式

          說(shuō)明:
          以下可能需要使用到如下的類
          import org.apache.poi.hssf.usermodel.HSSFCell;
          import org.apache.poi.hssf.usermodel.HSSFCellStyle;
          import org.apache.poi.hssf.usermodel.HSSFDataFormat;
          import org.apache.poi.hssf.usermodel.HSSFFont;
          import org.apache.poi.hssf.usermodel.HSSFRow;
          import org.apache.poi.hssf.usermodel.HSSFSheet;
          import org.apache.poi.hssf.usermodel.HSSFWorkbook;
          import org.apache.poi.hssf.util.HSSFColor;

          創(chuàng)建workbook

          HSSFWorkbook wb = new HSSFWorkbook();
          //使用默認(rèn)的構(gòu)造方法創(chuàng)建workbook
          FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          //指定文件名
          wb.write(fileOut);
          //輸出到文件
          fileOut.close();

          創(chuàng)建一個(gè)sheet

          HSSFWorkbook wb = new HSSFWorkbook();
          HSSFSheet sheet1 = wb.createSheet("new sheet");
          //workbook創(chuàng)建sheet
          HSSFSheet sheet2 = wb.createSheet("second sheet");
          //workbook創(chuàng)建另外的sheet
          FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          wb.write(fileOut);
          fileOut.close();

          創(chuàng)建cells
          HSSFWorkbook wb = new HSSFWorkbook();
          HSSFSheet sheet = wb.createSheet("new sheet");
          //注意以下的代碼很多方法的參數(shù)是short 而不是int 所以需要做一次類型轉(zhuǎn)換
          HSSFRow row = sheet.createRow((short)0);
          //sheet 創(chuàng)建一行
          HSSFCell cell = row.createCell((short)0);
          //行創(chuàng)建一個(gè)單元格
          cell.setCellValue(1);
          //設(shè)定單元格的值
          //值的類型參數(shù)有多中double ,String ,boolean,
          row.createCell((short)1).setCellValue(1.2);
          row.createCell((short)2).setCellValue("This is a string");
          row.createCell((short)3).setCellValue(true);

          // Write the output to a file
          FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          wb.write(fileOut);
          fileOut.close();

          創(chuàng)建日期cells
          HSSFWorkbook wb = new HSSFWorkbook();
          HSSFSheet sheet = wb.createSheet("new sheet");

          HSSFRow row = sheet.createRow((short)0);

          HSSFCell cell = row.createCell((short)0);
          //設(shè)定值為日期
          cell.setCellValue(new Date());

          HSSFCellStyle cellStyle = wb.createCellStyle();
          //指定日期顯示格式
          cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));
          cell = row.createCell((short)1);
          cell.setCellValue(new Date());
          //設(shè)定單元格日期顯示格式
          cell.setCellStyle(cellStyle);

          FileOutputStream fileOut = new FileOutputStream("workbook.xls");
          wb.write(fileOut);
          fileOut.close();


          設(shè)定單元格格式
          單元格格式的設(shè)定有很多形式包括單元格的對(duì)齊方式,內(nèi)容的字體設(shè)置,
          單元格的背景色等,因?yàn)樾问奖容^多,只舉一些例子.以下的例子在
          POI1.5中可能會(huì)有所改變具體查看API.
          ..........
          // Aqua background
          HSSFCellStyle style = wb.createCellStyle();
          //創(chuàng)建一個(gè)樣式
          style.setFillBackgroundColor(HSSFCellStyle.AQUA);
          //設(shè)定此樣式的的背景顏色填充
          style.setFillPattern(HSSFCellStyle.BIG_SPOTS);

          //樣式的填充類型。
          //有多種式樣如:
          //HSSFCellStyle.BIG_SPOTS
          //HSSFCellStyle.FINE_DOTS
          //HSSFCellStyle.SPARSE_DOTS等
          style.setAlignment(HSSFCellStyle.ALIGN_CENTER );
          //居中對(duì)齊
          style.setFillBackgroundColor(HSSFColor.GREEN.index);
          //設(shè)定單元個(gè)背景顏色
          style.setFillForegroundColor(HSSFColor.RED.index);
          //設(shè)置單元格顯示顏色
          HSSFCell cell = row.createCell((short) 1);
          cell.setCellValue("X");
          cell.setCellStyle(style);

          -----------------------------------------------------------------
          加上response.setContentType("Application/msexcel");
               response.setHeader("Content-disposition","attachment; filename=book.xls" );
          然后提交給它的時(shí)候會(huì)時(shí)候會(huì)提示下載,
          下載的就是生成的EXCEL文件。

          -----------------------------------------------------------


          有趣的是,對(duì)一個(gè)html文件(數(shù)據(jù)在表格中),當(dāng)把后綴改為xls后,打開(kāi)文件即是。

          ------------------------------------------

          >>加上response.setContentType("Application/msexcel");
          >>     response.setHeader("Content-disposition","attachment; >>filename=book.xls" );
          >>然后提交給它的時(shí)候會(huì)時(shí)候會(huì)提示下載,
          >>下載的就是生成的EXCEL文件。

          book.xls的存放路徑應(yīng)該是哪里?

          ----------------------------------------------------------------


          使用poi的hssf生成一個(gè)excel文件以后
          有一個(gè)主類Workbook(相當(dāng)于一個(gè)excel文件)的方法
          Workbook.write(OutputStream)可以寫到response.getOutputStream()里面
          如果事先設(shè)置response的contentType為excel和下載的附件名稱就可下載excel
              HSSFWorkbook book = _proxy.expertExcel(_formBean,_login);

              if(book!=null)
              {
                  response.setContentType ( "application/ms-excel" ) ;
                  response.setHeader ( "Content-Disposition" ,
                                       "attachment;filename="+new String("導(dǎo)出Excel.xls".getBytes(),"iso-8859-1"))

          ;
                  book.write(response.getOutputStream());
          }
          其中expertExcel無(wú)非是從數(shù)據(jù)庫(kù)或者其他地方獲取數(shù)據(jù)創(chuàng)建excel即可.

           


          ---------------------------------------------------------------
          response.setHeader("Content-disposition","attachment; filename=book.xls" );
          原來(lái)加上attachment瀏覽器就會(huì)提示保存或者打開(kāi),是我想要的。Thanks all.


          -------------------------------------------------------------------------

          1.用poi生成Excel文件,和WORD文檔都可以,是個(gè)不錯(cuò)的方法,參見(jiàn)poi網(wǎng)站,樓上的朋友描述的很清楚了,此方法適用于生

          成,讀取,解析xls文件
          2.另外一種更簡(jiǎn)單的方法:只適用于顯示用的EXCEL文件格式,生成常規(guī)的html文件格式,后綴命名方式為.xls即可.
          3.espreadsheet適用于網(wǎng)上即時(shí)的excel文件交互操作,生成,解析,保存修改,但需要購(gòu)買

          -------------------------------------------------------------------------

          生成一個(gè)rtf文件,然后擴(kuò)展名寫".doc",OK

          -----------------------------------------------------------

          用這個(gè)組件向excel寫數(shù)據(jù)時(shí),總是出現(xiàn)中文亂碼情況,請(qǐng)問(wèn)怎樣解決?

          源代碼:

            HSSFWorkbook wb = new HSSFWorkbook();
                  HSSFSheet sheet = wb.createSheet("new sheet");
                  HSSFHeader header = sheet.getHeader();
                  header.setCenter("Center Header");
                  HSSFRow row = sheet.createRow((short)0);                    
                  HSSFCell cell = row.createCell((short)0);                 
                  cell.setCellValue(1);                                        
                  row.createCell((short)1).setCellValue(1.2123654);
                  row.createCell((short)2).setCellValue("This is a string");
                  row.createCell((short)3).setCellValue(true);
                  row = sheet.createRow((short)1);
                  cell = row.createCell((short)0);                        
                  cell.setCellValue(new Date());                    
                  row.createCell((short)1).setCellValue(str);
                  row.createCell((short)2).setCellValue("This我是一個(gè)好人string");
                  FileOutputStream fileOut = new FileOutputStream("d:/filename.xls");
                  wb.write(fileOut);
                  fileOut.close();

          當(dāng)我打開(kāi)這個(gè)"d:/filename.xls"文件時(shí),其中寫入的中文全都是亂碼!!!
          如何解決???

          ----------------------------------------------------------------------

          源代碼:
                  HSSFWorkbook wb = new HSSFWorkbook();
                  HSSFSheet sheet = wb.createSheet("new sheet");
                  HSSFHeader header = sheet.getHeader();
                  header.setCenter("Center Header");
                  HSSFRow row = sheet.createRow((short)0);
                  HSSFCell cell = row.createCell((short)0);
                  cell.setCellValue(1);
                  row.createCell((short)1).setCellValue(1.2123654);
                  row.createCell((short)2).setCellValue("This is a string");
                  row.createCell((short)3).setCellValue(true);
                  row = sheet.createRow((short)1);
                  cell = row.createCell((short)0);  
                  cell.setCellValue(new Date());                    
                  String str = new String("我是一個(gè)好人!!!");
                  row.createCell((short)1).setCellValue(str);
                  row.createCell((short)2).setCellValue("This我是一個(gè)好人string");
                 
                  FileOutputStream fileOut = new FileOutputStream("d:/filename.xls");
                  wb.write(fileOut);
                  fileOut.close();
          當(dāng)我打開(kāi)“d:/filename.xls”文件察看時(shí),里面的中文字符全部是亂碼!
          請(qǐng)問(wèn)如何解決?

          ---------------------------------------------------------------------

          <%@ page contentType="application/msexcel;charset=gb2312" %>
          response.setHeader("Content-disposition","inline; filename=***.xls");就可以了,要是想要word 就
          <%@ page contentType="application/msword;charset=gb2312" %>
          response.setHeader("Content-disposition","inline; filename=test1.xls");


          -------------------------------------------------------------------

          引用 pengruihua 說(shuō):

                  有趣的是,對(duì)一個(gè)html文件(數(shù)據(jù)在表格中),當(dāng)把后綴改為xls后,打開(kāi)文件即是。

          這個(gè)只能說(shuō)明excel強(qiáng),這樣寫得xls,在JXL或者POI中都是不認(rèn)的。

          加一句,用POI寫Excel有點(diǎn)問(wèn)題,當(dāng)反復(fù)讀寫一個(gè)excel文件的時(shí)候,讀的速度會(huì)越來(lái)越慢。
          我的一個(gè)生成excel的就是,到了幾千條記錄的時(shí)候慢得就不能接受了,最后只好先生成cvs的文本,再將文本導(dǎo)成xls

          文件


          ---------------------------------------------------------------------------
          引用 java_century 說(shuō):

                  源代碼:
                  HSSFWorkbook wb = new HSSFWorkbook();
                  HSSFSheet sheet = wb.createSheet("new sheet");
                  HSSFHeader header = sheet.getHeader();
                  header.setCenter("Center Header");
                  HSSFRow row = sheet.createRow((short)0);
                  HSSFCell cell = row.createCell((short)0);
                  cell.setCellValue(1);
                  row.createCell((short)1).setCellValue(1.2123654);
                  row.createCell((short)2).setCellValue("This is a string");
                  row.createCell((short)3).setCellValue(true);
                  row = sheet.createRow((short)1);
                  cell = row.createCell((short)0);  
                  cell.setCellValue(new Date());                    
                  String str = new String("我是一個(gè)好人!!!");
                  row.createCell((short)1).setCellValue(str);
                  row.createCell((short)2).setCellValue("This我是一個(gè)好人string");
                 
                  FileOutputStream fileOut = new FileOutputStream("d:/filename.xls");
                  wb.write(fileOut);
                  fileOut.close();
          當(dāng)我打開(kāi)“d:/filename.xls”文件察看時(shí),里面的中文字符全部是亂碼!
          請(qǐng)問(wèn)如何解決?


          使用POI這樣處理中文
          HSSFCell cell = row.createCell((short)1);
          cell.setEncoding(HSSFCell.ENCODING_UTF_16);
          cell.setCellValue("中文");

          posted on 2007-10-26 09:37 lk 閱讀(10504) 評(píng)論(8)  編輯  收藏 所屬分類: j2se

          FeedBack:
          # re: java操作Excel(Jakarta_POI) 2007-11-16 15:59 撒旦飛
          怎么把單元格設(shè)為金錢的形式啊!如¥100
          設(shè)置100,在excel中自動(dòng)賦上¥100啊?  回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2007-11-19 09:39 lk
          朋友! 不要要求太多,jxl沒(méi)提供這么全面的方法,它只提供了數(shù)字(number)、標(biāo)簽(label)、日期(date)、布爾(boolean)幾種簡(jiǎn)單的類型。

          你可以在程序里自己寫一下嘛!

          excel還是蠻強(qiáng)大的我已經(jīng)試過(guò)了,在excel里,你不設(shè)置單元格格式,只要你輸入了貨幣符號(hào)excel就會(huì)自動(dòng)將該單元格設(shè)置成貨幣格式,在你需要的單元個(gè)里輸入值時(shí)用程序先加一個(gè)¥后面加錢數(shù)就OK了。

            回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2007-11-22 21:13 victim
          是好東西``我也一直在用,不過(guò)有一個(gè)問(wèn)題一直沒(méi)解決,不知道怎么設(shè)置打開(kāi)時(shí)默認(rèn)顯示指定工作表```  回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2007-11-22 21:16 victim
          啊```不好意思``以解決`

          hwb.setSelectedTab((short)hwb.getSheetIndex(sheetName));  回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2007-11-27 15:23 
          我使用的時(shí)候有個(gè)問(wèn)題,我導(dǎo)出來(lái)在excel數(shù)字是顯示文本,但我只要雙擊那一格,里面的文本數(shù)字就變?yōu)閿?shù)值類型。例如文本的“350702198116117551”
          雙擊后就變?yōu)?.50702E+17,焦點(diǎn)離開(kāi)后還是顯示3.50702E+17,而不是起先的350702198116117551 怎么在程序里設(shè)置完,雙擊不會(huì)變?yōu)閿?shù)值類型啊。
            回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2007-12-01 15:35 tobe
          最近想做個(gè)讀取excel內(nèi)容存入數(shù)據(jù)庫(kù)的程序,用poi文本格式的已經(jīng)實(shí)現(xiàn),但是那個(gè)excel里的圖片不知道怎樣才能讀出來(lái) ,請(qǐng)指教!  回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2008-10-21 15:56 ufo
          我的excel中需要有幾個(gè)下拉框供用戶來(lái)選擇項(xiàng)目,為什么保存時(shí)若焦點(diǎn)在下拉框上時(shí),上傳后就解析不出來(lái)呢,提示:
          org.apache.poi.hssf.record.RecordFormatException: Unable to construct record instance, the following exception occured: null
          at org.apache.poi.hssf.record.RecordFactory.createRecord(RecordFactory.java:90)
          at org.apache.poi.hssf.record.RecordFactory.createRecords(RecordFactory.java:45)
          at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:50)
          at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:81)
          at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:75)。
            回復(fù)  更多評(píng)論
            
          # re: java操作Excel(Jakarta_POI) 2012-10-16 12:36 
          我也遇到了這個(gè)問(wèn)題,該怎么解決呢@ufo
            回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 大英县| 墨脱县| 泉州市| 石阡县| 清水河县| 瑞金市| 大足县| 壤塘县| 呼图壁县| 松桃| 衡水市| 鸡东县| 青冈县| 安国市| 榆社县| 延边| 蒙自县| 政和县| 沛县| 札达县| 宁都县| 宣威市| 东宁县| 呈贡县| 尚义县| 松潘县| 乌什县| 黑龙江省| 焉耆| 新兴县| 五寨县| 农安县| 仪陇县| 得荣县| 兴义市| 田林县| 社旗县| 理塘县| 武夷山市| 兴和县| 焉耆|