编辑EXCEL一直用POI,忽然看见一个JExcel的文档,贴过来,以便后用
转自:http://www.blogjava.net/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}
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 然后下载的方法,如果以后遇到,一定继续完善。
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}
请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处: http://www.blogjava.net/rosen