`
yongtree
  • 浏览: 231102 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

生成Excel并在客户端下载的JSF实现

阅读更多

 

Excel这个大家几乎每天都用到的工具,为我们的工作带来了极大的方便。在现在的B/S系统中,特别是很多大型的办公系统中,大量的 报表需要处理,导出EXCEL的功能就显得尤为重要了。导出Excel已经是相当成熟的技术了,但是在java中却不是一件容易的事。特别是在JSF架构的系统中,由于使用的人数和学习的资料都很少,实现导出Excel的功能也颇费周折。由于项目的需要,本人需要实现这样的功能,经过对大量代码的改造,实现了JSF下的生成EXCEL并在客户端实现下载的功能。下面的例子中,我用的是POI来生成Excel。Apache的Jakata项目的POI子项目,目标是处理ole2对象。 POI可以到 http://www.apache.org/dyn/closer.cgi/jakarta/poi/ 下载。 编译好的jar主要有这样4个:poi包,poi Browser包,poi hdf包,poi hssf例程包。实际运行时,需要有poi包就可以了。

在下面的工具类中,我通过private static void downloadFile(String strfileName) 这个方法在生成EXCEL以后实现在客户端的下载。在这个类中,这个方法就是经过改造的JSF实现。不过这个工具类有个不足之处就是,传递给downloadFile(String strfileName) 的文件名不支持中文,希望大家注意,也希望各位能给出解决办法。

package mj.util.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

/**
 * 本工具类解决了java到处Excel,并同时实现了客户端下载 不足之处:下载方法传入的文件名不支持中文
 
 @author yongtree
 
 */
public class ExcelUtils {

  private static String sheetName = "data";

  private HSSFWorkbook wb;

  private HSSFSheet sheet;

  private HSSFRow row;

  private HSSFCell cell;

  private HSSFFont font;

  private HSSFCellStyle cellStyle;

  private FileOutputStream fileOut;

  public ExcelUtils() {
    wb = new HSSFWorkbook();
  }

  /**
   @param excelName
   *            excel名称。
   @param list
   *            这个list里面存放的是对象数组。数组元素可以转化为字符串显示的。这个对象数组一般对应数据库里的几列。
   @param firstRowValue
   */
  public void outputExcel(String excelName, List list, String[] firstRowValue) {
    try {
      this.createSheet(firstRowValue);
      this.setValueToRow(excelName, list);
    catch (Exception ex) {
      System.out.print(ex);
    }
    // System.out.println("文件名是:" + excelName);
    downloadFile(excelName);
  }

  public void outputExcel(String excelName, List list) {
    try {
      this.setValueToRow(excelName, list);
    catch (Exception e) {
      // TODO: handle exception
    }
    downloadFile(excelName);
  }

  private void setValueToRow(String excelName, List list) {
    // 获得JSF上下文环境
    FacesContext context = FacesContext.getCurrentInstance();
    // 获得ServletContext对象
    ServletContext servletContext = (ServletContextcontext
        .getExternalContext().getContext();
    // 取得文件的绝对路径
    excelName = servletContext.getRealPath("/UploadFile""/" + excelName;
    System.out.println("生成文件的路径是:" + excelName);
    Object[] obj;
    try {
      for (int i = 0; i < list.size(); i++) {
        row = sheet.createRow(i + 1);
        obj = (Object[]) list.get(i);
        this.createCell(row, obj);
      }
      fileOut = new FileOutputStream(excelName);
      wb.write(fileOut);

    catch (Exception ex) {
      System.out.print("生成报表有误:" + ex);
    finally {
      try {
        fileOut.flush();
        fileOut.close();
      catch (Exception e) {
        System.out.println("ExcelUtil.setValueToRow()");
      }
    }
  }

  private void createSheet(String[] firstRowValue) {
    try {
      sheet = wb.createSheet(ExcelUtils.sheetName);
      row = sheet.createRow(0);
      font = wb.createFont();
      font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
      cellStyle = wb.createCellStyle();
      cellStyle.setFont(font);
      for (int i = 0; i < firstRowValue.length; i++) {
        cell = row.createCell((shorti);
        cell.setCellStyle(cellStyle);
        cell.setEncoding(HSSFCell.ENCODING_UTF_16);
        cell.setCellValue(firstRowValue[i]);
      }
    catch (Exception ex) {
      System.out.print(ex);
    }
  }

  private void createCell(HSSFRow row, Object[] obj) {
    try {
      for (int i = 0; i < obj.length; i++) {
        cell = row.createCell((shorti);
        cell.setEncoding(HSSFCell.ENCODING_UTF_16);
        cell.setCellValue(obj[i].toString());
      }
    catch (Exception ex) {
      System.out.print(ex);
    }
  }

  /**
   <p>
   * 功能说明:根据提供的文件名下载文件,不支持中文文件名
   </p>
   * 此方法由yongtree添加,实现文件生成后的下载
   
   @param strfileName
   *            String
   @return void
   */
  private static void downloadFile(String strfileName) {
    try {
      // 获得JSF上下文环境
      FacesContext context = FacesContext.getCurrentInstance();
      // 获得ServletContext对象
      ServletContext servletContext = (ServletContextcontext
          .getExternalContext().getContext();
      // 取得文件的绝对路径
      String excelName = servletContext.getRealPath("/UploadFile""/"
          + strfileName;
      File exportFile = new File(excelName);
      HttpServletResponse httpServletResponse = (HttpServletResponseFacesContext
          .getCurrentInstance().getExternalContext().getResponse();
      ServletOutputStream servletOutputStream = httpServletResponse
          .getOutputStream();
      httpServletResponse.setHeader("Content-disposition",
          "attachment; filename=" + strfileName);
      httpServletResponse.setContentLength((intexportFile.length());
      httpServletResponse.setContentType("application/x-download");
      // httpServletResponse.setContentType("application/vnd.ms-excel");

      byte[] b = new byte[1024];
      int i = 0;
      FileInputStream fis = new java.io.FileInputStream(exportFile);
      while ((i = fis.read(b)) 0) {
        servletOutputStream.write(b, 0, i);
      }
    catch (IOException e) {
      e.printStackTrace();
    }
    FacesContext.getCurrentInstance().responseComplete();
  }

}

分享到:
评论
13 楼 JavaLet 2008-06-11  
修改了一下源码,问题解决了:
http://purebit.net/showtopic.aspx?page=end&topicid=9744#11013

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

/**
* 本工具类解决了java到处Excel,并同时实现了客户端下载 不足之处:下载方法传入的文件名不支持中文
*
* @author Java程序员,专注于Java领域的开发和新技术的研究
*
*/
public class ExcelUtils {

    private static String sheetName = "data";
    private HSSFWorkbook wb;
    private HSSFSheet sheet;
    private HSSFRow row;
    private HSSFCell cell;
    private HSSFFont font;
    private HSSFCellStyle cellStyle;
    private FileOutputStream fileOut;

    public ExcelUtils() {
        wb = new HSSFWorkbook();
    }

    /**
     * @param excelName
     *            excel名称。
     * @param list
     *            这个list里面存放的是对象数组。数组元素可以转化为字符串显示的。这个对象数组一般对应数据库里的几列。
     * @param firstRowValue
     */
    public void outputExcel(String excelName, List list, String[] firstRowValue) {
        try {
            this.createSheet(firstRowValue);
            this.setValueToRow(excelName, list);
        } catch (Exception ex) {
            System.out.print(ex);
        }
        // System.out.println("文件名是:" + excelName);
        downloadFile(excelName);
    }

    public void outputExcel(String excelName, List list) {
        try {
            this.setValueToRow(excelName, list);
        } catch (Exception e) {
        // TODO: handle exception
        }
        downloadFile(excelName);
    }

    private void setValueToRow(String excelName, List list) {
        // 获得JSF上下文环境
        FacesContext context = FacesContext.getCurrentInstance();
        // 获得ServletContext对象
        ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
        // 取得文件的绝对路径
        excelName = servletContext.getRealPath("/UploadFile") + "/" + excelName;
        System.out.println("生成文件的路径是:" + excelName);
        ArrayList obj;
        try {
            for (int i = 0; i < list.size(); i++) {
                row = sheet.createRow(i + 1);
                obj = (ArrayList)list.get(i);
                this.createCell(row, obj);
            }
            fileOut = new FileOutputStream(excelName);
            wb.write(fileOut);

        } catch (Exception ex) {
            System.out.print("生成报表有误:" + ex);
        } finally {
            try {
                fileOut.flush();
                fileOut.close();
            } catch (Exception e) {
                System.out.println("ExcelUtil.setValueToRow()");
            }
        }
    }

    private void createSheet(String[] firstRowValue) {
        try {
            sheet = wb.createSheet(ExcelUtils.sheetName);
            row = sheet.createRow(0);
            font = wb.createFont();
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            cellStyle = wb.createCellStyle();
            cellStyle.setFont(font);
            for (int i = 0; i < firstRowValue.length; i++) {
                cell = row.createCell((short) i);
                cell.setCellStyle(cellStyle);
                cell.setEncoding(HSSFCell.ENCODING_UTF_16);
                cell.setCellValue(firstRowValue[i]);
            }
        } catch (Exception ex) {
            System.out.print(ex);
        }
    }

    private void createCell(HSSFRow row, ArrayList obj) {
        try {
            for (int i = 0; i < obj.size(); i++) {
                cell = row.createCell((short) i);
                cell.setEncoding(HSSFCell.ENCODING_UTF_16);
                cell.setCellValue(obj.get(i).toString());
            }
        } catch (Exception ex) {
            System.out.print(ex);
        }
    }

    /**
     * <p>
     * 功能说明:根据提供的文件名下载文件,不支持中文文件名
     * </p>
     * 此方法由yongtree添加,实现文件生成后的下载
     *
     * @param strfileName
     *            String
     * @return void
     */
    private static void downloadFile(String strfileName) {
        try {
            // 获得JSF上下文环境
            FacesContext context = FacesContext.getCurrentInstance();
            // 获得ServletContext对象
            ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
            // 取得文件的绝对路径
            String excelName = servletContext.getRealPath("/UploadFile") + "/" + strfileName;
            File exportFile = new File(excelName);
            HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
            httpServletResponse.setHeader("Content-disposition",
                    "attachment; filename=" + strfileName);
            httpServletResponse.setContentLength((int) exportFile.length());
            httpServletResponse.setContentType("application/x-download");
            // httpServletResponse.setContentType("application/vnd.ms-excel");

            byte[] b = new byte[1024];
            int i = 0;
            FileInputStream fis = new java.io.FileInputStream(exportFile);
            while ((i = fis.read(b)) > 0) {
                servletOutputStream.write(b, 0, i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        FacesContext.getCurrentInstance().responseComplete();
    }
}
12 楼 JavaLet 2008-06-11  
老大们,我用的就是楼主提供的源码,为什么老出错呢??

生成报表有误:java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.Object;
11 楼 jerry.xhz 2008-05-29  
国内项目中,应用excel作为数据文件导出的功能,很常见,也很能为客户解决问题,方便客户制作数据报表,从效率和性能上讲,有2种实现方式:一,返回数据结果集到页面,直接展现为excel,只能应用于很少量的数据,否则客户肯定不能接受;二,在服务端得到数据结果集,调用各种工具类,将数据写入文件,如写入dbf和excel文件,然后提供客户端下载,这种方式应该是首选方案,如楼主的解决方案,将系统运行的压力交给服务器,在服务器上开辟一个专门的空间来存放文件,反之在客户端,还能利用各种下载工具进行文件下载,具备很好的性能和可扩展性
10 楼 aninfeel 2008-05-29  
不管用什么框架,对于输出excel和验证码之类的,我统统都是设置一下header,然后response.getOutputStream().....,何必搞得那么复杂。
9 楼 lizhongyao728@sohu.com 2008-05-29  
我在做jsf上传是有一个问题请教:
在执行setValueToRow(String excelName, List list)方法中的
obj = (Object[]) list.get(i);行时会抛一个java.lang.ClassCastException:com.tplife.orgadmin.orginfo.vo.OrgView 异常
我的list.get(i)得到的是数据库查询的一条记录
请问我该怎样改


8 楼 sswh 2008-01-30  
<div class='quote_title'>yongtree 写道</div><div class='quote_div'><p><span style='color: #7f0055;'><strong>不过这个工具类有个不足之处就是,传递给</strong><span style='color: #000000;'>downloadFile(String strfileName)</span><span style='color: #7f0055;'><strong> 的文件名</strong></span></span><strong><span style='color: #7f0055;'>不支持中文,希望大家注意,也希望各位能给出解决办法。</span></strong></p></div><p>方法一:象 xfspeed 说的,用URLEncoder。不过URLEncode的缺陷是,在IE中打开的Excel文件,名字显示为%A1%A2%A3..的形式。</p><p> </p><p>方法二:对文件名进行编码。因为IE和FireFox在处理非URLEncoder的http header时,使用的解码方式不同,IE使用系统的默认编码:GBK,FireFox使用Content-Type指定的编码。所以,通用的做法:</p><p> </p><p>     response.setContentType("application/vnd.ms-excel;charset=GBK"); </p><p>     filename = new String(filename.getBytes("GBK"), "ISO-8859-1"); </p><p>     response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");</p><p> </p><p>用struts2的话,我的action这样配置:</p><p> </p><pre name='code' class='xml'>&lt;action name="download_attachment" class="queryAction" method="download"&gt;
&lt;result type="stream"&gt;
&lt;param name="contentType"&gt;${attachment.mimeType};charset=GBK&lt;/param&gt;
&lt;param name="contentLength"&gt;${attachment.content.length()}&lt;/param&gt;
&lt;param name="inputName"&gt;attachment.content.binaryStream&lt;/param&gt;
&lt;param name="contentDisposition"&gt;
attachment;filename="${@my.util.CommonUtils@toAnotherCharset(attachment.name,'GBK','ISO-8859-1')}"&lt;/param&gt;
&lt;param name="bufferSize"&gt;1024&lt;/param&gt;
&lt;/result&gt;
&lt;/action&gt;
</pre> <p> </p>
7 楼 一叶孤鸿 2008-01-29  
如果生成的excel文件比较大(30M以上),无论使用POI还是JXL,对服务器的内存是个考验;
不知道各位对生成很大的excel文件有何好的解决方法?
6 楼 xfspeed 2008-01-29  
实现中文文件名的方法:
strfileName = java.net.URLEncoder.encode(strfileName, "UTF-8");
把上面这句加在你的downloadFile方法中,具体的位置我就不描述了,一看就知道了
5 楼 yegaofei 2007-10-19  
[/list][list]
引用
[u][i][b]
4 楼 yongtree 2007-10-18  
JavaInAction说的那种方法我也使用过,但是不是非常的好。
3 楼 JavaInActoin 2007-10-17  
最简单的导出为Excel的方式,可以用在某些场合:
用Excel做好模板,存为html格式,改为.jsp,将
<meta http-equiv=Content-Type content="text/html; charset=gb2312">
改为
<meta http-equiv=Content-Type content="application/vnd.ms-excel; charset=gb2312">
在需要显示数据的地方增加脚本。
这样一个正常的JSP,返回到用户时就是一个excel了。
2 楼 linxizeng 2007-10-17  
发现excel 还是用得蛮多的,有时候对数据的计算和数据的导入导出的确很方便,就是平台性不好~
1 楼 曹晓钢 2007-10-17  
不知道Seam是否有集成的excel导出实现?

相关推荐

Global site tag (gtag.js) - Google Analytics