java poi 讀取excel各種數(shù)據(jù)
Microsoft的Office系列產(chǎn)品擁有大 量的用戶,Word、Excel也成為辦公文件的首選。在Java中,已經(jīng)有很多對(duì)于Word、Excel的開源的解決方案,其中比較出色的是 Apache的Jakata項(xiàng)目的POI子項(xiàng)目。該項(xiàng)目的官方網(wǎng)站是http://jakarta.apache.org/poi/。
POI 包括一系列的API,它們可以操作基于MicroSoft OLE 2 Compound Document Format的各種格式文件,可以通過這些API在Java中讀寫Excel、Word等文件。POI是完全的Java Excel和Java Word解決方案。POI子項(xiàng)目包括:POIFS、HSSF、HDF、HPSF。表7-2對(duì)它們進(jìn)行了簡要介紹。
表7-2 POI子項(xiàng)目介紹
子項(xiàng)目名
|
說明
|
POIFS(POI File System)
|
POIFS是POI項(xiàng)目中最早的最基礎(chǔ)的一個(gè)模塊,是Java到OLE 2 Compound Document Format的接口,支持讀寫功能,所有的其他項(xiàng)目都依賴與該項(xiàng)目。
|
HSSF(Horrible Spreadsheet Format)
|
HSSF是Java到Microsoft Excel 97(-2002)文件的接口,支持讀寫功能
|
HWPF(Horrible Word Processing Format)
|
HWPF是Java到Microsoft Word 97文件的接口,支持讀寫功能,但目前該模塊還處于剛開始開發(fā)階段,只能實(shí)現(xiàn)一些簡單文件的操作,在后續(xù)版本中,會(huì)提供更強(qiáng)大的支持
|
HPSF(Horrible Property Set Format)
|
HPSF 是Java到OLE 2 Compound Document Format文件的屬性設(shè)置的接口,屬性設(shè)置通常用來設(shè)置文檔的屬性(標(biāo)題,作者,最后修改日期等),還可以設(shè)置用戶定義的屬性。HPSF支持讀寫功能,當(dāng)前發(fā)布版本中直支持讀功能。
|
7.3.1 對(duì)Excel的處理類
下 面通過HSSF提供的接口對(duì)Excel文件經(jīng)行處理。首先需要下載POI的包,可以到apache的官方網(wǎng)站下載,地址為:http: //apache.justdn.org/jakarta/poi/,本書采用的是poi-2.5.1-final-20040804.jar,讀者可以 下載當(dāng)前的穩(wěn)定版本。把下載的包按照前面介紹的方式加入Build Path,然后新建一個(gè)ch7.poi包,并創(chuàng)建一個(gè)ExcelReader類。
ExcelReader類可以讀取一個(gè)XLS文件,然后將其內(nèi)容逐行提取出來,寫入文本文件。其代碼如下。
7.3.2 ExcelReader的運(yùn)行效果
java 代碼
- public class ExcelReader{
- // 創(chuàng)建文件輸入流
- private BufferedReader reader = null;
- // 文件類型
- private String filetype;
- // 文件二進(jìn)制輸入流
- private InputStream is = null;
- // 當(dāng)前的Sheet
- private int currSheet;
- // 當(dāng)前位置
- private int currPosition;
- // Sheet數(shù)量
- private int numOfSheets;
- // HSSFWorkbook
- HSSFWorkbook workbook = null;
- // 設(shè)置Cell之間以空格分割
- private static String EXCEL_LINE_DELIMITER = " ";
- // 設(shè)置最大列數(shù)
- private static int MAX_EXCEL_COLUMNS = 64;
- // 構(gòu)造函數(shù)創(chuàng)建一個(gè)ExcelReader
- public ExcelReader(String inputfile) throws IOException, Exception{
- // 判斷參數(shù)是否為空或沒有意義
- if (inputfile == null || inputfile.trim().equals("")){
- throw new IOException("no input file specified");
- }
- // 取得文件名的后綴名賦值給filetype
- this.filetype = inputfile.substring(inputfile.lastIndexOf(".") + 1);
- // 設(shè)置開始行為0
- currPosition = 0;
- // 設(shè)置當(dāng)前位置為0
- currSheet = 0;
- // 創(chuàng)建文件輸入流
- is = new FileInputStream(inputfile);
- // 判斷文件格式
- if (filetype.equalsIgnoreCase("txt")){
- // 如果是txt則直接創(chuàng)建BufferedReader讀取
- reader = new BufferedReader(new InputStreamReader(is));
- }
- else if (filetype.equalsIgnoreCase("xls")){
- // 如果是Excel文件則創(chuàng)建HSSFWorkbook讀取
- workbook = new HSSFWorkbook(is);
- // 設(shè)置Sheet數(shù)
- numOfSheets = workbook.getNumberOfSheets();
- }
- else{
- throw new Exception("File Type Not Supported");
- }
- }
- // 函數(shù)readLine讀取文件的一行
- public String readLine() throws IOException{
- // 如果是txt文件則通過reader讀取
- if (filetype.equalsIgnoreCase("txt")){
- String str = reader.readLine();
- // 空行則略去,直接讀取下一行
- while (str.trim().equals("")){
- str = reader.readLine();
- }
- return str;
- }
- // 如果是XLS文件則通過POI提供的API讀取文件
- else if (filetype.equalsIgnoreCase("xls")){
- // 根據(jù)currSheet值獲得當(dāng)前的sheet
- HSSFSheet sheet = workbook.getSheetAt(currSheet);
- // 判斷當(dāng)前行是否到但前Sheet的結(jié)尾
- if (currPosition > sheet.getLastRowNum()){
- // 當(dāng)前行位置清零
- currPosition = 0;
- // 判斷是否還有Sheet
- while (currSheet != numOfSheets - 1){
- // 得到下一張Sheet
- sheet = workbook.getSheetAt(currSheet + 1);
- // 當(dāng)前行數(shù)是否已經(jīng)到達(dá)文件末尾
- if (currPosition == sheet.getLastRowNum()){
- // 當(dāng)前Sheet指向下一張Sheet
- currSheet++;
- continue;
- } else{
- // 獲取當(dāng)前行數(shù)
- int row = currPosition;
- currPosition++;
- // 讀取當(dāng)前行數(shù)據(jù)
- return getLine(sheet, row);
- }
- }
- return null;
- }
- // 獲取當(dāng)前行數(shù)
- int row = currPosition;
- currPosition++;
- // 讀取當(dāng)前行數(shù)據(jù)
- return getLine(sheet, row);
- }
- return null;
- }
- // 函數(shù)getLine返回Sheet的一行數(shù)據(jù)
- private String getLine(HSSFSheet sheet, int row){
- // 根據(jù)行數(shù)取得Sheet的一行
- HSSFRow rowline = sheet.getRow(row);
- // 創(chuàng)建字符創(chuàng)緩沖區(qū)
- StringBuffer buffer = new StringBuffer();
- // 獲取當(dāng)前行的列數(shù)
- int filledColumns = rowline.getLastCellNum();
- HSSFCell cell = null;
- // 循環(huán)遍歷所有列
- for (int i = 0; i < filledColumns; i++){
- // 取得當(dāng)前Cell
- cell = rowline.getCell((short) i);
- String cellvalue = null;
- if (cell != null){
- // 判斷當(dāng)前Cell的Type
- switch (cell.getCellType()){
- // 如果當(dāng)前Cell的Type為NUMERIC
- case HSSFCell.CELL_TYPE_NUMERIC:{
- // 判斷當(dāng)前的cell是否為Date
- if (HSSFDateUtil.isCellDateFormatted(cell)){
- // 如果是Date類型則,取得該Cell的Date值
- Date date = cell.getDateCellValue();
- // 把Date轉(zhuǎn)換成本地格式的字符串
- cellvalue = cell.getDateCellValue().toLocaleString();
- }
- // 如果是純數(shù)字
- else{
- // 取得當(dāng)前Cell的數(shù)值
- Integer num = new Integer((int) cell
- .getNumericCellValue());
- cellvalue = String.valueOf(num);
- }
- break;
- }
- // 如果當(dāng)前Cell的Type為STRIN
- case HSSFCell.CELL_TYPE_STRING:
- // 取得當(dāng)前的Cell字符串
- cellvalue = cell.getStringCellValue().replaceAll("'", "''");
- break;
- // 默認(rèn)的Cell值
- default:
- cellvalue = " ";
- }
- } else{
- cellvalue = "";
- }
- // 在每個(gè)字段之間插入分割符
- buffer.append(cellvalue).append(EXCEL_LINE_DELIMITER);
- }
- // 以字符串返回該行的數(shù)據(jù)
- return buffer.toString();
- }
- // close函數(shù)執(zhí)行流的關(guān)閉操作
- public void close(){
- // 如果is不為空,則關(guān)閉InputSteam文件輸入流
- if (is != null){
- try{
- is.close();
- } catch (IOException e){
- is = null;
- }
- }
- // 如果reader不為空則關(guān)閉BufferedReader文件輸入流
- if (reader != null){
- try{
- reader.close();
- } catch (IOException e){
- reader = null;
- }
- }
- }
- }
下面創(chuàng)建一個(gè)main函數(shù),用來測(cè)試上面的ExcelReader類,代碼如下。
java 代碼
- public static void main(String[] args){
- try{
- ExcelReader er=new ExcelReader("c:\xp.xls");
- String line=er.readLine();
- while(line != null){
- System.out.println(line);
- line=er.readLine();
- }
- er.close();
- }catch(Exception e){
- e.printStackTrace();
- }
- }
main函數(shù)先創(chuàng)建一個(gè)ExcelReader類,然后調(diào)用它提供的接口readLine,對(duì)XLS文件進(jìn)行讀取,打印到控制臺(tái),處理前的XLS文件如圖7-12所示。

