編輯EXCEL一直用POI,忽然看見一個JExcel的文檔,貼過來,以便后用
轉(zhuǎn)自:http://www.aygfsteel.com/rosen
最近遇到點讀取 Excel 數(shù)據(jù)的問題,于是花了點時間找開源工具。
要解析 Excel,首當其沖的是上傳文件,以前在項目里我們用 SmartUpload 進行上傳,不過這個項目似乎已經(jīng)停止開發(fā)了,于是在這里我使用 Apache Commons FileUpload,可以在 http://jakarta.apache.org/commons/fileupload 找到。目前該項目的最新版本是 1.1.1,網(wǎng)上有大量的范例程序,不過后來用的時候發(fā)現(xiàn)大部分方法在新版本中都不推薦使用了,于是好好讀了一回 API 和官方范例。
先來看看如何上傳文件,Servlet 很簡單,在這里我限制了最大上傳量為 1M,且直接讀進內(nèi)存中,不進行磁盤臨時文件緩存。
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 組件需要的內(nèi)容
59
RequestContext requestContext = new ServletRequestContext(request);
60
// 判斷是否包含 multipart 內(nèi)容
61
if (ServletFileUpload.isMultipartContent(requestContext))
{
62
// 創(chuàng)建基于磁盤的文件工廠
63
DiskFileItemFactory factory = new DiskFileItemFactory();
64
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節(jié)約內(nèi)存。默認為 1024 字節(jié)
65
factory.setSizeThreshold( 1024 * 1024 );
66
// 創(chuàng)建上傳處理器,可以處理從單個 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
// 由于提交了表單字段信息,需要進行循環(huán)區(qū)分。
75
for ( int i = 0 ; i < items.size(); i ++ )
{
76
FileItem fi = (FileItem) items.get(i);
77
// 如果不是表單內(nèi)容,取出 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
// 創(chuàng)建一個待寫文件
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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20



21

22


23

24

25



26

27

28

29


30

31

32



33

34

35

36

37



38

39

40


41

42

43

44

45

46

47

48

49



50

51

52

53

54

55

56

57

58

59

60

61



62

63

64

65

66

67

68

69

70

71

72



73

74

75



76

77

78



79

80

81

82

83

84

85

86

87

88

89

90

91



92

93

94

95

96

97

98

99

100

101

102

103


104

105

106

107

108



109

110

上面的程序示范了如何上傳文件到服務器,本文的主要目的不光是上傳,還要進行 Excel 解析,抽取有用的內(nèi)容。開源的 Excel 解析器很多,在此我選擇了 JExcelApi,可以在 http://jexcelapi.sourceforge.net 找到,據(jù)說是韓國人開發(fā)的,最新版本是 2.6.2。為什么沒有選 POI,原因也是因為它 N 久沒有更新了。我總是喜歡最新的東東,比如 Adobe 的 PDF Reader,硬是下載了 8.0,結(jié)果感覺還沒有 6.0 好用。:(
以下程序修改直上傳,做了部分調(diào)整,取消了文件儲存,直接通過讀取輸入流進行解析,并假設約定的 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 組件需要的內(nèi)容
60
RequestContext requestContext = new ServletRequestContext(request);
61
// 判斷是否包含 multipart 內(nèi)容,如果不包含,則不進行任何處理。
62
if (ServletFileUpload.isMultipartContent(requestContext))
{
63
// 創(chuàng)建基于磁盤的文件工廠
64
DiskFileItemFactory factory = new DiskFileItemFactory();
65
// 設置直接存儲文件的極限大小,一旦超過則寫入臨時文件以節(jié)約內(nèi)存。默認為 1024 字節(jié)
66
factory.setSizeThreshold( 1024 * 1024 );
67
// 創(chuàng)建上傳處理器,可以處理從單個 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
// 由于提交了表單字段信息,需要進行循環(huán)區(qū)分。
76
for ( int i = 0 ; i < items.size(); i ++ )
{
77
FileItem fi = (FileItem) items.get(i);
78
// 如果不是表單內(nèi)容,取出 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
// 總行數(shù)
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
// 取出內(nèi)容
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 用起來很簡單,而且還可以根據(jù) Excel 中數(shù)據(jù)類型轉(zhuǎn)換成 Java 數(shù)據(jù)類型,比如 int、double,具體信息可以參考它的開發(fā)指南。當然,本范例還提供現(xiàn)構(gòu)造 Excel 然后下載的方法,如果以后遇到,一定繼續(xù)完善。
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21



22

23


24

25

26



27

28

29

30


31

32

33



34

35

36

37

38



39

40

41


42

43

44

45

46

47

48

49

50



51

52

53

54

55

56

57

58

59

60

61

62



63

64

65

66

67

68

69

70

71



72

73

74

75

76



77

78

79



80

81

82

83

84

85

86



87

88

89

90

91

92

93

94

95

96

97

98


99

100

101

102

103

104

105



106

107

108



109

110

111

112

113

114

115

116

117

118

119

120



121

122

123

124

125

126

127



128

129



130



131

132

133

134

135

136


137

138

139

140

141



142

143

請注意!引用、轉(zhuǎn)貼本文應注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen