2012年1月28日 星期六

Jakarta POI

POI在我們程式開發中,最常使用的時機是處理Excel檔。是Jakarta底下的一個專案。
網址: http://poi.apache.org/

處理Excel的時機,分為要讀取Excel檔案以及匯出成Excel檔。底下先介紹POI的類別指的是那些部分。

1         讀取Excel檔的流程:
1.1      讀取檔案:使用POIFSFileSystem取得一個InputStream
1.2      建立活頁簿:使用HSSFWorkbook
1.3      取得sheet:使用HSSFSheet  sheet = wb.getSheetAt(0) 表示要取得第一個sheet
1.4      取得row:使用HSSFRow
row = sheet.getRow(0);
表示要取得第一行
1.5      取得cell:使用HSSFCell cell = row.getCell((short) 0); 表示要取得第A個欄位
1.6      取得資料:

字串(String)
cell.getStringCellValue();
數字(double)
cell.getNumericCellValue()
時間(Date)
cell.getDateCellValue();


我們通常會用跑迴圈的方式去讀取資料,因此必須取得迴圈的次數,底下這些是常用的:

sheet數量
HSSFWorkbook
getNumberOfSheets()
row數量
HSSFSheet
getPhysicalNumberOfRows()
cell數量
HSSFRow
getPhysicalNumberOfCells()


HSSFCell取得資料的時候,常會發生NumberFormatException,以致於無法讀取資料,因此建議的寫法如下: 使用try catch去捉到正確的資料
if(cell != null){
                     try {
                           cellValue = cell.getStringCellValue();
                     } catch (NumberFormatException ex) {
                          cellValue = String
                                     .valueOf((int) cell.getNumericCellValue());
                     }
                }else{
                     cellValue = "";
                }

在讀取Excel的檔案,需要注意幾點:
1         通常第一排(row)是標題,不要轉檔
2         不要因為某一筆資料發生錯誤,而導致整個檔案都無法繼續轉檔
3         某一筆資料發生錯誤時,應該要紀錄是第幾筆資料發生錯誤,並回覆給User知道
4         留下Excel的這個範本,以後User上傳Excel檔案時,都應遵照此範本格式



建立Excel檔的流程:
建立Excel分為2種方法:無中生有,或者是讀取一個範本檔去增加資料,這2種方法的差別只在於workbooksheetrowcell,無中生有是用create,讀取範本是用get。底下的流程都是一樣的:
1.        new 一個ByteArrayOutputStream
2.        取得或new一個HSSFWorkbook
3.        取得或create sheet
4.        取得或create row
5.        取得或create Cell
6.        cell塞入資料  cell.setCellValue(value)
7.        HSSFWorkbook寫入ByteArrayOutputStream
因為這個部分的API非常多且雜,所以最好要養成查看API的習慣
set column寬度:
必須在一開始還未createCell之前要設好,否則會有奇怪的bug,數值大概要設到1000以上才有效果…
ex: sheet1.setColumnWidth( (short)1, (short) ( ( 50 * 4 ) / ( (double) 1 / 20 ) ) );

set row 高度:
在每一個row產生之後,在產生cell之前,是設row 高度的最好時機
ex: row.setHeight( (short) 0x349 ); //16進位制

合併儲存格:4個參數分別為(起始row,起始column,結束row,結束column)
sheet1.addMergedRegion(new Region(0,(short)5,0,(short)6));

設置UTF16編碼,避免中文亂碼:
cell.setEncoding(HSSFCell.ENCODING_UTF_16);

HSSFCellStyle
產生方式:HSSFCellStyle cellStyle = wb.createCellStyle();

強制換行
cellStyle.setWrapText(true);
水平對齊方式
cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);
垂直對齊方式
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);
框線
(上、下、左、右)
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
字型
HSSFFont font = wb.createFont();
font.setFontHeightInPoints((short) 12); //字大小12
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //Bold
cellStyle.setFont(font);
儲存格顏色
(前景顏色當背景)
cellStyle.setFillForegroundColor(HSSFColor.AQUA.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
資料樣式
cellStyle.setDataFormat(format.getFormat("#,##0.00"));
可用樣式:參考HSSFDataFormat  (0代表一個數字、#代表如果為0,則不要顯示)
常用樣式: double num = 1323.21345;
cellStyle.setDataFormat(format.getFormat("0")); à 1323
"0.00" à 1323.21
"#,##0" à 1,323
"#,##0.00" à 1,323.21
double num = 0.3214
"0.00%" à 32.14%




POI Tip:
1.        寫的時候,可以先寫成小程式,之後再把這個小程式套在Web App
2.        Web產生Excel,通常都用Servlet直接轉成outputStream,而不會產生一個檔案放在Server上面。
3.        User上傳檔案,在Struts可以用uploadFileForm…