黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

Java-Excel報(bào)表開(kāi)發(fā)POI

系統(tǒng) 2583 0

本篇面向?qū)ο鬄镴ava的初學(xué)者,從下載必備軟件到創(chuàng)建一個(gè)空白的POI工程,已經(jīng)熟練掌握環(huán)境搭建的請(qǐng)?zhí)^(guò)此文。

開(kāi)發(fā)環(huán)境為windowsXP-SP2,Eclipse3.2,JDK1.5.07,其實(shí)差不多都行,不會(huì)有太大的差異。本文從POI下載開(kāi)始講解,前提是開(kāi)發(fā)環(huán)境包括系統(tǒng)變量等等已經(jīng)正確設(shè)置完畢。

1.POI的下載

截至本文發(fā)表,POI最新版本是3.0.1,距離上一個(gè)Final版本有3年了吧,以至于我差點(diǎn)兒就把他放棄了——以為沒(méi)人管了。官方的公告講,這一版主要是追加了一些新的特性和BUG修正,不過(guò)稍微有點(diǎn)兒遺憾的是,還不能很好的操作Excel2007。

下載上面的JAR和源碼(源碼不是必須的,但是為了早日修得正果,深入系統(tǒng)的看看POI代碼還是有必要的)并解壓待用。

2.用Eclipse搭建項(xiàng)目

  • 打開(kāi)Eclipse
  • 依次點(diǎn)擊File->New->Java Project
  • 輸入項(xiàng)目名稱,本例中設(shè)置為POI
  • 單擊完成
  • 在項(xiàng)目上點(diǎn)擊右鍵->New->Folder
  • 輸入文件夾名稱lib
  • 把剛才解壓的poi-3.0.1-FINAL-20070705.jar復(fù)制過(guò)來(lái)
  • 右鍵點(diǎn)擊項(xiàng)目,選擇Properties
  • 在左側(cè)列表里選中Java Build Path,右側(cè)選中Libraries
  • 點(diǎn)擊Add JARs,選擇POI項(xiàng)目的lib下的所有文件
  • 兩次OK確認(rèn),回到Eclipse界面

小技巧,快捷操作:可以用鼠標(biāo)左鍵選中poi-3.0.1-FINAL-20070705.jar但不松開(kāi),拖到任務(wù)欄的Eclipse圖標(biāo)上等候1秒左右,Eclipse會(huì)自動(dòng)彈起來(lái),依然不松開(kāi)移動(dòng)到lib文件夾上,這個(gè)時(shí)候鼠標(biāo)后面跟個(gè)十字符號(hào),松開(kāi)左鍵,就完成了復(fù)制動(dòng)作。這個(gè)是對(duì)整個(gè)windows系統(tǒng)都好用的快捷復(fù)制方式,視源盤符和目標(biāo)盤符的不同偶爾會(huì)用到Ctrl鍵。

到此為止,我們做好了POI學(xué)習(xí)的前提準(zhǔn)備,接下來(lái)將從最簡(jiǎn)單的文檔創(chuàng)建開(kāi)始一步一步學(xué)習(xí)怎樣讓POI更好的為我們工作。

第一講:基本的Excel讀寫

本文主要演示一下POI的基本操作,例如怎樣讀取和創(chuàng)建一個(gè)具體的Excel文件。按照慣例,拿HelloWorld說(shuō)事兒。

說(shuō)明:本文主要內(nèi)容皆包含于 官方幫助手冊(cè) ,之所以要拿出來(lái),出于兩個(gè)原因,手冊(cè)是英文的+手冊(cè)是對(duì)應(yīng)2.5.1的。

核心代碼如下,注釋部分為講解。這里只挑干的講,完整的代碼請(qǐng)參考 (下載代碼)

//創(chuàng)建一個(gè)空白的WorkBook

HSSFWorkbook wb = new HSSFWorkbook();

//基于上面的WorkBook創(chuàng)建屬于此WorkBook的Sheet,

//3.0.1版在使用全角Sheet名的時(shí)候不必再setEncdoing了,個(gè)人感覺(jué)方便了許多。

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

//創(chuàng)建屬于上面Sheet的Row,參數(shù)0可以是0~65535之間的任何一個(gè),

