Web應用中難免會遇到需要將數據導出並生成excel文件的需求。同樣,對於本博客中的總結,也是建立在為了完成這樣的一個需求,才開始去了解其實現形式,並且順利完成需求的開發,先將實現過程總結於此。本博文是本人的勞動成果所得,在博客園總結分享,歡迎轉載。在沒有作者的書面說明的情況下,必須保留本段聲明。作者:itRed 郵箱:it_red@sina.com 博客鏈接:http://www.cnblogs.com/itred GitHub鏈接:http://github.com/itred
根據自己的梳理,完成這樣的需求在自己的技術范圍之內比較認可的有兩種方式,其一是利用第三方插件JXL實現excel文件的生成,另一種方式則是不需要第三方的插件,直接通過jsp頁面的設置和action層的response跳轉完成excel文件的生成。綜合來講,采用第三方插件不僅能夠滿足功能性需求,而且還提供函數、字體、顏色及其他方面的接口,如果直接采用jsp跳轉形式,則樣式會略顯低調,但是其實現形式很容易理解,無需了解更多的技術層面的東西。現將兩種具體的實現方式列出:
Demo 1:
首先來個簡單易懂的。直接在action中將數據放到session服務器緩存中,然后再跳轉到指定的jsp頁面,在指定的jsp頁面中設置其ContentType,這個會牽扯到http協議的response.ContentType 。不同的ContentType會影響到客戶端看到的具體效果,默認的ContentType為text/html,也就是最為常見的網頁格式。
新建web項目,加入struts2的相關jar包, 在默認的index.jsp頁面加入一個form表單,本案例僅僅完成功能,數據在后台已經封裝好,無前端交互,直接input一個提交按鈕,轉向action。index.jsp的源碼如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>導出</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <form action="getXls_excel" method="post"> <input type="submit" value="提交" /> </form> </body> </html>
然后新建action名為ExcelAction,源碼如下:
package com.red.action; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * jsp形式導出excel * @author Red */ public class ExcelAction extends ActionSupport { private static final long serialVersionUID = -3673769122296267756L; protected HttpServletRequest request = ServletActionContext.getRequest(); protected HttpServletResponse response = ServletActionContext.getResponse(); public void getXls() throws IOException { StringBuffer sb = new StringBuffer(); sb.append("<table><tr><td>用戶名稱</td><td>郵箱地址</td></tr>"); Map<String, String> map = new HashMap<String, String>(); map.put("red1", "it_red@sina.com"); map.put("red2", "it_red@sohu.com"); map.put("red3", "it_red@163.com"); for (String key : map.keySet()) { sb.append("<tr><td>").append(key).append("</td><td>").append(map.get(key)).append("</td></tr>"); } request.getSession().setAttribute("excel", sb.toString()); response.sendRedirect(request.getContextPath() + "/export.jsp"); } }
然后新建一個跳轉后的jsp頁面,也即是處理excel文件的工具。源碼如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page contentType="application/msexcel"%> <% response.setContentType("application/msexcel;charset=UTF-8"); response.setHeader("Content-disposition", "attachment; filename=test.xls"); %> <html> <head> <title>Excel</title> </head> <body> <% String str = new String(session.getAttribute("excel").toString()); out.print(str); %> </body> </html>
在這里導出的文檔編碼是根據本地電腦的編碼形式進行編碼的,所以,如果本地是中文則需要修改response.setContentType("application/msexcel;charset=UTF-8");中的編碼,將其改為GBK或者GB18030,只要支持中文就行。
功能實現,基本效果如下:
Demo2:
第二種方式是直接通過流的形式響應客戶端瀏覽器,通過瀏覽器來提供下載。只是在這個地方,將ContentType設置在了action中,而並非是在jsp頁面上。
加入JXL的jar包,Action源碼:
package com.red.action; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jxl.Workbook; import jxl.format.UnderlineStyle; import jxl.write.Colour; import jxl.write.Label; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import jxl.write.biff.RowsExceededException; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * 第三方插件導出Excel * @author Red */ public class WriteExcelAction extends ActionSupport { HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); public void writeExcel() throws RowsExceededException, WriteException, IOException { OutputStream os = response.getOutputStream();// 取得輸出流 response.reset();// 清空輸出流 response.setHeader("Content-disposition", "attachment; filename=testRed.xls");// 設定輸出文件頭 response.setContentType("application/msexcel");// 定義輸出類型 WritableWorkbook wbook = Workbook.createWorkbook(os); // 建立excel文件 String tmptitle = "測試數據"; // 標題 WritableSheet wsheet = wbook.createSheet(tmptitle, 0); // sheet名稱 // 設置excel標題 WritableFont wfont = new WritableFont(WritableFont.ARIAL, 16, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK); WritableCellFormat wcfFC = new WritableCellFormat(wfont); wcfFC.setBackground(Colour.AQUA); wsheet.addCell(new Label(1, 0, tmptitle, wcfFC)); wfont = new jxl.write.WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK); wcfFC = new WritableCellFormat(wfont); // 開始生成主體內容 wsheet.addCell(new Label(0, 2, "姓名")); wsheet.addCell(new Label(1, 2, "郵箱")); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Map<String, String> map = new HashMap<String, String>(); map.put("Red1", "it_red@sina.com"); map.put("Red2", "it_red@sohu.com"); map.put("Red3", "it_red@163.com"); int count = 0; for (String key : map.keySet()) { wsheet.addCell(new Label(0, count + 3, key)); wsheet.addCell(new Label(1, count + 3, map.get(key))); count++; } // 主體內容生成結束 wbook.write(); // 寫入文件 wbook.close(); os.close(); // 關閉流 } }
實現效果如下:
在完成以上兩個Demo之后,打開其生成的excel文件,很容易看到兩者的差別。其實對於究竟選擇哪種形式來生成excel文件,還是需要根據實際的開發情況及應用本身來決定的。各有其特點和好處以及缺點。l另外,當你能理解以上代碼時,以上代碼便不僅僅只能生成excel文件了,自然而然就可以生成一些其他文件。
另附本博文中所涉及到的案例源碼請點擊鏈接
作者:itRed 博客:http://itred.cnblogs.com |