Microsoft的Office系列產(chǎn)品擁有大 量的用戶,Word、Excel也成為辦公文件的首選。在Java中,已經(jīng)有很多對于Word、Excel的開源的解決方案,其中比較出色的是 Apache的Jakata項目的POI子項目。該項目的官方網(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子項目包括:POIFS、HSSF、HDF、HPSF。表7-2對它們進行了簡要介紹。
表7-2 POI子項目介紹
子項目名
|
說明
|
POIFS(POI File System)
|
POIFS是POI項目中最早的最基礎(chǔ)的一個模塊,是Java到OLE 2 Compound Document Format的接口,支持讀寫功能,所有的其他項目都依賴與該項目。
|
HSSF(Horrible Spreadsheet Format)
|
HSSF是Java到Microsoft Excel 97(-2002)文件的接口,支持讀寫功能
|
HWPF(Horrible Word Processing Format)
|
HWPF是Java到Microsoft Word 97文件的接口,支持讀寫功能,但目前該模塊還處于剛開始開發(fā)階段,只能實現(xiàn)一些簡單文件的操作,在后續(xù)版本中,會提供更強大的支持
|
HPSF(Horrible Property Set Format)
|
HPSF 是Java到OLE 2 Compound Document Format文件的屬性設(shè)置的接口,屬性設(shè)置通常用來設(shè)置文檔的屬性(標題,作者,最后修改日期等),還可以設(shè)置用戶定義的屬性。HPSF支持讀寫功能,當前發(fā)布版本中直支持讀功能。
|
7.3.1 對Excel的處理類
下 面通過HSSF提供的接口對Excel文件經(jīng)行處理。首先需要下載POI的包,可以到apache的官方網(wǎng)站下載,地址為:http: //apache.justdn.org/jakarta/poi/,本書采用的是poi-2.5.1-final-20040804.jar,讀者可以 下載當前的穩(wěn)定版本。把下載的包按照前面介紹的方式加入Build Path,然后新建一個ch7.poi包,并創(chuàng)建一個ExcelReader類。
ExcelReader類可以讀取一個XLS文件,然后將其內(nèi)容逐行提取出來,寫入文本文件。其代碼如下。
java 代碼
-

public class ExcelReader
{
// 創(chuàng)建文件輸入流
private BufferedReader reader = null;
// 文件類型
private String filetype;
// 文件二進制輸入流
private InputStream is = null;
// 當前的Sheet
private int currSheet;
// 當前位置
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)建一個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è)置當前位置為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值獲得當前的sheet
HSSFSheet sheet = workbook.getSheetAt(currSheet);
// 判斷當前行是否到但前Sheet的結(jié)尾

if (currPosition > sheet.getLastRowNum())
{
// 當前行位置清零
currPosition = 0;
// 判斷是否還有Sheet

while (currSheet != numOfSheets - 1)
{
// 得到下一張Sheet
sheet = workbook.getSheetAt(currSheet + 1);
// 當前行數(shù)是否已經(jīng)到達文件末尾

if (currPosition == sheet.getLastRowNum())
{
// 當前Sheet指向下一張Sheet
currSheet++;
continue;

} else
{
// 獲取當前行數(shù)
int row = currPosition;
currPosition++;
// 讀取當前行數(shù)據(jù)
return getLine(sheet, row);
}
}
return null;
}
// 獲取當前行數(shù)
int row = currPosition;
currPosition++;
// 讀取當前行數(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();
// 獲取當前行的列數(shù)
int filledColumns = rowline.getLastCellNum();
HSSFCell cell = null;
// 循環(huán)遍歷所有列

