兩種方式實現java生成Excel


 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
GitHub:https://github.com/itRed 版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段說明,
且在文章明顯位置給出原文鏈接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM