入職后參與的第一個項目是“煙草GIS項目”,分配給我的任務參主要是用戶對系統數據Excel格式的錄入和導出,滿足此項需求可以在很大程度上為用戶在項目外對數據的處理中提供很大便利,使其可以利用Excel的強大功能來實現一些統計運算,但是java自帶的API中並沒有直接操作Excel表格的的方法,為解決問題,只能借助第三方的解決方案。
根據了解所知,在java處理Excel領域已經存在很多的開源解決方案,其中比較突出的有ApachePOI和JExcelApi(jxl)。
*Apache是世界上使用排名第一的Web服務器軟件,它的跨平台和安全性使其成為最流行的Web服務器軟件之一,ApachePOI是Apache基金組織Jakarta項目的子項目,它包括一系列的API,可以操作多種格式的Microsoft Office文件,通過這些API使java更方便的操作Excel、Word等格式的Office文件
*JExcelApi(jxl)是一個韓國人寫的java操作Excel的工具,名氣雖然遜於ApachePOI,但同樣有自己的的特色
功能上POI要強一些,對於圖形圖表的支持更完善,但是JExcelApi(jxl)對於以下方面有着明顯的優勢:1、合並單元格加邊框問題;2、中文亂碼問題等等
接下來要記錄的就是用ApachePOI對Excel的基本操作:
我把項目中對Excel操作划分為三大部分:1、生成Excel模板,方便用戶導出后填充;2、完善Excel表格,數據導入處理;3、讀取數據庫數據,Excel格式導出數據。本文章中記錄是對模板生成導出的分析整理
* 模板導出
接下來我會以“個人信息”的excel為例,為大家做示范(如圖1.1所示),雖然這只是一個最簡單的模板,但是復雜的模板無非是在基礎上的堆積,可能多些麻煩,但是基本作法大體都是雷同的
圖1.1
首先先闡述需要到處模板的樣式和要求(如圖1.1所示):
一、模板有3行標題欄(即:方便用戶觀看,但是讀取時不會讀取的行);
二、模板中第1行占據5列;
三、模板中1、3、5列的第2行和第3行都是合並的;
四、模板中第2行的3、4列是合並的;
五、特殊要求:(很有效,也很常用)
部門只有固定的幾個,為避免錄入時錄入不明確、模糊信息,模板中設定部門一列中有個選擇框,設定只能選擇(“研發部”,“財務部”,“工程部”)
六、留給用戶填寫的空的表格;
七、標題欄的字體多為宋體、加粗;
八、標題欄中和填充欄中都無底色;
九、能夠導出,導出存放位置自選;(這點很關鍵,是個小技巧,但我查了好多資料,關鍵是查詢時不會表述)
下面我們進行代碼編寫
1、導入要用到的ApachePOI的jar包,我導入的有下圖中的這些:

