Java-Excel 報表開發 POI

轉自:http://blog.sina.com.cn/s/blog_5e0d59fb0100bx5s.htmlphp

 開發環境爲windowsXP-SP2,Eclipse3.2,JDK1.5.07,其實差很少都行,不會有太大的差別。本文從POI下載開始講解,前提是開發環境包括系統變量等等已經正確設置完畢。html

 

1.POI的下載apache

 截至本文發表,POI最新版本是3.0.1,距離上一個Final版本有3年了吧,以致於我差點兒就把他放棄了——覺得沒人管了。官方的公告講,這一版主要是追加了一些新的特性和BUG修正,不過稍微有點兒遺憾的是,還不能很好的操做Excel2007。windows

POI官方網址:ide


http://poi.apache.org/
JAR包下載:學習


http://apache.mirror.phpchina.com/poi/release/bin/poi-bin-3.0.1-FINAL-20070705.zip
×××:測試


http://apache.mirror.phpchina.com/poi/release/src/poi-src-3.0.1-FINAL-20070705.zip字體

下載上面的JAR和源碼(源碼不是必須的,可是爲了早日修得正果,深刻系統的看看POI代碼仍是有必要的)並解壓待用。ui

2.用Eclipse搭建項目設計


  打開Eclipse
 依次點擊File->New->Java Project
 輸入項目名稱,本例中設置爲POI
 單擊完成
 在項目上點擊右鍵->New->Folder
 輸入文件夾名稱lib
 把剛纔解壓的poi-3.0.1-FINAL-20070705.jar複製過來
 右鍵點擊項目,選擇Properties
 在左側列表裏選中Java Build Path,右側選中Libraries
 點擊Add JARs,選擇POI項目的lib下的全部文件
 兩次OK確認,回到Eclipse界面

 小技巧,快捷操做:能夠用鼠標左鍵選中poi-3.0.1-FINAL-20070705.jar但不鬆開,拖到任務欄的Eclipse圖標上等候1秒左右,Eclipse會自動彈起來,依然不鬆開移動到lib文件夾上,這個時候鼠標後面跟個十字符號,鬆開左鍵,就完成了複製動做。這個是對整個windows系統都好用的快捷複製方式,視源盤符和目標盤符的不一樣偶爾會用到Ctrl鍵。


 到此爲止,咱們作好了POI學習的前提準備,接下來將從最簡單的文檔建立開始一步一步學習怎樣讓POI更好的爲咱們工做。

 

第一講:基本的Excel讀寫

 本文主要演示一下POI的基本操做,例如怎樣讀取和建立一個具體的Excel文件。按照慣例,拿HelloWorld說事兒。

 說明:本文主要內容皆包含於官方幫助手冊,之因此要拿出來,出於兩個緣由,手冊是英文的+手冊是對應2.5.1的。

 核心代碼以下,註釋部分爲講解。這裏只挑乾的講,完整的代碼請參考(下載代碼)。


//建立一個空白的WorkBook

HSSFWorkbook wb = new HSSFWorkbook();

//基於上面的WorkBook建立屬於此WorkBook的Sheet,

//3.0.1版在使用全角Sheet名的時候沒必要再setEncdoing了,我的感受方便了許多。

HSSFSheet st = wb.createSheet("測試頁");

//建立屬於上面Sheet的Row,參數0能夠是0~65535之間的任何一個,

//注意,儘管參數是Int類型,可是Excel最多支持65536行

HSSFRow row = st.createRow(0);

//建立屬於上面Row的Cell,參數0能夠是0~255之間的任何一個,

//一樣,是由於Excel最大支持的列數爲256列

HSSFCell cell = row.createCell((short) 0);

//設置此單元格的格式爲文本,此句能夠省略,Excel會自動識別。

//其餘還有幾種經常使用的格式,請參考本文底部的補充部分。

cell.setCellType(HSSFCell.CELL_TYPE_STRING);

//此處是3.0.1版的改進之處,上一版能夠直接setCellValue("Hello, World!"),

//可是在3.0.1裏,被deprecated了。

cell.setCellValue(new HSSFRichTextString("Hello, World!"));

//建立一個文件輸出流,指定到C盤根目錄下(C盤都有吧?)

//xls是Excel97-2003的標準擴展名,2007是xlsx,目前的POI能直接生產的仍是xls格式,

//若是此處把擴展名改爲xlsx,在用Excel2007打開此文件時會報錯。

FileOutputStream writeFile = new FileOutputStream("c:/helloworld.xls");

//把WorkBook寫到流裏

wb.write(writeFile);

//記得手動關閉流,官方文檔已經作了特別說明,說POI不負責關閉用戶打開的流。因此...

writeFile.close();


上面就是建立一個新文檔的簡易代碼,下面的例子是讀取剛纔建立的Excel並把讀取到的內容顯示在控制檯上。


//指定要讀取的文件,本例使用上面生成的helloworld.xls

FileInputStream readFile = new FileInputStream("c:/helloworld.xls");

//建立一個WorkBook,從指定的文件流中建立,即上面指定了的文件流

HSSFWorkbook wb = new HSSFWorkbook(readFile);

//獲取名稱爲「測試頁」的sheet

//注意,若是不能肯定具體的名稱,能夠用getSheetAt(int)方法取得Sheet

HSSFSheet st = wb.getSheet("測試頁");

//得到第一行,同上,若是此行沒有被建立過則拋出異常

HSSFRow row = st.getRow(0);

//獲取第一個單元格,若是沒有被建立過則拋出異常

HSSFCell cell = row.getCell((short) 0);

//把cell中的內容按字符串方式讀取出來,並顯示在控制檯上

//注意,getRichStringCellValue()方法是3.0.1新追加的,

//老版本中的getStringCellValue()方法被deprecated了

System.out.println(cell.getRichStringCellValue());

//記得關閉流

readFile.close();


上面對建立和讀取分別舉例說明,回顧兩段代碼,不難看出POI操做Excel的「套路」:

得到一個WorkBook(準確說是HSSFWorkBook,對於POI來講,WorkBook是「另有其類」,如下類同)
得到要讀/寫的Sheet對象
得到要操做的Row對象
得到最小單位——Cell對象

而後就能夠隨意的讀取、寫入了。

 

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

 


關於單元格格式的補充:


單元格一共有以下幾種格式,都是HSSFCell類的靜態共有屬性,


CELL_TYPE_NUMERIC - 數字格式
CELL_TYPE_STRING - 字符串(默認)
CELL_TYPE_FORMULA - 公式
CELL_TYPE_BLANK - 空白
CELL_TYPE_BOOLEAN - 布爾
CELL_TYPE_ERROR - 錯誤


第二講:單元格邊框、字體及顏色

此文概要性的講述了一下單元格的邊框、字體以及顏色的設置方式,在POI中,這一切都是經過實例化HSSFCellStyle對象來實現的,HSSFCellStyle類還有不少其餘實際有用方法,本例中只是取平時用的比較廣泛的一些設置來作演示的。好,開始講解了……


// 設置行號

row.setHeightInPoints((short) 50);

// 設置列寬,(256 * 50)這種寫法是由於width參數單位是單個字符的256分之一

st.setColumnWidth(cell.getCellNum(), (short) (256 * 50));

// 讓HSSFWorkbook建立一個單元格樣式的對象

// 小技巧:在多處用到徹底同樣的樣式的時候能夠用工廠模式生產

HSSFCellStyle cellStyle = wb.createCellStyle();

// 設置單元格的橫向和縱向對齊方式,具體參數就不列了,參考HSSFCellStyle

cellStyle.setAlignment(HSSFCellStyle.ALIGN_JUSTIFY);

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

// 這個地方是用來在單元格里畫斜線的

// 原理是在指定的兩個點之間畫線,而後默認狀況此線會隨着單元格的變化而變化

// 相似Excel那種設置邊框的方式達到的斜線效果目前好像POI不支持

// 若是是我疏忽了請記得告訴我一些,先行謝過啦