//注意,盡管參數(shù)是Int類型,但是Excel最多支持65536行

HSSFRow row = st.createRow(0);

//創(chuàng)建屬于上面Row的Cell,參數(shù)0可以是0~255之間的任何一個(gè),

//同樣,是因?yàn)镋xcel最大支持的列數(shù)為256列

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

//設(shè)置此單元格的格式為文本,此句可以省略,Excel會(huì)自動(dòng)識(shí)別。

//其他還有幾種常用的格式,請(qǐng)參考本文底部的補(bǔ)充部分。

cell.setCellType(HSSFCell.CELL_TYPE_STRING);

//此處是3.0.1版的改進(jìn)之處,上一版可以直接setCellValue("Hello, World!"),

//但是在3.0.1里,被deprecated了。

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

//創(chuàng)建一個(gè)文件輸出流,指定到C盤根目錄下(C盤都有吧?)

//xls是Excel97-2003的標(biāo)準(zhǔn)擴(kuò)展名,2007是xlsx,目前的POI能直接生產(chǎn)的還是xls格式,

//如果此處把擴(kuò)展名改成xlsx,在用Excel2007打開(kāi)此文件時(shí)會(huì)報(bào)錯(cuò)。

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

//把WorkBook寫到流里

wb.write(writeFile);

//記得手動(dòng)關(guān)閉流,官方文檔已經(jīng)做了特別說(shuō)明,說(shuō)POI不負(fù)責(zé)關(guān)閉用戶打開(kāi)的流。所以...

writeFile.close();

上面就是創(chuàng)建一個(gè)新文檔的簡(jiǎn)易代碼,下面的例子是讀取剛才創(chuàng)建的Excel并把讀取到的內(nèi)容顯示在控制臺(tái)上。

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

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

//創(chuàng)建一個(gè)WorkBook,從指定的文件流中創(chuàng)建,即上面指定了的文件流

HSSFWorkbook wb = new HSSFWorkbook(readFile);

//獲取名稱為“測(cè)試頁(yè)”的sheet

//注意,如果不能確定具體的名稱,可以用getSheetAt(int)方法取得Sheet

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

//獲得第一行,同上,如果此行沒(méi)有被創(chuàng)建過(guò)則拋出異常

HSSFRow row = st.getRow(0);

//獲取第一個(gè)單元格,如果沒(méi)有被創(chuàng)建過(guò)則拋出異常

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

//把cell中的內(nèi)容按字符串方式讀取出來(lái),并顯示在控制臺(tái)上

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

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

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

//記得關(guān)閉流

readFile.close();

上面對(duì)創(chuàng)建和讀取分別舉例說(shuō)明,回顧兩段代碼,不難看出POI操作Excel的“套路”:

  • 獲得一個(gè)WorkBook(準(zhǔn)確說(shuō)是HSSFWorkBook,對(duì)于POI來(lái)說(shuō),WorkBook是“另有其類”,以下類同)
  • 獲得要讀/寫的Sheet對(duì)象
  • 獲得要操作的Row對(duì)象
  • 獲得最小單位——Cell對(duì)象

然后就可以隨意的讀取、寫入了。


關(guān)于單元格格式的補(bǔ)充:

    單元格一共有如下幾種格式, 都是HSSFCell類的靜態(tài)共有屬性,

  • CELL_TYPE_NUMERIC - 數(shù)字格式
  • CELL_TYPE_STRING - 字符串(默認(rèn))
  • CELL_TYPE_FORMULA - 公式
  • CELL_TYPE_BLANK - 空白
  • CELL_TYPE_BOOLEAN - 布爾
  • CELL_TYPE_ERROR - 錯(cuò)誤

第二講:?jiǎn)卧襁吙颉⒆煮w及顏色

此文概要性的講述了一下單元格的邊框、字體以及顏色的設(shè)置方式,在POI中,這一切都是通過(guò)實(shí)例化HSSFCellStyle對(duì)象來(lái)實(shí)現(xiàn)的,HSSFCellStyle類還有很多其他實(shí)際有用方法,本例中只是取平時(shí)用的比較普遍的一些設(shè)置來(lái)做演示的。好,開(kāi)始講解了……

// 設(shè)置行號(hào)

row.setHeightInPoints((short) 50);

