Apache POI是Apache軟件基金會的開放源碼函式庫。html
提供API給Java應用程序對Microsoft Office格式檔案讀和寫的功能。java
老外起名字老是很謙虛,POI爲(Poor Obfuscation Implementation)的首字母縮寫,意爲「可憐的模糊實現」。sql
若是你查看過 Apache 開源庫中的任意項目的源碼,你會發現恰到好處的設計模式、高內聚低耦合的模塊關係、數據庫
到位的接口抽象、優雅的實現方式,這樣的一些特色。apache
o(︶︿︶)o 唉 須要多嚴謹的思惟、多大的代碼實現量,多少項目的設計積累,才能達到那樣的高度?設計模式
POI 中主要提供的讀寫 Microsoft Office 功能點以下:app
本文借一次使用POI 實現讀寫 Excel 的過程,記述其中具體POI運用的方式。ide
由搜索引擎點進來的同窗,上面這一句話就是本文的主旨句。若能解決你問題,請往下細看。字體
項目中使用的是最新的 poi-3.14-20160307.jar,百度雲地址:http://pan.baidu.com/s/1bnWFWg3 密碼: kameui
Oschina 收錄地址:https://www.oschina.net/p/poi
官方 Demo : http://poi.apache.org/spreadsheet/examples.html#hssf-only
因項目比較大,下面爲單獨新建工程後的例子。
上圖左側用例圖爲 POI 寫 Excel
a.getExcelData: 獲取須要輸出到Excel數據,這裏的數據獲取能夠是從持久層,頁面展現層......
(例子中的數據爲Mysql自有數據庫中表help_categroy 表記錄),其中的 JavaBean創建 與 數據庫獲取的過程這裏就不說了。
獲取數據的數據類型是這樣的 List<HelpCategory>
b.POI Write Workbook:這裏纔是關鍵的地方,使用POI 將數據實例化爲 HSSFWorkbook。核心代碼以下:
public HSSFWorkbook expExcel(List<HelpCategory> helpCategories) { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); createSheetStyle(workbook, sheet); 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); } 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); } } return workbook; }
獲取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
http://blog.csdn.net/tolcf/article/details/48346697
上圖左側用例圖爲 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表格樣式的變化........
但熟悉具體核心讀寫實現,已不變應萬變,可爲上將。