HSSFPatriarch patriarch = st.createDrawingPatriarch();

HSSFClientAnchor anchor = new HSSFClientAnchor();

anchor.setAnchor(cell.getCellNum(), row.getRowNum(), 0, 0, (short) (cell.getCellNum() + 1),

row.getRowNum() + 1, 0, 0);

patriarch.createSimpleShape(anchor);

// 設置單元格的文本方式爲可多行編寫方式

cellStyle.setWrapText(true);

// 設置單元格的填充方式,以及前景顏色和背景顏色

// 三點注意:

// 1.若是須要前景顏色或背景顏色,必定要指定填充方式,二者順序無所謂;

// 2.若是同時存在前景顏色和背景顏色,前景顏色的設置要寫在前面;

// 3.前景顏色不是字體顏色。

cellStyle.setFillPattern(HSSFCellStyle.DIAMONDS);

cellStyle.setFillForegroundColor(HSSFColor.RED.index);

cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_YELLOW.index);

// 設置單元格底部的邊框及其樣式和顏色

// 這裏僅設置了底邊邊框,左邊框、右邊框和頂邊框同理可設

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_SLANTED_DASH_DOT);

cellStyle.setBottomBorderColor(HSSFColor.DARK_RED.index);

// 建立一個字體對象,由於字體也是單元格格式的一部分,因此從屬於HSSFCellStyle

// 下面幾個字體的相關設置望文生義,就不用一一說明了吧

HSSFFont font = wb.createFont();

font.setFontName("宋體");

font.setItalic(true);

font.setColor(HSSFColor.BLUE.index);

font.setFontHeightInPoints((short) 20);

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

// 將字體對象賦值給單元格樣式對象

cellStyle.setFont(font);

// 將單元格樣式對應應用於單元格

cell.setCellStyle(cellStyle);


這樣就OK了,能夠能夠看到效果了。

 

補充,各個章節的例子最終都在同一個附件內,下載的時候下任何一個頁面內的均可以,都是同樣的。

 

 

 

Java-Excel報表開發POI—合併、分組及凍結

Java-Excel報表開發POI系列講座

 

第三講:單元格的合併、數據行的分組以及Excel窗口的凍結

原本想把這三個東西分開來實現的,後來發現分開後內容都不多,因而就合在一塊兒說吧。那總不能乾巴巴的列幾個例子就完了吧,那就拿比較初級但又會常常遇到的表格類數據的統計的設計來作個小例子。(×××)

結果發現——還真夠辛苦的。

此次先看效果圖吧,其中的豎排並非真正意義上Excel那種設置的豎排,而是稍微轉變了一下輸出的方式實現的,由於老外的英文單詞沒有這種豎排的可能(頂可能是旋轉,可是那樣字體就變了)。除此以外想到的另一種豎排文字的實現方式就是樣式旋轉+字體旋轉,沒測試,不知道是否可用,誰有功夫實現一下,而後記得告訴我結果啊。

 

老樣子,把核心的代碼和簡要的說明列出來你們看一下吧。