// 設(shè)置列寬,(256 * 50)這種寫法是因?yàn)閣idth參數(shù)單位是單個(gè)字符的256分之一

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

// 讓HSSFWorkbook創(chuàng)建一個(gè)單元格樣式的對(duì)象

// 小技巧:在多處用到完全一樣的樣式的時(shí)候可以用工廠模式生產(chǎn)

HSSFCellStyle cellStyle = wb.createCellStyle();

// 設(shè)置單元格的橫向和縱向?qū)R方式,具體參數(shù)就不列了,參考HSSFCellStyle

cellStyle.setAlignment(HSSFCellStyle.ALIGN_JUSTIFY);

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

// 這個(gè)地方是用來(lái)在單元格里畫斜線的

// 原理是在指定的兩個(gè)點(diǎn)之間畫線,然后默認(rèn)情況此線會(huì)隨著單元格的變化而變化

// 類似Excel那種設(shè)置邊框的方式達(dá)到的斜線效果目前好像POI不支持

// 如果是我疏忽了請(qǐng)記得告訴我一些,先行謝過(guò)啦

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);

// 設(shè)置單元格的文本方式為可多行編寫方式

cellStyle.setWrapText(true);

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

// 三點(diǎn)注意:

// 1.如果需要前景顏色或背景顏色,一定要指定填充方式,兩者順序無(wú)所謂;

// 2.如果同時(shí)存在前景顏色和背景顏色,前景顏色的設(shè)置要寫在前面;

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

cellStyle.setFillPattern(HSSFCellStyle.DIAMONDS);

cellStyle.setFillForegroundColor(HSSFColor.RED.index);

cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_YELLOW.index);

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

// 這里僅設(shè)置了底邊邊框,左邊框、右邊框和頂邊框同理可設(shè)

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_SLANTED_DASH_DOT);

cellStyle.setBottomBorderColor(HSSFColor.DARK_RED.index);

// 創(chuàng)建一個(gè)字體對(duì)象,因?yàn)樽煮w也是單元格格式的一部分,所以從屬于HSSFCellStyle

// 下面幾個(gè)字體的相關(guān)設(shè)置望文生義,就不用一一說(shuō)明了吧

HSSFFont font = wb.createFont();

font.setFontName("宋體");

font.setItalic(true);

font.setColor(HSSFColor.BLUE.index);

font.setFontHeightInPoints((short) 20);

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

// 將字體對(duì)象賦值給單元格樣式對(duì)象

cellStyle.setFont(font);

// 將單元格樣式對(duì)應(yīng)應(yīng)用于單元格

cell.setCellStyle(cellStyle);

這樣就OK了,可以可以看到效果了。

補(bǔ)充,各個(gè)章節(jié)的例子最終都在同一個(gè)附件內(nèi),下載的時(shí)候下任何一個(gè)頁(yè)面內(nèi)的都可以,都是一樣的。

Java-Excel報(bào)表開(kāi)發(fā)POI—合并、分組及凍結(jié)

Java-Excel報(bào)表開(kāi)發(fā)POI系列講座

第三講:?jiǎn)卧竦暮喜ⅰ?shù)據(jù)行的分組以及Excel窗口的凍結(jié)

本來(lái)想把這三個(gè)東西分開(kāi)來(lái)實(shí)現(xiàn)的,后來(lái)發(fā)現(xiàn)分開(kāi)后內(nèi)容都很少,于是就合在一起說(shuō)吧。那總不能干巴巴的列幾個(gè)例子就完了吧,那就拿比較初級(jí)但又會(huì)經(jīng)常遇到的表格類數(shù)據(jù)的統(tǒng)計(jì)的設(shè)計(jì)來(lái)做個(gè)小例子。 (源碼下載)

結(jié)果發(fā)現(xiàn)——還真夠辛苦的。

這次先看效果圖吧,其中的豎排并不是真正意義上Excel那種設(shè)置的豎排,而是稍微轉(zhuǎn)變了一下輸出的方式實(shí)現(xiàn)的,因?yàn)槔贤獾挠⑽膯卧~沒(méi)有這種豎排的可能(頂多是旋轉(zhuǎn),但是那樣字體就變了)。除此之外想到的另外一種豎排文字的實(shí)現(xiàn)方式就是樣式旋轉(zhuǎn)+字體旋轉(zhuǎn),沒(méi)測(cè)試,不知道是否可用,誰(shuí)有功夫?qū)崿F(xiàn)一下,然后記得告訴我結(jié)果啊。

