
<!--Google 468*60橫幅廣告開始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as"; google_ad_type = "image"; //2007-07-26: CSDN google_ad_channel = "6063905817"; google_color_border = "6699CC"; google_color_bg = "E6E6E6"; google_color_link = "FFFFFF"; google_color_text = "333333"; google_color_url = "AECCEB"; google_ui_features = "rc:6"; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--Google 468*60橫幅廣告結束-->
本文轉載自: http://www.blogjava.net/rosen
最近遇到點讀取 Excel 數據的問題,于是花了點時間找開源工具。
要解析 Excel,首當其沖的是上傳文件,以前在項目里我們用 SmartUpload 進行上傳,不過這個項目似乎已經停止開發了,于是在這里我使用 Apache Commons FileUpload,可以在
http://jakarta.apache.org/commons/fileupload
找到。目前該項目的最新版本是 1.1.1,網上有大量的范例程序,不過后來用的時候發現大部分方法在新版本中都不推薦使用了,于是好好讀了一回 API 和官方范例。
先來看看如何上傳文件,Servlet 很簡單,在這里我限制了最大上傳量為 1M,且直接讀進內存中,不進行磁盤臨時文件緩存。
import java.io.PrintWriter;
import java.io.File;
import java.net.URI;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.FileItem;
public class UploadServlet extends HttpServlet{
/**
*Constructoroftheobject.
*/
public UploadServlet(){
super ();
}
/**
*Destructionoftheservlet.
*/
public void destroy(){
super .destroy();
}
public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
}
/**
*上傳文件
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void doPost(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
response.setContentType( " text/html " );
response.setCharacterEncoding( " gbk " );
PrintWriterout = response.getWriter();
out.println( " <html> " );
out.println( " <head><title>提示</title></head> " );
out.println( " <body> " );
// 不用獲取URL對象也行,直接用getServletContext().getRealPath("/")代替。
URLurl = getServletContext().getResource( " / " );
// 從HTTPservlet獲取fileupload組件需要的內容
RequestContextrequestContext = new ServletRequestContext(request);
// 判斷是否包含multipart內容
if (ServletFileUpload.isMultipartContent(requestContext)){
// 創建基于磁盤的文件工廠
DiskFileItemFactoryfactory = new DiskFileItemFactory();
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節約內存。默認為1024字節
factory.setSizeThreshold( 1024 * 1024 );
// 創建上傳處理器,可以處理從單個HTML上傳的多個上傳文件。
ServletFileUploadupload = new ServletFileUpload(factory);
// 最大允許上傳的文件大小
upload.setSizeMax( 1024 * 1024 );
// 處理上傳
Listitems = null ;
try {
items = upload.parseRequest(requestContext);
// 由于提交了表單字段信息,需要進行循環區分。
for ( int i = 0 ;i < items.size();i ++ ){
FileItemfi = (FileItem)items.get(i);
// 如果不是表單內容,取出multipart。
if ( ! fi.isFormField()){
// 上傳文件路徑和文件、擴展名。
StringsourcePath = fi.getName();
String[]sourcePaths = sourcePath.split( " //// " );
// 獲取真實文件名
StringfileName = sourcePaths[sourcePaths.length - 1 ];
// 創建一個待寫文件
FileuploadedFile = new File( new URI(url.toString() + fileName));
// 寫入
fi.write(uploadedFile);
out.println(fileName + " 上傳成功。 " );
}
}
} catch (Exceptione){
out.println( " 上傳失敗,請檢查上傳文件大小是否超過1兆,并保證在上傳時該文件沒有被其他程序占用。 " );
out.println( " <br>原因: " + e.toString());
e.printStackTrace();
}
}
out.println( " </body> " );
out.println( " </html> " );
out.flush();
out.close();
}
/**
*Initializationoftheservlet.
*
* @throws ServletException
*/
public void init() throws ServletException{
}
}
上面的程序示范了如何上傳文件到服務器,本文的主要目的不光是上傳,還要進行 Excel 解析,抽取有用的內容。開源的 Excel 解析器很多,在此我選擇了 JExcelApi,可以在
http://jexcelapi.sourceforge.net
找到,據說是韓國人開發的,最新版本是 2.6.2。為什么沒有選 POI,原因也是因為它 N 久沒有更新了。我總是喜歡最新的東東,比如 Adobe 的 PDF Reader,硬是下載了 8.0,結果感覺還沒有 6.0 好用。:(
以下程序修改直上傳,做了部分調整,取消了文件儲存,直接通過讀取輸入流進行解析,并假設約定的 Excel 文件有五列 N 行,第一行為標題信息。
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.FileItem;
import jxl.Workbook;
import jxl.Sheet;
import jxl.Cell;
public class UploadServlet extends HttpServlet{
/**
*Constructoroftheobject.
*/
public UploadServlet(){
super ();
}
/**
*Destructionoftheservlet.
*/
public void destroy(){
super .destroy();
}
public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
}
/**
*上傳文件
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void doPost(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
response.setContentType( " text/html " );
response.setCharacterEncoding( " gbk " );
PrintWriterout = response.getWriter();
out.println( " <html> " );
out.println( " <head><title>提示</title></head> " );
out.println( " <body> " );
// 聲明文件域
FileItemfileItem = null ;
// 從HTTPservlet獲取fileupload組件需要的內容
RequestContextrequestContext = new ServletRequestContext(request);
// 判斷是否包含multipart內容,如果不包含,則不進行任何處理。
if (ServletFileUpload.isMultipartContent(requestContext)){
// 創建基于磁盤的文件工廠
DiskFileItemFactoryfactory = new DiskFileItemFactory();
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節約內存。默認為1024字節
factory.setSizeThreshold( 1024 * 1024 );
// 創建上傳處理器,可以處理從單個HTML上傳的多個上傳文件。
ServletFileUploadupload = new ServletFileUpload(factory);
// 最大允許上傳的文件大小
upload.setSizeMax( 1024 * 1024 );
try {
// 處理上傳
Listitems = null ;
items = upload.parseRequest(requestContext);
// 由于提交了表單字段信息,需要進行循環區分。
for ( int i = 0 ;i < items.size();i ++ ){
FileItemfi = (FileItem)items.get(i);
// 如果不是表單內容,取出multipart。
if ( ! fi.isFormField()){
fileItem = fi;
// 一次只上傳單個文件
break ;
}
}
out.println(parseExcel(fileItem));
} catch (Exceptione){
out.println( " 上傳失敗!請檢查上傳的文件是否為excel格式、信息是否完整完整、且大小是否超過1兆。 " );
out.println( " <br>原因: " + e.toString());
e.printStackTrace();
}
}
out.println( " </body> " );
out.println( " </html> " );
out.flush();
out.close();
}
/**
*分析excel文件
*
* @param FileItemfi文件域
* @return String
* @throws Exception
*/
private StringparseExcel(FileItemfi) throws Exception{
// 聲明Workbook
Workbookworkbook = null ;
try {
workbook = Workbook.getWorkbook(fi.getInputStream());
Sheetsheet = workbook.getSheet( 0 );
// 總行數
int count = sheet.getRows();
// 取出標題
Stringa1 = sheet.getCell( 0 , 0 ).getContents();
Stringa2 = sheet.getCell( 1 , 0 ).getContents();
Stringa3 = sheet.getCell( 2 , 0 ).getContents();
Stringa4 = sheet.getCell( 3 , 0 ).getContents();
Stringa5 = sheet.getCell( 4 , 0 ).getContents();
// 取出內容
for ( int i = 1 ;i < count;i ++ ){
Cell[]cells = sheet.getRow(i);
System.out.println(cells[ 0 ].getContents()
+ cells[ 1 ].getContents() + cells[ 2 ].getContents()
+ cells[ 3 ].getContents() + cells[ 4 ].getContents());
}
return " 上傳成功。 " ;
} catch (Exceptione){
throw e;
} finally {
if (workbook != null ){
workbook.close();
}
}
}
/**
*Initializationoftheservlet.
*
* @throws ServletException
*/
public void init() throws ServletException{
}
}
JExcelApi 用起來很簡單,而且還可以根據 Excel 中數據類型轉換成 Java 數據類型,比如 int、double,具體信息可以參考它的開發指南。當然,本范例還提供現構造 Excel 然后下載的方法,如果以后遇到,一定繼續完善。
------------------------------------------------------------------------------------------------
關于生成 excel 和下載,一月份的文章還留了個尾巴,今天把它補充上去。2007-04-22 by rosen jiang
代碼如下,放在 servlet 中,io 異常我沒捕獲,直接由 get or post 方法拋出,當然,如果更嚴謹點可以放在 finally 里關閉。
response.setContentType( " application/x-msdownload;charset=GBK " );
Stringfilename = new String( " 供應商報價清單.xls " .getBytes( " GBK " ), " ISO_8859_1 " );
response.setHeader( " Content-Disposition " , " attachment;filename= " + filename);
// 虛擬數據
StringmaterialName = " 馬桶 " ; // 材料名
Stringsize = " 200×300 " ; // 規格
Stringunit = " 臺 " ; // 單位
Stringqty = " 2 " ; // 數量
Stringband = " 不知道牌子 " ; // 材料品牌
Stringcompany = " 成都某廠 " ; // 廠家名
Stringmemo = " 質量可靠 " ; // 備注
Stringprice = " 20.30 " ; // 價格
StringrepDate = " 2007-04-11 " ; // 報價時間
List < String[] > list = new ArrayList < String[] > ();
for ( int i = 10 ;i > 0 ;i -- ){
String[]outPut = {materialName,size,unit,qty + i,band,company,memo,price,repDate};
list.add(outPut);
}
// 輸出流
ByteArrayOutputStreambaos = new ByteArrayOutputStream();
// 構造工作區
WritableWorkbookworkbook = Workbook.createWorkbook(baos);
// 構造sheet
WritableSheetsheet = workbook.createSheet( " 報價清單 " , 0 );
// 構造粗標題字體
WritableFontblodFont = new WritableFont(WritableFont.TAHOMA, 10 ,WritableFont.BOLD, false );
WritableCellFormatblodFormat = new WritableCellFormat(blodFont);
Labellabel = null ;
try {
// 標題行
label = new Label( 0 , 0 , " 材料名 " ,blodFormat);
sheet.addCell(label);
label = new Label( 1 , 0 , " 規格 " ,blodFormat);
sheet.addCell(label);
label = new Label( 2 , 0 , " 單位 " ,blodFormat);
sheet.addCell(label);
label = new Label( 3 , 0 , " 數量 " ,blodFormat);
sheet.addCell(label);
label = new Label( 4 , 0 , " 材料品牌 " ,blodFormat);
sheet.addCell(label);
label = new Label( 5 , 0 , " 廠家名 " ,blodFormat);
sheet.addCell(label);
label = new Label( 6 , 0 , " 備注 " ,blodFormat);
sheet.addCell(label);
label = new Label( 7 , 0 , " 價格 " ,blodFormat);
sheet.addCell(label);
label = new Label( 8 , 0 , " 報價時間 " ,blodFormat);
sheet.addCell(label);
// 輸出業務數據
for ( int i = 1 ;i <= list.size();i ++ ){
String[]outPut = list.get(i - 1 );
label = new Label( 0 ,i,outPut[ 0 ]);
sheet.addCell(label);
label = new Label( 1 ,i,outPut[ 1 ]);
sheet.addCell(label);
label = new Label( 2 ,i,outPut[ 2 ]);
sheet.addCell(label);
label = new Label( 3 ,i,outPut[ 3 ]);
sheet.addCell(label);
label = new Label( 4 ,i,outPut[ 4 ]);
sheet.addCell(label);
label = new Label( 5 ,i,outPut[ 5 ]);
sheet.addCell(label);
label = new Label( 6 ,i,outPut[ 6 ]);
sheet.addCell(label);
label = new Label( 7 ,i,outPut[ 7 ]);
sheet.addCell(label);
label = new Label( 8 ,i,repDate);
sheet.addCell(label);
}
// 寫入文件
workbook.write();
workbook.close();
// 向瀏覽器返回文件流
OutputStreamos = response.getOutputStream();
os.write(baos.toByteArray());
os.flush();
os.close();
baos.close();
} catch (RowsExceededExceptione){
e.printStackTrace();
} catch (WriteExceptione){
e.printStackTrace();
}
}
生成 excel 的樣子是這樣的:

請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處: http://www.blogjava.net/rosen
<!--新Google 468*60橫幅廣告開始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; /* 468x60, 創建于 08-8-6 */ google_ad_slot = "7368701459"; google_ad_width = 468; google_ad_height = 60; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--新Google 468*60橫幅廣告結束-->
<!--新Google 468x15 橫鏈接單元開始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; /* 468x15 橫鏈接單元 */ google_ad_slot = "5785741422"; google_ad_width = 468; google_ad_height = 15; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--新Google 468x15 橫鏈接單元結束-->
<!-- Google Reader shared發布代碼開始 --><script type="text/javascript" src="http://www.google.com/reader/ui/publisher.js"></script><script type="text/javascript" src="http://www.google.com/reader/public/javascript/user/00697638153916680411/state/com.google/broadcast?n=5&callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22%5Cu8FD9%5Cu4E9B%5Cu6587%5Cu7AE0%5Cu4E5F%5Cu503C%5Cu5F97%5Cu4E00%5Cu770B%22%2Cs%3A%22false%22%7D)%3Bnew%20GRC"></script><!-- Google Reader shared發布代碼結束 -->
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