for (int i = 0; i < filledColumns; i++)
{
// 取得當前Cell
cell = rowline.getCell((short) i);
String cellvalue = null;

if (cell != null)
{
// 判斷當前Cell的Type

switch (cell.getCellType())
{
// 如果當前Cell的Type為NUMERIC

case HSSFCell.CELL_TYPE_NUMERIC:
{
// 判斷當前的cell是否為Date

if (HSSFDateUtil.isCellDateFormatted(cell))
{
// 如果是Date類型則,取得該Cell的Date值
Date date = cell.getDateCellValue();
// 把Date轉(zhuǎn)換成本地格式的字符串
cellvalue = cell.getDateCellValue().toLocaleString();
}
// 如果是純數(shù)字

else
{
// 取得當前Cell的數(shù)值
Integer num = new Integer((int) cell
.getNumericCellValue());
cellvalue = String.valueOf(num);
}
break;
}
// 如果當前Cell的Type為STRIN
case HSSFCell.CELL_TYPE_STRING:
// 取得當前的Cell字符串
cellvalue = cell.getStringCellValue().replaceAll("'", "''");
break;
// 默認的Cell值
default:
cellvalue = " ";
}

} else
{
cellvalue = "";
}
// 在每個字段之間插入分割符
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;
}
}
}
}
7.3.2 ExcelReader的運行效果
下面創(chuàng)建一個main函數(shù),用來測試上面的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)建一個ExcelReader類,然后調(diào)用它提供的接口readLine,對XLS文件進行讀取,打印到控制臺,處理前的XLS文件如圖7-12所示。
圖7-12 處理前的XLS文件內(nèi)容
運行main函數(shù)進行內(nèi)容提取后,Eclipse的控制臺輸出如圖7-13所示。
圖7-13 輸出結(jié)果
可以看到,Excel文件中的內(nèi)容已經(jīng)被成功的輸出了出來。
7.3.3 POI中Excel文件Cell的類型
在讀取每一個Cell的值的時候,通過getCellType方法獲得當前Cell的類型,在Excel中Cell有6種類型,如表7-3所示。
表7-3 Cell的類型
CellType
|
說明
|
CELL_TYPE_BLANK
|
空值
|
CELL_TYPE_BOOLEAN
|
布爾型
|
CELL_TYPE_ERROR
|
錯誤
|
CELL_TYPE_FORMULA
|
公式型
|
CELL_TYPE_STRING
|
字符串型
|
CELL_TYPE_NUMERIC
|
數(shù)值型
|
本 例采用了CELL_TYPE_STRING和CELL_TYPE_NUMERIC類型,因為在Excel文件中只有字符串和數(shù)字。如果Cell的Type 為CELL_TYPE_NUMERIC時,還需要進一步判斷該Cell的數(shù)據(jù)格式,因為它有可能是Date類型,在Excel中的Date類型也是以 Double類型的數(shù)字存儲的。Excel中的Date表示當前時間與1900年1月1日相隔的天數(shù),所以需要調(diào)用HSSFDateUtil的 isCellDateFormatted方法,判斷該Cell的數(shù)據(jù)格式是否是Excel Date類型。如果是,則調(diào)用getDateCellValue方法,返回一個Java類型的Date。
實際上Excel的數(shù)據(jù)格式有很多,還支持用戶自定義的類型,在Excel中,選擇一個單元格然后右鍵選擇“設(shè)置單元格格式”,在彈出的單元格格式中選中“數(shù)字”,如圖7-14所示。
圖7-14 Excel的單元格格式
圖中的數(shù)據(jù)有數(shù)值、貨幣、時間、日期、文本等格式。這些數(shù)據(jù)格式在POI中的HSSFDataFormat類里都有相應(yīng)的定義。
HSSFDataFormat 是HSSF子項目里面定義的一個類。類HSSFDataFormat允許用戶新建數(shù)據(jù)格式類型。HSSFDataFormat類包含靜態(tài)方法 static java.lang.String getBuiltinFormat(short index),它可以根據(jù)編號返回內(nèi)置數(shù)據(jù)類型。另外static short getBuiltinFormat(java.lang.String format)方法則可以根據(jù)數(shù)據(jù)類型返回其編號, static java.util.List getBuiltinFormats()可以返回整個內(nèi)置的數(shù)據(jù)格式列表。
在HSSFDataFormat里一共定義了49種內(nèi)置的數(shù)據(jù)格式,如表7-4所示。
表7-4 HSSFDataFormat的數(shù)據(jù)格式
內(nèi)置數(shù)據(jù)類型
|
編號
|
"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 2008-11-29 09:50
Vincent-chen 閱讀(1036)
評論(0) 編輯 收藏 所屬分類:
POI 、
Print