Posted on 2007-04-07 17:15
它山の石 閱讀(718)
評論(0) 編輯 收藏
編輯EXCEL一直用POI,忽然看見一個JExcel的文檔,貼過來,以便后用
轉自:http://m.tkk7.com/rosen
最近遇到點讀取 Excel 數據的問題,于是花了點時間找開源工具。
要解析 Excel,首當其沖的是上傳文件,以前在項目里我們用 SmartUpload 進行上傳,不過這個項目似乎已經停止開發了,于是在這里我使用 Apache Commons FileUpload,可以在 http://jakarta.apache.org/commons/fileupload 找到。目前該項目的最新版本是 1.1.1,網上有大量的范例程序,不過后來用的時候發現大部分方法在新版本中都不推薦使用了,于是好好讀了一回 API 和官方范例。
先來看看如何上傳文件,Servlet 很簡單,在這里我限制了最大上傳量為 1M,且直接讀進內存中,不進行磁盤臨時文件緩存。
1
import java.io.IOException;
2
import java.io.PrintWriter;
3
import java.io.File;
4
import java.net.URI;
5
import java.net.URL;
6
7
import javax.servlet.ServletException;
8
import javax.servlet.http.HttpServlet;
9
import javax.servlet.http.HttpServletRequest;
10
import javax.servlet.http.HttpServletResponse;
11
12
import java.util.List;
13
14
import org.apache.commons.fileupload.RequestContext;
15
import org.apache.commons.fileupload.servlet.ServletRequestContext;
16
import org.apache.commons.fileupload.servlet.ServletFileUpload;
17
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
18
import org.apache.commons.fileupload.FileItem;
19
20
public class UploadServlet extends HttpServlet
{
21
22
/** *//**
23
* Constructor of the object.
24
*/
25
public UploadServlet()
{
26
super ();
27
}
28
29
/** *//**
30
* Destruction of the servlet.
31
*/
32
public void destroy()
{
33
super .destroy();
34
}
35
36
public void doGet(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException
{
38
}
39
40
/** *//**
41
* 上傳文件
42
*
43
* @param request
44
* @param response
45
* @throws ServletException
46
* @throws IOException
47
*/
48
public void doPost(HttpServletRequest request, HttpServletResponse response)
49
throws ServletException, IOException
{
50
response.setContentType( " text/html " );
51
response.setCharacterEncoding( " gbk " );
52
PrintWriter out = response.getWriter();
53
out.println( " <html> " );
54
out.println( " <head><title>提示</title></head> " );
55
out.println( " <body> " );
56
// 不用獲取 URL 對象也行,直接用 getServletContext().getRealPath("/") 代替。
57
URL url = getServletContext().getResource( " / " );
58
// 從 HTTP servlet 獲取 fileupload 組件需要的內容
59
RequestContext requestContext = new ServletRequestContext(request);
60
// 判斷是否包含 multipart 內容
61
if (ServletFileUpload.isMultipartContent(requestContext))
{
62
// 創建基于磁盤的文件工廠
63
DiskFileItemFactory factory = new DiskFileItemFactory();
64
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節約內存。默認為 1024 字節
65
factory.setSizeThreshold( 1024 * 1024 );
66
// 創建上傳處理器,可以處理從單個 HTML 上傳的多個上傳文件。
67
ServletFileUpload upload = new ServletFileUpload(factory);
68
// 最大允許上傳的文件大小
69
upload.setSizeMax( 1024 * 1024 );
70
// 處理上傳
71
List items = null ;
72
try
{
73
items = upload.parseRequest(requestContext);
74
// 由于提交了表單字段信息,需要進行循環區分。
75
for ( int i = 0 ; i < items.size(); i ++ )
{
76
FileItem fi = (FileItem) items.get(i);
77
// 如果不是表單內容,取出 multipart。
78
if ( ! fi.isFormField())
{
79
// 上傳文件路徑和文件、擴展名。
80
String sourcePath = fi.getName();
81
String[] sourcePaths = sourcePath.split( " \\\\ " );
82
// 獲取真實文件名
83
String fileName = sourcePaths[sourcePaths.length - 1 ];
84
// 創建一個待寫文件
85
File uploadedFile = new File( new URI(url.toString() + fileName));
86
// 寫入
87
fi.write(uploadedFile);
88
out.println(fileName + " 上傳成功。 " );
89
}
90
}
91
} catch (Exception e)
{
92
out.println( " 上傳失敗,請檢查上傳文件大小是否超過1兆,并保證在上傳時該文件沒有被其他程序占用。 " );
93
out.println( " <br>原因: " + e.toString());
94
e.printStackTrace();
95
}
96
}
97
out.println( " </body> " );
98
out.println( " </html> " );
99
out.flush();
100
out.close();
101
}
102
103
/** *//**
104
* Initialization of the servlet.
105
*
106
* @throws ServletException
107
*/
108
public void init() throws ServletException
{
109
}
110
}
上面的程序示范了如何上傳文件到服務器,本文的主要目的不光是上傳,還要進行 Excel 解析,抽取有用的內容。開源的 Excel 解析器很多,在此我選擇了 JExcelApi,可以在
http://jexcelapi.sourceforge.net 找到,據說是韓國人開發的,最新版本是 2.6.2。為什么沒有選 POI,原因也是因為它 N 久沒有更新了。我總是喜歡最新的東東,比如 Adobe 的 PDF Reader,硬是下載了 8.0,結果感覺還沒有 6.0 好用。:(
以下程序修改直上傳,做了部分調整,取消了文件儲存,直接通過讀取輸入流進行解析,并假設約定的 Excel 文件有五列 N 行,第一行為標題信息。
1
import java.io.IOException;
2
import java.io.PrintWriter;
3
4
import javax.servlet.ServletException;
5
import javax.servlet.http.HttpServlet;
6
import javax.servlet.http.HttpServletRequest;
7
import javax.servlet.http.HttpServletResponse;
8
9
import java.util.List;
10
11
import org.apache.commons.fileupload.RequestContext;
12
import org.apache.commons.fileupload.servlet.ServletRequestContext;
13
import org.apache.commons.fileupload.servlet.ServletFileUpload;
14
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
15
import org.apache.commons.fileupload.FileItem;
16
17
import jxl.Workbook;
18
import jxl.Sheet;
19
import jxl.Cell;
20
21
public class UploadServlet extends HttpServlet
{
22
23
/** *//**
24
* Constructor of the object.
25
*/
26
public UploadServlet()
{
27
super ();
28
}
29
30
/** *//**
31
* Destruction of the servlet.
32
*/
33
public void destroy()
{
34
super .destroy();
35
}
36
37
public void doGet(HttpServletRequest request, HttpServletResponse response)
38
throws ServletException, IOException
{
39
}
40
41
/** *//**
42
* 上傳文件
43
*
44
* @param request
45
* @param response
46
* @throws ServletException
47
* @throws IOException
48
*/
49
public void doPost(HttpServletRequest request, HttpServletResponse response)
50
throws ServletException, IOException
{
51
response.setContentType( " text/html " );
52
response.setCharacterEncoding( " gbk " );
53
PrintWriter out = response.getWriter();
54
out.println( " <html> " );
55
out.println( " <head><title>提示</title></head> " );
56
out.println( " <body> " );
57
// 聲明文件域
58
FileItem fileItem = null ;
59
// 從 HTTP servlet 獲取 fileupload 組件需要的內容
60
RequestContext requestContext = new ServletRequestContext(request);
61
// 判斷是否包含 multipart 內容,如果不包含,則不進行任何處理。
62
if (ServletFileUpload.isMultipartContent(requestContext))
{
63
// 創建基于磁盤的文件工廠
64
DiskFileItemFactory factory = new DiskFileItemFactory();
65
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節約內存。默認為 1024 字節
66
factory.setSizeThreshold( 1024 * 1024 );
67
// 創建上傳處理器,可以處理從單個 HTML 上傳的多個上傳文件。
68
ServletFileUpload upload = new ServletFileUpload(factory);
69
// 最大允許上傳的文件大小
70
upload.setSizeMax( 1024 * 1024 );
71
try
{
72
// 處理上傳
73
List items = null ;
74
items = upload.parseRequest(requestContext);
75
// 由于提交了表單字段信息,需要進行循環區分。
76
for ( int i = 0 ; i < items.size(); i ++ )
{
77
FileItem fi = (FileItem) items.get(i);
78
// 如果不是表單內容,取出 multipart。
79
if ( ! fi.isFormField())
{
80
fileItem = fi;
81
// 一次只上傳單個文件
82
break ;
83
}
84
}
85
out.println(parseExcel(fileItem));
86
} catch (Exception e)
{
87
out.println( " 上傳失敗!請檢查上傳的文件是否為excel格式、信息是否完整完整、且大小是否超過1兆。 " );
88
out.println( " <br>原因: " + e.toString());
89
e.printStackTrace();
90
}
91
}
92
out.println( " </body> " );
93
out.println( " </html> " );
94
out.flush();
95
out.close();
96
}
97
98
/** *//**
99
* 分析excel文件
100
*
101
* @param FileItem fi 文件域
102
* @return String
103
* @throws Exception
104
*/
105
private String parseExcel(FileItem fi) throws Exception
{
106
// 聲明 Workbook
107
Workbook workbook = null ;
108
try
{
109
workbook = Workbook.getWorkbook(fi.getInputStream());
110
Sheet sheet = workbook.getSheet( 0 );
111
// 總行數
112
int count = sheet.getRows();
113
// 取出標題
114
String a1 = sheet.getCell( 0 , 0 ).getContents();
115
String a2 = sheet.getCell( 1 , 0 ).getContents();
116
String a3 = sheet.getCell( 2 , 0 ).getContents();
117
String a4 = sheet.getCell( 3 , 0 ).getContents();
118
String a5 = sheet.getCell( 4 , 0 ).getContents();
119
// 取出內容
120
for ( int i = 1 ;i < count;i ++ )
{
121
Cell[] cells = sheet.getRow(i);
122
System.out.println(cells[ 0 ].getContents()
123
+ cells[ 1 ].getContents() + cells[ 2 ].getContents()
124
+ cells[ 3 ].getContents() + cells[ 4 ].getContents());
125
}
126
return " 上傳成功。 " ;
127
} catch (Exception e)
{
128
throw e;
129
} finally
{
130
if (workbook != null )
{
131
workbook.close();
132
}
133
}
134
}
135
136
/** *//**
137
* Initialization of the servlet.
138
*
139
* @throws ServletException
140
*/
141
public void init() throws ServletException
{
142
}
143
}
JExcelApi 用起來很簡單,而且還可以根據 Excel 中數據類型轉換成 Java 數據類型,比如 int、double,具體信息可以參考它的開發指南。當然,本范例還提供現構造 Excel 然后下載的方法,如果以后遇到,一定繼續完善。
請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處:http://m.tkk7.com/rosen