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 |