圖7-12 處理前的XLS文件內(nèi)容
運(yùn)行main函數(shù)進(jìn)行內(nèi)容提取后,Eclipse的控制臺(tái)輸出如圖7-13所示。

圖7-13 輸出結(jié)果
可以看到,Excel文件中的內(nèi)容已經(jīng)被成功的輸出了出來。
7.3.3 POI中Excel文件Cell的類型
在讀取每一個(gè)Cell的值的時(shí)候,通過getCellType方法獲得當(dāng)前Cell的類型,在Excel中Cell有6種類型,如表7-3所示。
表7-3 Cell的類型
CellType
|
說明
|
CELL_TYPE_BLANK
|
空值
|
CELL_TYPE_BOOLEAN
|
布爾型
|
CELL_TYPE_ERROR
|
錯(cuò)誤
|
CELL_TYPE_FORMULA
|
公式型
|
CELL_TYPE_STRING
|
字符串型
|
CELL_TYPE_NUMERIC
|
數(shù)值型
|
本 例采用了CELL_TYPE_STRING和CELL_TYPE_NUMERIC類型,因?yàn)樵?span id="wmqeeuq" class="hilite2">Excel文件中只有字符串和數(shù)字。如果Cell的Type 為CELL_TYPE_NUMERIC時(shí),還需要進(jìn)一步判斷該Cell的數(shù)據(jù)格式,因?yàn)樗锌赡苁荄ate類型,在Excel中的Date類型也是以 Double類型的數(shù)字存儲(chǔ)的。Excel中的Date表示當(dāng)前時(shí)間與1900年1月1日相隔的天數(shù),所以需要調(diào)用HSSFDateUtil的 isCellDateFormatted方法,判斷該Cell的數(shù)據(jù)格式是否是Excel Date類型。如果是,則調(diào)用getDateCellValue方法,返回一個(gè)Java類型的Date。
實(shí)際上Excel的數(shù)據(jù)格式有很多,還支持用戶自定義的類型,在Excel中,選擇一個(gè)單元格然后右鍵選擇“設(shè)置單元格格式”,在彈出的單元格格式中選中“數(shù)字”,如圖7-14所示。