2、我們先來實現純java語言來實現生成excel並導出到指定位置
(ApachePOI將Excel划分為HSSFWorkBook、HSSFSheet、HSSFRow、HSSFCell幾部分,按部就班的填充即可)
1 public boolean createExcelModel()throws Exception{ 2 //這是基本步驟,創建一個工作簿,在工作簿上創建一頁並命名 3 HSSFWorkBook excel=new HSSFWorkBook(); 4 HSSFSheet sheet=excel.createSheet(); 5 excel.setSheetName(0, "個人信息模板"); 6 //創建第一列的樣式 7 HSSFCellStyle style=excel.createCellStyle(); 8 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); style.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM); 9 style.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM); 10 style.setBorderRight(HSSFCellStyle.BORDER_MEDIUM); 11 style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM); 12 //創建第一格中字體樣式 13 HSSFFont font=model.createFont(); 14 font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 15 //將設置的字體樣式加入單元格樣式中 16 style.setFont(font); 17 //創建第一格單元格,並將之前設置的樣式加入 18 HSSFRow row=sheet.createRow((short)0); 19 HSSFCell cell=row.createCell((short)0); 20 cell.setCellValue("個人信息錄入"); 21 cell.setCellStyle(style); 22 //這個地方加入每個列都是“”,並不是沒有用處的 23 //POI對於合並后邊框問題處理並不好,這樣更美觀些,也可能有其他辦法 24 HSSFCell cella=null; 25 for (int i = 1; i < 5; i++) { 26 cella=row.createCell((short)i); 27 cella.setCellValue(""); 28 cella.setCellStyle(style); 29 } 30 //設置接下來兩行標題的樣式 31 HSSFCellStyle styleTitle=excel.createCellStyle(); 32 //加邊框 styleTitle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM); 33 styleTitle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM); styleTitle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM); 34 styleTitle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM); 35 HSSFFont fontTitle = model.createFont(); 36 fontTitle.setBoldweight((short) 10);// 設置字體的寬度 37 fontTitle.setFontHeightInPoints((short) 10);// 設置字體的高度 38 fontTitle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗體顯示 39 styleTitle.setFont(fontTitle);// 設置style1的字體 40 styleTitle.setWrapText(true);// 設置自動換行 41 // 設置單元格字體顯示居中(左右方向) 42 styleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER); 43 // 設置單元格字體顯示居中(上下方向) styleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); 44 //創建第二行,並將上面設置的標題樣式加入 45 HSSFRow rowTitle=sheet.createRow((short)1); 46 //第二行四列數據 47 HSSFCell cellNum=rowTitle.createCell((short)0); 48 cellNum.setCellValue("編號"); 49 cellNum.setCellStyle(styleTitle); 50 HSSFCell cellName=rowTitle.createCell((short)1); 51 cellName.setCellValue("姓名"); 52 cellName.setCellStyle(styleTitle); 53 HSSFCell cellMsg=rowTitle.createCell((short)2); 54 cellMsg.setCellValue("驗證信息"); 55 cellMsg.setCellStyle(styleTitle); 56 HSSFCell cellDept=rowTitle.createCell((short)4); 57 cellDept.setCellValue("部門"); 58 cellDept.setCellStyle(styleTitle); 59 //第三行兩列數據 60 HSSFRow rowAT=sheet.createRow((short)2); 61 HSSFCell cellS=null; 62 for (int i = 0; i < 2; i++) { 63 cellS=rowAT.createCell((short)i); 64 cellS.setCellValue(""); 65 cellS.setCellStyle(styleTitle); 66 } 67 HSSFCell cellSss=rowAT.createCell((short)2); 68 cellSss.setCellValue("密碼"); 69 cellSss.setCellStyle(styleTitle); 70 HSSFCell cellCard=rowAT.createCell((short)3); 71 cellCard.setCellValue("身份證號"); 72 cellCard.setCellStyle(styleTitle); 73 HSSFCell cellD=rowAT.createCell((short)4); 74 cellD.setCellValue(""); 75 cellD.setCellStyle(styleTitle); 76 //將標題的合並合並起來 77 Region region=null; 78 region=new Region((short)0,(short)0,(short)0,(short)4); 79 sheet.addMergedRegion(region); 80 region=new Region((short)1,(short)0,(short)2,(short)0); 81 sheet.addMergedRegion(region); 82 region=new Region((short)1,(short)1,(short)2,(short)1); 83 sheet.addMergedRegion(region); 84 region=new Region((short)1,(short)4,(short)2,(short)4); 85 sheet.addMergedRegion(region); 86 region=new Region((short)1,(short)2,(short)1,(short)3); 87 sheet.addMergedRegion(region); 88 //生成填充表格 89 HSSFRow rowi=null; 90 HSSFCell celli=null; 91 for (int i = 3; i < 10; i++) { 92 rowi=sheet.createRow(i); 93 for (int j = 0; j < 5; j++) { 94 celli=rowi.createCell((short)j); 95 celli.setCellValue(""); 96 celli.setCellStyle(styleTitle); 97 } 98 } 99 for (int i = 0; i < 5; i++) { 100 sheet.setColumnWidth((short) i, (short) 4000); 101 } 102 }
以上代碼就生成了Excel模板的雛形,當然不要忘記相應的導包。我們來大體回顧一下代碼的基本步驟:
a、生成工作簿,並在工作簿上生成一頁並命名;
b、生成一行數據樣式;
c、創建一行,並把生成的樣式賦給此行;
d、重復b和c兩步,生成新的兩行,並給予其樣式,這樣標題欄部分就完成了;
e、Region來完成單元格合並,形成標題欄的正常形式;
f、生成填充欄,並賦予其初始值為“”.
這樣我們前面列出的一、二、三、四、六、七和八就都完成了,里面的Region實現合並、HSSFStyle樣式中細分類是重點。
備注:Region中(起始行,起始列,終止行、終止列)
3、實現加入下拉列表框功能(在現有基礎上補充以下代碼),這個地方為固定的,如果想要改變下拉列表框內的值,傳遞LIST的參數即可。
//設置一個需要提供下拉的區域 String[] list={"研發部","財務部","工程部",}; //確定下拉列表框的位置 CellRangeAddressList regions=new CellRangeAddressList(3,65535,4,4); //生成下拉列表框的內容 DVConstraint constraint=DVConstraint.createExplicitListConstraint(list); //綁定下拉框的作用區域 HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint); //對哪一頁起作用 sheet.addValidationData(dataValidate)
生成的效果圖,如圖1.2,這只是個示例圖,效果跟這個一樣

圖1.2
4、這樣來看,我們所有的需求只有“導出”一項沒有完成了,接下來我們來說說導出。
首先,是最基本最簡單的java語言直接導出
1 String path="D:\\test";
//將生成的excel格式文檔以流的形式輸出 2 FileOutputStream fops=new FileOutputStream(path); 3 excel.write(fops); 4 //輸出完成后,關閉流通道 5 fops.close();
另外,如果是想要自己選擇下載的位置,那就做如下操作(以jsp+servlet為例):
1 public void doPost(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 //添加這個表頭,使得可以保存的形式進行導出 4 response.setContentType("application/vnd.ms-excel"); 5 try{ 6 HSSFWorkbook model=new HSSFWorkbook(); 7 //這一部分是在生成的工作簿上做一個excel表格 8 //**這個地方是把生成的工作簿傳遞給service,在這個工作簿上生成頁** 9 //這一部分是數據流的形式還原excel表格 10 //這個地方就不用再加path地址 11 ServletOutputStream out = response.getOutputStream(); 12 model.write(out); 13 //out flush是將緩沖區內的數據,不許等到緩沖區滿(自己理解的是緩沖完成)才輸出,而是直接輸出 14 out.flush(); 15 out.close(); 16 }catch (Exception e) { 17 e.printStackTrace(); 18 } 19 }
該功能的效果圖如圖1.3所示
圖1.3
好了,到此為止,我們想要導出模板的所有需求全部都完成了,現在我們來簡單回顧下全部的工作步驟和實現:
a、導入Apache POI的包,為的是用第三方來解決問題,導包是必須滴;
b、生成Excel模板雛形,這里對於region、hssfstyle樣式關注比較多,尤其是樣式,比較繁瑣,像邊框、居中、底色、字體等等;
c、下拉列表框的特殊需求,現代人都喜歡干什么都省事,而且實現這個的也能有效避免數據錄入錯誤的幾率,有必要做上也好;
d、自主選擇導出路徑,加上此功能之后在一瞬間感覺項目正規了好多。
這就是我的第一篇博客,經驗不多,而且進入軟件行業時間不長,理解可能會有些偏頗,寫的有點糙,希望大家見諒,如果有我沒說到,或者可能會有相關的問題,希望大家能給我留言,大家互相交流,共同進步,接下來我會完成Apache POI實現Excel數據讀取和數據庫數據放入Excel的博客,謝謝大家。