// 這裏首先建立一個單元格樣式對象,設置了四周的邊框以及字體能夠換行

  // 其中的字體換行是用來豎向顯示其中的一個單元格的

  // 更好的一點兒作法是再作一個單獨的單元格樣式對象

  // 要否則在處理自動列寬的時候可能會有點兒小問題

  HSSFCellStyle normalStyle = wb.createCellStyle();

  normalStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);

  normalStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);

  normalStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);

  normalStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);

  normalStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

  normalStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

  normalStyle.setWrapText(true);

  // 合併單元格A1-C1,填入內容的時候添到第一個格子裏就能夠

  // 可是注意一點:單元格合併後設置邊框只在原第一個上有效,

  // 若是想應用的合併後的總體,則須要一個個的Create出單元格並應用樣式

  // 這個明顯是一個不太方便的操做,期待POI下一版的改進了

  st.addMergedRegion(new Region(0, (short) 0, 0, (short) 2));

  HSSFRow row = st.createRow(0);

  HSSFCell cell = row.createCell((short) 0);

  cell.setCellValue(new HSSFRichTextString("業務一覽表"));

  cell.setCellStyle(normalStyle);

  row.createCell((short) 1).setCellStyle(normalStyle);

  row.createCell((short) 2).setCellStyle(normalStyle);

  // 設置列頭,固然也能夠一個一個格子的寫,用循環感受有些取巧而已

  // 一樣,須要單獨給每一個單元格應用樣式對象

  String[] seasonName = { "第一季度", "第二季度", "第三季度", "第四季度" };

  for (short i = 3; i < 7; i++)

  {

  cell = row.createCell(i);

  cell.setCellValue(new HSSFRichTextString(seasonName[i - 3]));

  cell.setCellStyle(normalStyle);

  }

  // 這個是豎排文字的實現

  // 目前POI沒找到(或許沒提供,或許我無知)讓文字豎排的方法,

  // HSSFCellStyle.setRotation()方法是設置旋轉角度的,和豎排不太同樣,

  // 後來想了一下,由於只有中文等全角字符纔有豎排的可能,

  // 一個英文單詞要是豎排看起來恐怕會很是怪異,不過不排除搞藝術的……

  st.addMergedRegion(new Region(1, (short) 0, 6, (short) 0));

  row = st.createRow(1);

  cell = row.createCell((short) 0);

  cell.setCellValue(new HSSFRichTextString("地\n區\n代\n理\nA"));

  cell.setCellStyle(normalStyle);

  for (int i = 2; i < 7; i++)

  st.createRow(i).createCell((short) 0).setCellStyle(normalStyle);

  // 屬於地區的二級分類,豎向合併相鄰的兩個單元格,其餘同上

  String[] shopName = { "連鎖店A", "連鎖店B", "連鎖店C" };

  for (int i = 1; i < 6; i = i + 2)

  {

  row = st.createRow(i);

  cell = row.createCell((short) 1);

  cell.setCellValue(new HSSFRichTextString(shopName[(i - 1) / 2]));

  cell.setCellStyle(normalStyle);

  st.createRow(i + 1).createCell((short) 1).setCellStyle(normalStyle);

  st.addMergedRegion(new Region(i, (short) 1, i + 1, (short) 1));

  }

  // 屬於連鎖店的下一級,基本也是建立出來而後賦值+應用樣式

  for (int i = 1; i < 7; i = i + 2)

  {

  cell = st.getRow(i).createCell((short) 2);

  cell.setCellValue(new HSSFRichTextString("收入"));

  cell.setCellStyle(normalStyle);

  cell = st.getRow(i + 1).createCell((short) 2);

  cell.setCellValue(new HSSFRichTextString("支出"));

  cell.setCellStyle(normalStyle);

  }

  // 數據部分,直接Create而後應用樣式,有數據的話這個地方就打數據好了

  for (int i = 1; i < 7; i++)

  for (short j = 3; j < 7; j++)

  st.createRow(i).createCell(j).setCellStyle(normalStyle);

  // 凍結Excel的窗口,邊界爲數據部分的邊界

  st.createFreezePane(3, 1);

  // 按照連鎖店級別分組(固然實際狀況這樣分組沒啥意義)

  for (int i = 1; i < 7; i = i + 2)

  st.groupRow(i, i);

  // 按照地區分組

  st.groupRow(1, 5);


其實這樣實現起來是否是很麻煩呢?答案是:是。

其實這只是舉個例子,熟悉一下POI的各類API而已,真正要實現這樣一個表格的時候,例如項目須要製做報表等等,一般的作法都是事先把格式一切的東西都手動製做好(這個作好了的文件在實際的項目裏咱們稱之爲「數據模板」,簡稱「模板」),而後在Java應用中適當的時機把這個文件讀進來修改,最後再另存到指定的位置或者傳遞給下一個處理者(例如以流的方式送給Servlet等等),這樣其實POI具體作的事情就是向模板裏寫業務的數據,仍是很方便快捷的。

相關文章
相關標籤/搜索