JXL导出Excel数据表

 

封装了一个简单易用、通用、动态的从数据库导出到Excel的方法,可以动态的指定导出那些列,显示什么名字,按什么顺序显示;支持本地文件存储和JSP/Servlet文件下载。

本方法包括两个类,Column是辅助类,Excel是主类:

Column:

 

/** 
 * 用于Excel导出的辅助类,映射数据结果集(ResultSet)内列名的元数据和Excel内的显示列名  
 */  
public class Column {  
    private int index;  
    private String metaName;  
    private String displayName;  
    private int length;  
  
    /** 
     * 构造函数 
     *  
     * @param index 
     *            显示顺序,0 为显示的第一列 
     * @param meta 
     *            元列名,在ResultSet内的名字,必须大写 
     * @param display 
     *            显示列名,在Excel内的显示,可以是任何文字 
     * @param length 
     *            列名长度 
     */  
    public Column(int index, String meta, String display,int length) {  
        this.index = index;  
        this.metaName = meta;  
        this.displayName = display;  
        this.length = length;  
    }  
  
    /** 
     * 显示列名,在Excel内的显示,可以是任何文字 
     *  
     * @return 
     */  
    public String getDisplayName() {  
        return displayName;  
    }  
  
    /** 
     * 显示顺序,0 为显示的第一列 
     *  
     * @return 
     */  
    public int getIndex() {  
        return index;  
    }  
  
    /** 
     * 元列名,在ResultSet内的名字,必须大写 
     *  
     * @return 
     */  
    public String getMetaName() {  
        return metaName;  
    }  
  
    public void setDisplayName(String displayName) {  
        this.displayName = displayName;  
    }  
  
    public void setIndex(int index) {  
        this.index = index;  
    }  
  
    public void setMetaName(String metaName) {  
        this.metaName = metaName;  
    }  
  
    public int getLength() {  
        return length;  
    }  
  
    public void setLength(int length) {  
        this.length = length;  
    }  
}

Excel:

   /**

* 从数据库读数据,写入Excel 
     *  
     * @param os 
     *            数据流,如果是写本地文件的话,可以是FileOutputStream; 
     *            如果是写Web下载的话,可以是ServletOupputStream 
     * @param title 
     *            Excel工作簿的标题,如果不用的话,可以写null或者"" 
     * @param rs 
     *            数据结果集 
     * @param map 
     *            数据结果集对应Excel表列名映射:key对应数据结果集的列名,必须是大写; value,目前只能对应Column对象 
     * @throws Exception 
     *             方法内的父类异常有SQLException和IOException 
     */  
    public static void export(OutputStream os, String title, ResultSet rs,  
            Map map) throws Exception {    
        jxl.write.WritableWorkbook wbook = Workbook.createWorkbook(os); // 建立excel文件  
        jxl.write.WritableSheet wsheet = wbook.createSheet("第一页", 0); // sheet名称  
        jxl.write.Label wlabel = null; // Excel表格的Cell  
          
        ResultSetMetaData rsmd = rs.getMetaData();  
        int count = rsmd.getColumnCount();  
          
        // 如果有标题的话,要设置一下偏移  
        int offset = 1;  
        if (title == null || title.trim().equals(""))  
            offset = 0;  
        else {  
            // 设置标题字体  
            int numTitle = 18;// 列名字体大小  
            jxl.write.WritableFont titleFont = new jxl.write.WritableFont(  
            WritableFont.createFont("宋体"), numTitle, WritableFont.BOLD);  
            jxl.write.WritableCellFormat titleFormat = new jxl.write.WritableCellFormat(titleFont);  
            titleFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条  
            titleFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐  
            titleFormat.setAlignment(Alignment.CENTRE); // 水平对齐    
            // 添加excel标题  
            jxl.write.Label wlabel1 = new jxl.write.Label(0, 0, title, titleFormat);          
            wsheet.addCell(wlabel1);  
            wsheet.mergeCells(0, 0, count-1, 0);//合并单元格  
        }  
         // 设置列名字体  
        int charTitle = 12;// 列名字体大小  
        jxl.write.WritableFont columnFont = new jxl.write.WritableFont(  
        WritableFont.createFont("宋体"), charTitle, WritableFont.BOLD);  
  
        jxl.write.WritableCellFormat columnFormat = new jxl.write.WritableCellFormat(  
                columnFont);  
        columnFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条  
        columnFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐  
        columnFormat.setAlignment(Alignment.CENTRE); // 水平对齐  
        columnFormat.setWrap(true); // 是否换行  
        columnFormat.setBackground(Colour.GRAY_25);// 背景色暗灰-25%  
          
        // 根据原数据和map来创建Excel的列名  
          
        for (int i = 1; i <= count; i++) {  
            String name = rsmd.getColumnName(i).toUpperCase();  
            if (map.containsKey(name)) {  
                Column col = (Column) map.get(name);  
                wlabel = new jxl.write.Label(col.getIndex(), offset, col  
                        .getDisplayName(),columnFormat);  
                wsheet.setColumnView(i-1, col.getLength()); // 设置列宽,第1列  
                wsheet.addCell(wlabel);  
            }  
        }  
  
        // 设置正文字体  
        int charNormal = 10;// 标题字体大小  
        WritableFont normalFont = new WritableFont(WritableFont  
          .createFont("宋体"), charNormal);  
        jxl.write.WritableCellFormat normalFormat = new jxl.write.WritableCellFormat(  
          normalFont);  
        normalFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条  
        normalFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐  
        normalFormat.setAlignment(Alignment.CENTRE);// 水平对齐  
        normalFormat.setWrap(true); // 是否换行  
          
        // 往Excel输出数据  
        int rowIndex = 1 + offset;  
        Collection array = map.values();  
        while (rs.next()) {  
            Iterator it = array.iterator();  
            while (it.hasNext()) {  
                Column col = (Column) it.next();  
                String value = rs.getString(col.getMetaName());  
                wlabel = new jxl.write.Label(col.getIndex(), rowIndex, value,normalFormat);  
                wsheet.addCell(wlabel);  
            }  
            rowIndex++;  
        }  
        wbook.write(); // 写入文件  
        wbook.close();  
        os.flush();  
        os.close();  
    }  
}

 //JSP页面的下载如下,同样的代码也可以改成Servlet的

  <%

