注意:本文針對對
Struts,Value?List有一定使用經驗的開發人員,如果你不是在web環境下使用
POI,建議你直接去看
POI的教程。
1.問題由來
?????在此之前,我一直用valuelist來完成查詢并顯示結果,效果不錯。valuelist可以導出excel,csv,但是一用之下,并沒有相象的那么好,它導出的excel并不是真正的excel文件,是一個html的文本文件,這樣由于某些處理上的不完善,在我這里出現了導出的文件在打開時,表頭和下面的內容錯開,并且有多余的空列。如果對它的有關源代碼進行修改,做到正常顯示是沒問題的,但是如果客戶的需求再變一點點,比如要設置一定的格式,用它來做就不太方便了。所以我只好尋求另一種方案,最后終于找到
POI,看它的介紹很不錯,按照它的指南一試之下,也很簡單,于是決定就用它了?,F在的問題就是怎樣取得valuelist的查詢結果,并且用
POI導出到Excel中。
2.從web頁面動作時調用的Action
在我們真正用到的查詢action里只要設置好三個屬性值就可以了.
package?com.sogoodsoft.test.export.action;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?org.apache.struts.action.*;
import?com.sogoodsoft.framework.exporter.ExportBaseAction;
/**
?*?導出查詢的excel表
?*?
?*?@author?Albert?Song?
?*?@version?1.0
?*/
public?class?ExportQueryAction?extends?ExportBaseAction?{
?
?public?ActionForward?execute(ActionMapping?mapping,?ActionForm?form,
???HttpServletRequest?request,?HttpServletResponse?response)
???throws?Exception?{
??//列名,必須和applicationContext.xml中對應的sql的列名一致。
???//?順序不必一致
??
??String?colNames[]={"stu_no","stu_name"};
??//Excel表的表頭,列名對應的中文,必須和列名的順序對應
??String?titleNames[]={"學號","姓名"};
??//applicataionContext.xml中sql對應的id
??String?valueListName="testList";
//??這三項必須設置
???setColNames(colNames);
???setTitleNames(titleNames);
???set
ValueListName(valueListName);
???
???return?super.export(mapping,form,request,response);
?}
}
3.在ExportBaseAction?中取得valuelist的查詢結果
valuelist可以不用
Struts單獨使用,我這里是在
Struts中的用法,代碼大概像這樣
package?com.sogoodsoft.framework.exporter;
import?java.util.List;
import?java.util.ArrayList;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?org.apache.commons.beanutils.PropertyUtils;
import?org.apache.struts.action.*;
import?org.springframework.web.context.WebApplicationContext;
import?org.springframework.web.context.support.WebApplicationContextUtils;
import?net.mlw.vlh.*;
import?net.mlw.vlh.web.
ValueListRequestUtil;
import?com.sogoodsoft.util.BaseAction;
/**
?*?
?*?
?*?@author?Albert?Song?
?*?@version?1.0
?*/
public?class?ExportBaseAction?extends?BaseAction?{
?
?/*
??*可導出的最大記錄數
??*/
?private?final?static?int?MAX_NUM_PER_PAGE=10000;
?
?private?
ValueListHandler?get
ValueListHandler()?{
??WebApplicationContext?context?=?WebApplicationContextUtils
????.getWebApplicationContext(getServlet().getServletContext());
??return?(
ValueListHandler)?context.getBean("valueListHandler",
????
ValueListHandler.class);
?}
?public?ActionForward?export(ActionMapping?mapping,?ActionForm?form,
???HttpServletRequest?request,?HttpServletResponse?response)
???throws?Exception?{
??
??
ValueListInfo?vli=
ValueListRequestUtil.build
ValueListInfo(request);
??vli.setPagingNumberPer(MAX_NUM_PER_PAGE);
??
??
ValueList?valueList?=?get
ValueListHandler().get
ValueList(valueListName,
????vli);
??
??List?ls=new?ArrayList();
??ls.add(titleNames);
??int?colWidths[]=new?int[colNames.length];//列寬
??for(int?i=0;i<colNames.length;i++)
??{
???colWidths[i]=titleNames[i].length();
??}
??while(valueList.hasNext())
??{
???String?cols[]=new?String[colNames.length];
???
???Object?bean=valueList.next();
???
???try?{
????for(int?i=0;i<colNames.length;i++)
????{
?????Object?value=PropertyUtils.getProperty(bean,colNames[i]);//關鍵點
?????if(value==null)
??????value="-";
?????cols[i]=(String)value;
?????if(colWidths[i]<cols[i].length())
?????{
??????colWidths[i]=cols[i].length();
?????}
????}
????ls.add(cols);
???}?catch?(Exception?e)?{
????
?????System.out.println("獲取valueList的屬性值時發生錯誤");
?????break;
???}
??}
??
??ExcelExporter.export(ls,response,colWidths);
??
??return?null;
?}
?
?/**
??*?@param?colNames返回的記錄集的列名.
??*/
?public?void?setColNames(String[]?colNames)?{
??this.colNames?=?colNames;
?}
?/**
??*?@param?titleNames?表頭漢字的字符串數組.
??*/
?public?void?setTitleNames(String[]?titleNames)?{
??this.titleNames?=?titleNames;
?}
?/**
??*?@param?valueListName?查詢用的value?list的sql的entry?key?.
??*/
?public?void?set
ValueListName(String?valueListName)?{
??this.valueListName?=?valueListName;
?}
}
4.真正導出excel的類
這里只是簡單的將傳入的字符串數組的List導出
package?com.sogoodsoft.framework.exporter;
import?java.util.List;
import?java.io.*;
import?javax.servlet.http.HttpServletResponse;
import?org.apache.poi.hssf.usermodel.*;
/**
?*?@author?Albert?Song
?*?
?*?導出數據到Excel文件中
?*??
?*/
public?class?ExcelExporter?{
?public?static?void?export(List?exportStringArrayList,
???HttpServletResponse?response)?throws?Exception?{
???export(exportStringArrayList,response,null);
?}
?public?static?void?export(List?exportStringArrayList,
???HttpServletResponse?response,int?colWidths[])?throws?Exception?{
???//僅僅為了防止系統拋出空指針異常,這應該算
POI的一個bug吧,這個問題花了我半天時間,現在還沒搞明白
???//總之設置之后就可以用了:)
???System.setProperty("org.apache.poi.util.
POILogger","org.apache.poi.util.
POILogger");
???List?ls=exportStringArrayList;
???
???HSSFWorkbook?wb?=?new?HSSFWorkbook();
???HSSFSheet?sheet?=?wb.createSheet("sheet1");
???
???if(colWidths!=null)
???{
????for(int?i=0;i<colWidths.length;i++)
????{
?????sheet.setColumnWidth((short)i,(short)(colWidths[i]*600));
????}
???}
???
???for(int?i=0;i<ls.size();i++)
?????{
????HSSFRow?row?=?sheet.createRow(i);
??????String[]?strs=(String[])ls.get(i);
??????for(int?j=0;j<strs.length;j++)
??????{
???????HSSFCell?cell?=?row.createCell((short)?j);
???????cell.setEncoding(HSSFCell.ENCODING_UTF_16);
???????cell.setCellValue(strs[j]);
???????
??????}
?????}
???//??Get?output?stream
???response.setContentType("application/x-msdownload");
???response.setHeader("content-disposition",
?????"attachment;?filename=dataexport.xls");
???OutputStream?os?=?response.getOutputStream();
???wb.write(os);
???os.close();
?}
}
5.小結
這不能算是文章,只能算是一個拋磚引玉的筆記,本人學習
POI也才一天半,貼出來的目的是為了感謝同樣貼出文章的同仁們,他們的無私奉獻給了我不少啟示,節省了我的時間,因此我覺得花一點時間將我的經驗和大家分享是值得的。