圖7-14 Excel的單元格格式
圖中的數(shù)據(jù)有數(shù)值、貨幣、時(shí)間、日期、文本等格式。這些數(shù)據(jù)格式在POI中的HSSFDataFormat類里都有相應(yīng)的定義。
HSSFDataFormat 是HSSF子項(xiàng)目里面定義的一個(gè)類。類HSSFDataFormat允許用戶新建數(shù)據(jù)格式類型。HSSFDataFormat類包含靜態(tài)方法 static java.lang.String getBuiltinFormat(short index),它可以根據(jù)編號(hào)返回內(nèi)置數(shù)據(jù)類型。另外static short getBuiltinFormat(java.lang.String format)方法則可以根據(jù)數(shù)據(jù)類型返回其編號(hào), static java.util.List getBuiltinFormats()可以返回整個(gè)內(nèi)置的數(shù)據(jù)格式列表。
在HSSFDataFormat里一共定義了49種內(nèi)置的數(shù)據(jù)格式,如表7-4所示。
表7-4 HSSFDataFormat的數(shù)據(jù)格式
內(nèi)置數(shù)據(jù)類型
|
編號(hào)
|
"General"
|
0
|
"0"
|
1
|
"0.00"
|
2
|
"#,##0"
|
3
|
"#,##0.00"
|
4
|
"($#,##0_);($#,##0)"
|
5
|
"($#,##0_);[Red]($#,##0)"
|
6
|
"($#,##0.00);($#,##0.00)"
|
7
|
"($#,##0.00_);[Red]($#,##0.00)"
|
8
|
"0%"
|
9
|
"0.00%"
|
0xa
|
"0.00E+00"
|
0xb
|
"# ?/?"
|
0xc
|
posted on 2009-04-23 00:07 強(qiáng)強(qiáng) 閱讀(17928) 評(píng)論(2) 編輯 收藏