ConnectionPool pool = ConnectionPool.getInstance();  
 Connection conn = null;  
 ResultSet rs = null;  
 Statement stmt = null;  
   
 conn = pool.getConnection();  
 stmt = conn.createStatement();  
 rs = stmt.executeQuery("Select t.*, t.rowid from mis2_personal_weekly_job_plan t Where Rownum Between 1 And 2");  
   
 HashMap map = new HashMap();  
 map.put("ID", new Column(0, "ID", "编号"));  
 map.put("JOB_CONTENT", new Column(1, "JOB_CONTENT", "工作内容"));  
 map.put("JOB_TARGET", new Column(2, "JOB_TARGET", "工作目标"));  
   
 String fileName = "周工作计划.xls";  
 response.reset();  
  
 response.setHeader("Cache-Control", "public");  
 response.setContentType("application/ms-excel;charset=gbk");  
 //response.setContentType("application/vnd.ms-excel");  
String fn=new String(fileName.getBytes("gb2312"),"ISO8859-1");// 将文件名变成中文  
 response.addHeader("Content-Disposition","attachment;filename=" + fn);  
 Excel.export(response.getOutputStream(), "", rs, map);  
%>

 

 

补充意见:

1、需要注意在封装字段标题时需要将map的关键字置为大写,不然会找不到的,因为在excel类里将从数据库取到的字段名称进行了toUpperCase()。

2、建议使用个计数器,在map中设置value时我们只需使用var++让他自己去加去,不用去写0,1,2,3...,这样我们在修改调整字段时,就不用去改这些写死的索引号,这样更为灵活一些。

3、导出文件好像不支持中文名,如果写中文它会用字母替代,还是用英文吧。

建议写成如下这样:

HashMap map = new HashMap(); 

 

  int k=0;//计数器,这样我们在写map的value值时,就不用在Column里写0,1,2,3...了,真接用k++ 

 

  //其中map中的关键字都得是大写的,不然会找不到的,因为在excel类里用了.toUpperCase()方法 

 

   map.put("ID".toUpperCase(), new Column(k++, "ID", "编号")); 

 

   map.put("JOB_CONTENT".toUpperCase(), new Column(k++, "JOB_CONTENT", "工作内容")); 

 

   map.put("JOB_TARGET".toUpperCase(), new Column(k++, "JOB_TARGET", "工作目标"));

最后不要使用JSP的方式导出,如果用JSP写导出的话,会出现异常信息:

java.lang.IllegalStateException: 已获取输出流

出现这种异常,只需要把导出的代码写入Servlet即可以解决。

切忌!切忌!