将选定的数据导入到Excel中,在IE系列里面挺简单的:用他们自带的ActiveXObject控件即可。火狐系列因为不支持这个控件所以不能用这种方法。在网络上搜了好一阵子都没有找到火狐浏览器下在客户端导出数据到Excel的好办法,最后只好用JXL的java后台使用下载的方式来模拟导出数据了。废话不多说,言归正传。
1、需要用到的jar包:
已经以附件的形式上传。其中以“commons”打头的JAR包用来实现文件的上传下载,“jxl.jar”是JXL核心JAR包,“json-lib-2.1.jar”是JSON的JAR包。
ezmorph-1.0.6.jar:EZMorph是一个简单的java类库用于将一种对象转换成另外一种对象。EZMorph原先是Json-lib项目中的转换器。EZMorph支持原始数据类型(Primitive),对象(Object),多维数组转换与DynaBeans的转换。兼容JDK1.3.1,整个类库大小只有76K左右。
(参考:http://baike.baidu.com/link?url=emmqr6B6hphRKk3xbW98PSgx72vVzsSPNnZ_FQdS2qzTM2gCPvFfyEMplHq-MigccMsFkedlY1cYpopBfPxBFK)
2、页面布局:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>将数据导出到Excel中</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="js/jquery-1.4.2.js"></script>
<style type="text/css">
.tabFirstTr{background:#ededed}
</style>
</head>
<body>
<body>
<table border="1" id="toExcel">
<tr class="tabFirstTr">
<td>序号</td><td><input type="checkbox" onclick="selectAllOrNot(this);"/></td><td>姓名</td><td>性别</td><td>年龄</td><td>所属部门</td><td>详细岗位</td>
</tr>
<tr>
<td>1</td><td><input type="checkbox" /></td><td>张三</td><td>男</td><td>10</td><td>部门1</td><td>部门主任</td>
</tr>
<tr>
<td>2</td><td><input type="checkbox" /><td>李四</td><td>男</td><td>20</td><td>部门2</td><td>副主任</td>
</tr>
<tr>
<td>3</td><td><input type="checkbox" /><td>王五</td><td>男</td><td>30</td><td>部门3</td><td>客户经理</td>
</tr>
<tr>
<td>4</td><td><input type="checkbox" /><td>赵六</td><td>男</td><td>40</td><td>部门4</td><td>客户经理</td>
</tr>
<tr>
<td>5</td><td><input type="checkbox" /><td>杨七</td><td>男</td><td>50</td><td>部门5</td><td>客户经理</td>
</tr>
</table>
<br /><br />
<input type="button" onclick="toExcel()" value="导出到Excel" />
</body>
</html>
3、用到的JS:
<script type="text/javascript">
//导出为Excel
function toExcel(){
var $head = $("#toExcel>tbody>tr.tabFirstTr").children("td:visible");
var $body = $("#toExcel>tbody>tr:not(.tabFirstTr)>td :checkbox:checked").parent().parent("tr");
var cells = parseInt($head.length);//列
var rows = parseInt($body.length);//行
//alert(cells+" "+(rows));
if(rows>0){
try {
var oXL = new ActiveXObject("Excel.Application"); //创建excel应用程序对象
}catch(e) {//可能不是IE,也可能是IE没有启用ActiveX控件
if(!+"\v1"){//IE不支持垂直制表符
alert( "要将该表导出到Excel,您必须安装Excel电子表格软件,同时浏览器须使用“ActiveX 控件”,您的浏览器须允许执行控件。");
return "";
}else{//说明是其他系列,那么调用Java方法生成Excel文件让客户下载
exportToExcel($head,$body);
return;
}
}
var oWB = oXL.Workbooks.Add(); //创建工作簿
var oSheet = oWB.ActiveSheet; //获取当前活动的工作簿
//标题行
$head.each(function(i){
oSheet.Cells(1,i+1).Value = $(this).text();//设置标题的内容
oSheet.Cells(1,i+1).Font.Bold=true;//加粗
oSheet.Cells(1,i+1).Font.Size=14;//设置字体大小
});
//内容行
var tdText=null;
var tdArray=null;
$body.each(function(m){
$(this).children("td:visible").each(function(n){//td的内容
tdText = $(this).text();
//处理"当数据用,号隔开,倒入到Excel时,Excel自动用科学技术发表示"的情况
tdArray= tdText.split(",");
if(tdArray.length==1){
tdArray= tdText.split(",");
}
if(!isempty(tdText) && tdArray.length>1 && (jQuery.trim(tdArray[0]).length==jQuery.trim(tdArray[1]).length)){
tdText = replaceAll(tdText,",",";");
tdText = replaceAll(tdText,",",";");
}
oSheet.Cells(m+2,n+1).Value = tdText;//赋值
oSheet.Cells(m+2,n+1).Font.Size=12;//设置字体大小
});
});
oXL.Visible = true; //设置Excel的属性
oXL.UserControl = true;
oSheet = null;
oWB = null;
oXL = null;
}else{
alert("请选择要导出的数据!");
}
return ;
}
/**
* 为非IE系列的浏览器添加导出为Excel的功能
* @param @head:table的第一个TR
* @param @body:table的其他tr
*/
function exportToExcel(head,body){
var $head = $(head);
var $body = $(body);
var head = "";//标题的值
var body = "";//内容
//标题行
$head.each(function(i){
head += ","+$(this).text();//设置标题的内容
});
head=head.substring(1);
//alert(head);
$body.each(function(m){
var body2="";
$(this).children("td:visible").each(function(n){//td的内容
tdText = $(this).text();
//处理"当数据用,号隔开,倒入到Excel时,Excel自动用科学技术发表示"的情况
tdArray= tdText.split(",");
if(tdArray.length==1){
tdArray= tdText.split(",");
}
if(!isempty(tdText) && tdArray.length>1 && (jQuery.trim(tdArray[0]).length==jQuery.trim(tdArray[1]).length)){
tdText = replaceAll(tdText,",",";");
tdText = replaceAll(tdText,",",";");
}
body2 += ","+tdText;//赋值
});
body +="@"+body2.substring(1);//因为上面有使用;,避免取值错误,因此使用@
});
body=body.substring(1);//去掉第一个@
var param = {"head":head,"body":body,"time":+(new Date()).getTime()};
param = JSON.stringify(param);//将Object类型的param转成字符串
//alert(param);
//从后台获取Excel文件模拟下载
var urls = (window.location+'')+"/ExcelServlet?param="+param;
if ($("#bodyFileDown").length <1){
$("body").append("<iframe id='bodyFileDown' src='' ></iframe>");
$("#bodyFileDown").hide();
}
$("#bodyFileDown").attr("src", urls);//设置src属性,iframe通过src自动请求Servlet
}
//点击“标题”中的复选框时全选或者不全选
function selectAllOrNot(obj){
//使用attr("checked"),IE正常,火狐则是undefined
var isChecked = $(obj)[0].checked;//判断是否选中
if(isChecked){//说明被选中了
$("#toExcel>tbody>tr:not(.tabFirstTr)>td :checkbox").each(function(){//全选
$(this).attr("checked",true);
});
}else{
$("#toExcel>tbody>tr:not(.tabFirstTr)>td :checkbox").each(function(){//全不选
$(this).attr("checked",false);
});
}
}
/**
*验证js变量的值是否为空,
* true-不存在
* false-存在
*
*/
function isempty(v){
switch (typeof v){
case 'undefined' : return true;
case 'string' : if((v.replace(/(^\s*)|(\s*$)/, "")).length == 0) return true; break;
case 'boolean' : if(!v) return true; break;
case 'number' : if(0 === v) return true; break;
case 'object' :
if(null === v) return true;
if(undefined !== v.length && v.length==0) return true;
for(var k in v){return false;} return true;
break;
}
return false;
}
</script>
4、使用的Servlet:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jxl.CellView;
import jxl.Workbook;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import net.sf.json.JSONObject;
public class ExcelServlet extends HttpServlet {
File saveDir = null;//文件目录
/**
* Constructor of the object.
*/
public ExcelServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
this.doPost(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String param = "1";
//获取传递过来的参数值
if(null!=request.getParameter("param") && !"".equals(request.getParameter("param"))){
param = request.getParameter("param");
}
param = new String(param.getBytes("ISO8859-1"),"UTF-8");//解决乱码的问题
//param = JSONObject.fromObject(param).toString();
if(!param.equals("1")){//说明有传递参数
JSONObject jsobj = JSONObject.fromObject(param);
String head = jsobj.getString("head");//获取标题
String body = jsobj.getString("body");//获取内容
try {
String[] title = head.split(",");//以,分割字符串
String fileName = System.currentTimeMillis()+".xls";//以当前时间作为Excel的名称:2003版本的
System.out.println(saveDir+ java.io.File.separator + fileName);
File excel = new File(saveDir+ java.io.File.separator + fileName);
WritableWorkbook workBook = Workbook.createWorkbook(excel);//创建可写入的Excel工作薄
WritableSheet sheet = workBook.createSheet("第一页", 0);//生成名为“第一页”的工作表,参数0表示这是第一页,1表示第二页,以此类推
//mergeCells(int x,int y,int m,int n):合并单元格,表示将从第x+1列,y+1行到m+1列,n+1行合并 (四个点定义了两个坐标,左上角和右下角)结果是合并了m-x+1行,n-y+1列,两者乘积就是合并的单元格数量。
sheet.mergeCells(0,0,title.length-1,0);
/**
* 定义excel主标题的格式
*/
WritableFont title2 = new WritableFont(WritableFont.ARIAL,12,WritableFont.BOLD);//加粗
WritableCellFormat titlewcf = new WritableCellFormat(title2); // 单元格定义
titlewcf.setAlignment(jxl.format.Alignment.CENTRE); //设置对齐方式
titlewcf.setBorder(Border.ALL, BorderLineStyle.THIN);//设置边框样式
titlewcf.setBackground(Colour.LIGHT_GREEN);//设置背景色
/**
* 定义excl列标题的格式
*/
WritableFont wf = new WritableFont(WritableFont.ARIAL,14,WritableFont.BOLD);//加粗
WritableCellFormat wcf = new WritableCellFormat(wf); // 单元格定义
wcf.setAlignment(jxl.format.Alignment.CENTRE); // 设置对齐方式
wcf.setBorder(Border.ALL, BorderLineStyle.THIN);//设置边框样式
wcf.setBackground(Colour.LIGHT_GREEN);//设置背景色
//为第一行合并的单元格设置标题
Label lab = new Label(0,0,"将数据导出到Excel中",wcf);
sheet.addCell(lab);
/**
* 定义excl内容的格式
*/
WritableFont comtent = new WritableFont(WritableFont.ARIAL,10,WritableFont.NO_BOLD);//常规
WritableCellFormat comtent_c = new WritableCellFormat(comtent); // 单元格定义
comtent_c.setAlignment(jxl.format.Alignment.CENTRE); // 设置对齐方式
comtent_c.setBorder(Border.ALL, BorderLineStyle.THIN);//设置边框样式
comtent_c.setBackground(Colour.LIGHT_GREEN);//设置背景色
//遍历“标题”内容并添加到Excel中
for(int i=0;i<title.length;i++){
sheet.setColumnView(i, 20);//设置单元格的宽度
//sheet.setRowView(i, 20, false);//设置单元格的高度(设置高度以后,导出来的数据会自动隐藏)
//Label(int x,int y,String content,WritableCellFormat wcf):指明单元格的位置和内容,四个参数依次为;第几列、第几行、内容、样式
Label label=new Label(i,1,title[i],wcf);//在第一行中添加文本类单元格
sheet.addCell(label);
}
//遍历body中的内容并添加到Excel中
String bodyContent[] = body.split("@");//多行数据以@分开
for(int i=0;i<bodyContent.length;i++){
String[] bodyContent2 = bodyContent[i].split(",");
for(int j=0;j<bodyContent2.length;j++){
Label label = new Label(j,i+2,bodyContent2[j],comtent_c);//从第二行开始添加单元格,第一行是标题
sheet.addCell(label);
}
}
//在Excel中写入数据并关闭文件
workBook.write();
workBook.close();
//提供下载
//这个头文件很关键,必须告知filename,否则系统会自动将文件以txt的形式下载,且文件名称为请求的Servlet名称(文件名称:ExcelServlet.txt)
response.setHeader("Content-Disposition", "attachment; filename="+ new String(excel.getName().getBytes("GB2312"),"ISO-8859-1"));
FileInputStream in = new FileInputStream(excel);
//response.reset();//解决:getWriter() has already been called for this response的问题
OutputStream outputStream = response.getOutputStream();
int i = 0;
byte b[] = new byte[1024];
while ((i = in.read(b)) != -1) {//读取Excel文件
outputStream.write(b, 0, i);//写入到页面提供下载
}
outputStream.flush();
outputStream.close();
outputStream=null;
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 初始化Servlet时,先判断指定目录是否存在,若不存在则新建
* 若存在,则删除指定目录下的文件,避免每次下载都生成文件导致硬盘容量不够
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
super.init();
String savePath = "D:"+java.io.File.separator+"saveDir";
saveDir = new File(savePath);
System.out.print("***********************************************\n"+saveDir.isDirectory()+"\n");
if(!saveDir.isDirectory()){//指定目录不存在则新建
saveDir.mkdir();
}else{//若是已经存在,那么删除里面的内容,避免每次下载都生成文件导致硬盘容量不够
deleteFiles(saveDir);
saveDir.mkdir();
}
}
/**
* 删除文件
* @param file:File类型,指定要删除的文件
* */
private void deleteFiles(File file){
if(file.isDirectory()){
File[] files = file.listFiles();//获取指定目录下的所有文件
for(int i=0;i<files.length;i++){
deleteFiles(files[i]);
}
}
file.delete();//删除文件
}
}
JXL参考:http://747017186.iteye.com/blog/1935172