老樣子,把核心的代碼和簡(jiǎn)要的說(shuō)明列出來(lái)大家看一下吧。

// 這里首先創(chuàng)建一個(gè)單元格樣式對(duì)象,設(shè)置了四周的邊框以及字體可以換行

// 其中的字體換行是用來(lái)豎向顯示其中的一個(gè)單元格的

// 更好的一點(diǎn)兒做法是再做一個(gè)單獨(dú)的單元格樣式對(duì)象

// 要不然在處理自動(dòng)列寬的時(shí)候可能會(huì)有點(diǎn)兒小問(wèn)題

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,填入內(nèi)容的時(shí)候添到第一個(gè)格子里就可以

// 但是注意一點(diǎn):?jiǎn)卧窈喜⑨嵩O(shè)置邊框只在原第一個(gè)上有效,

// 如果想應(yīng)用的合并後的整體,則需要一個(gè)個(gè)的Create出單元格并應(yīng)用樣式

// 這個(gè)明顯是一個(gè)不太方便的操作,期待POI下一版的改進(jìn)了

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("業(yè)務(wù)一覽表"));

cell.setCellStyle(normalStyle);

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

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

// 設(shè)置列頭,當(dāng)然也可以一個(gè)一個(gè)格子的寫,用循環(huán)感覺(jué)有些取巧而已

// 同樣,需要單獨(dú)給每個(gè)單元格應(yīng)用樣式對(duì)象

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

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

{

cell = row.createCell(i);

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

cell.setCellStyle(normalStyle);

}

// 這個(gè)是豎排文字的實(shí)現(xiàn)

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

// HSSFCellStyle.setRotation()方法是設(shè)置旋轉(zhuǎn)角度的,和豎排不太一樣,

// 后來(lái)想了一下,因?yàn)橹挥兄形牡热亲址庞胸Q排的可能,

// 一個(gè)英文單詞要是豎排看起來(lái)恐怕會(huì)非常怪異,不過(guò)不排除搞藝術(shù)的……

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

row = st.createRow(1);

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

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

cell.setCellStyle(normalStyle);

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

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

// 屬于地區(qū)的二級(jí)分類,豎向合并相鄰的兩個(gè)單元格,其他同上

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));

}

// 屬于連鎖店的下一級(jí),基本也是創(chuàng)建出來(lái)然后賦值+應(yīng)用樣式

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);

}

// 數(shù)據(jù)部分,直接Create然后應(yīng)用樣式,有數(shù)據(jù)的話這個(gè)地方就打數(shù)據(jù)好了

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

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

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

// 凍結(jié)Excel的窗口,邊界為數(shù)據(jù)部分的邊界

st.createFreezePane(3, 1);

// 按照連鎖店級(jí)別分組(當(dāng)然實(shí)際情況這樣分組沒(méi)啥意義)

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

st.groupRow(i, i);

// 按照地區(qū)分組

st.groupRow(1, 5);

其實(shí)這樣實(shí)現(xiàn)起來(lái)是不是很麻煩呢?答案是:是。

其實(shí)這只是舉個(gè)例子,熟悉一下POI的各種API而已,真正要實(shí)現(xiàn)這樣一個(gè)表格的時(shí)候,例如項(xiàng)目需要制作報(bào)表等等,通常的做法都是事先把格式一切的東西都手動(dòng)制作好(這個(gè)做好了的文件在實(shí)際的項(xiàng)目里我們稱之為“數(shù)據(jù)模板”,簡(jiǎn)稱“模板”),然后在Java應(yīng)用中適當(dāng)?shù)臅r(shí)機(jī)把這個(gè)文件讀進(jìn)來(lái)修改,最后再另存到指定的位置或者傳遞給下一個(gè)處理者(例如以流的方式送給Servlet等等),這樣其實(shí)POI具體做的事情就是向模板里寫業(yè)務(wù)的數(shù)據(jù),還是很方便快捷的。

Java-Excel報(bào)表開(kāi)發(fā)POI


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論