Apache POI是Apache軟件基金會的開放源碼函式庫。
提供API給Java應用程序對Microsoft Office格式檔案讀和寫的功能。
老外起名字總是很謙虛,POI為(Poor Obfuscation Implementation)的首字母縮寫,意為“可憐的模糊實現”。
如果你查看過 Apache 開源庫中的任意項目的源碼,你會發現恰到好處的設計模式、模塊之間的高內聚低耦合、接口抽象相當到位、實現方式也非常優雅,這樣的一些特定。
o(︶︿︶)o 唉 需要多嚴謹的思維、多大的代碼實現量,多少項目的設計積累,才能達到那樣的高度?
POI 中主要提供的讀寫 Microsoft Office 功能點如下:
本文借一次使用POI 實現讀寫 Excel 的過程,記述其中具體POI運用的方式。
由搜索引擎點進來的同學,上面這一句話就是本文的主旨句。若能解決你問題,請往下細看。
項目中使用的是最新的 poi-3.14-20160307.jar,百度雲地址:http://pan.baidu.com/s/1bnWFWg3 密碼: kame
因項目比較大,下面為單獨新建工程後的例子。

上圖左側用例圖為 POI 寫 Excel
a.getExcelData: 獲取需要輸出到Excel數據,這裡的數據獲取可以是從持久層,頁面展示層......
(例子中的數據為Mysql自有數據庫中表help_categroy 表記錄),其中的 JavaBean建立 與 數據庫獲取的過程這裡就不說了。
獲取數據的數據類型是這樣的 List<HelpCategory>
b.POI Write Workbook:這裡才是關鍵的地方,使用POI 將數據實例化為 HSSFWorkbook。核心代碼如下:

獲取JavaBean字段值作為表頭,並設置表頭的樣式:
HSSFRow row = sheet.createRow(0);
HSSFCell cell;
HelpCategory category = new HelpCategory();
Field[] fields = category.getClass().getDeclaredFields();
for (int j = 0; j < fields.length; j++) {
cell = row.createCell(j);
cell.setCellValue(fields[j].getName());
cell.setCellStyle(this.textAlignCenter);
}
獲取JavaBean HelpCategory 中字段的值填充到對應的表格中,並設置樣式:
for (int i = 0; i < helpCategories.size(); i++) {
category = helpCategories.get(i);
row = sheet.createRow(i + 1);
for (int k = 0; k < fields.length; k++) {
Field field = fields[k];
Object o = invokeGet(category, field.getName());
cell = row.createCell(k);
cell.setCellValue(o != null ? o.toString() : "");
cell.setCellStyle((k == 0 || k == 1) ? this.textAlignCenter : this.textAlignLeft);
}
}
這裡面用的了一點反射的東西,來獲取javaBean屬性的值。
如果你覺得反射的效率有點差勁,可以自己構造一個Map數據集合,同樣能達到這樣的效果。
private Object invokeGet(Object o, String fieldName) {
Method method = getGetMethod(o.getClass(), fieldName);
try {
return method.invoke(o, new Object[0]);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Method getGetMethod(Class objectClass, String fieldName) {
StringBuilder sb = new StringBuilder();
sb.append("get");
sb.append(fieldName.substring(0, 1).toUpperCase());
sb.append(fieldName.substring(1));
try {
return objectClass.getMethod(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
同樣你可以設置表格樣式、邊框樣式:
private void createSheetStyle(HSSFWorkbook _workbook, HSSFSheet _sheet) {
// 設置表字體
HSSFFont font10 = _workbook.createFont();
font10.setFontHeightInPoints((short) 12);
font10.setFontName("黑體");
// 設置表樣
this.textAlignCenter = getCellStyle(_workbook, font10, HSSFCellStyle.ALIGN_CENTER);
this.textAlignLeft = getCellStyle(_workbook, font10, HSSFCellStyle.ALIGN_LEFT);
// 設置列寬
_sheet.setColumnWidth(0, 4000);
_sheet.setColumnWidth(1, 4000);
_sheet.setColumnWidth(2, 10000);
_sheet.setColumnWidth(3, 10000);
}
上面的樣式設置,如果還滿足不了你的功能需求,更多的設置請參考博客:http://langhua9527.iteye.com/blog/388005
上圖左側用例圖為 POI 寫 Excel
a.getExcleFile:獲取要讀取的Excel文件...這裡就不說了。(注意:判斷獲取的文件後綴名)
String fileName = excel.getName();
int iIndex = fileName.lastIndexOf(".");
String ext = (iIndex < 0) ? "" : fileName.substring(iIndex + 1).toLowerCase();
if (!"xls,xlsx".contains(ext) || "".contains(ext)) {
System.out.println("文件類型不是EXCEL!");
}
b.POI Read Workbook:這裡就是重點啦,使用POI讀取Excel文件,解析並進行保存到你自己數據類型當中。
ArrayList<HelpCategory> categories = new ArrayList<>();
try {
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(new FileInputStream(excel));
HSSFWorkbook workbook = new HSSFWorkbook(poifsFileSystem);
HSSFSheet sheet = workbook.getSheetAt(0);
HelpCategory category = new HelpCategory();
Field[] declaredField = category.getClass().getDeclaredFields();
for (int k = 1; k <= sheet.getLastRowNum(); k++) {
HSSFRow row = sheet.getRow(k);
category = new HelpCategory();
for (int j = 0; j < declaredField.length; j++) {
HSSFCell cell = row.getCell(j);
invokeSet(category, declaredField[j].getName(), cell.getStringCellValue());
}
categories.add(category);
}
} catch (Exception e) {
e.printStackTrace();
}
上面也同樣用到了一些反射的東西,這裡獲取JavaBean 的set方法,來設置具體的屬性。
public void invokeSet(Object o, String fieldName, Object value) {
Method method = getSetMethod(o.getClass(), fieldName);
try {
method.invoke(o, new Object[]{value});
} catch (Exception e) {
e.printStackTrace();
}
}
public Method getSetMethod(Class objectClass, String fieldName) {
try {
Class[] parameterTypes = new Class[1];
Field field = objectClass.getDeclaredField(fieldName);
parameterTypes[0] = field.getType();
StringBuffer sb = new StringBuffer();
sb.append("set");
sb.append(fieldName.substring(0, 1).toUpperCase());
sb.append(fieldName.substring(1));
Method method = objectClass.getMethod(sb.toString(), parameterTypes);
return method;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
上述例子僅當作拋磚引玉之用,項目中的具體需求隨時都有其他的變化。
如獲取數據的途徑可能是多表聯合查詢或者是展現層、結果需要進行其他運算、寫Excel表格樣式的變化........
但熟悉具體核心讀寫實現,已不變應萬變,可為上將。