`

JXL通过AJAX将数据导出到Excel中

阅读更多

这篇博文写的对别人没有什么参考价值,仅仅给自己留个思路。

 

以前因为时间的原因导数据到Excel中用的是JS,也没有大数据的测试,结果到后来一碰上大数据就宕机。最近终于抽时间好好来琢磨这个问题啦,改从服务器端导数据。

 

前面的博文中其实也有提到用JXL导数据,但是导出的数据比较少,是直接将需要导出的数据拼接成字符串然后传到后台一个一个弄到Excel中的,大数据的话就不适用了。另外,以前的那个用的直接跳servlet,这回跳不了(因为总会报错——Cannot reset buffer after response has been committed,导致Ajax失败),所以只能用Ajax了。

 

用AJAX还有个毛病,等分两步:第一步使用AJAX生成Excel文件,并返回Excel的文件路径及名称。第二步:模拟访问该Excel进行下载。

 

说一下业务吧:

1、导入到Excel中的数据是存在数据库中,直接取,这个容易;

2、但是页面信息如从哪个表取数据、取哪些字段也是存在数据库里面的而且是变动的,这个比较难,需要根据给定的“视图编号”去查表(from )、查条件(where)、查排序(order by),通过JS从页面获取显示的字段信息(select)、需要导入的数据信息(取那几条)并传入后台用来查数据。

 

难点就在于:找表,找查询条件,找排序信息,找字段,拼接指定的数据信息

 

1、下面这段JS是触发点,也就是点某个按钮时触发tableList_excel()方法,这个方法首先判断是否有告知从哪儿取数——这个很重要,关系到from、where、order by,其次判断有没有选定要导出来的数据——这个也很重要,至少得告诉我你要导哪些数据吧,最后根据选定的数据条数来判断是使用客户端导数据还是使用服务器端,之所以设置为10条,一是每页显示的是10条,而是10条数据不是很多用JS导不算久,客户等的起。

//将选定数据导出到Excel中
function tableList_excel(obj){
	//1、判断是否指定获取数据的表
	var viewID=null;
	if($(obj).is("[viewID]")){
		viewID=$(obj).attr("viewID");
	}else{
		alert("缺少:viewID属性,无法获取选择参数");return ;
	}
	viewID = jQuery.trim(viewID);
	var rows = $("#table_"+viewID+">tbody>tr>td :checkbox:checked").length;
	//2、判断是否选定数据
	if(rows<=0){//说明没有选数据
		doalert("请选择要导出的数据!");
		return false;
	}
	
	//3、根据选取的行数判断使用服务器导出还是客户端导出
	if(rows>10){//多于10条,使用服务器导出数据
		 exportToExcelForServer(viewID);
		 return false;
	}else{//少于10条时直接用客户端导出
		exportToExcelForClient(viewID,0);
		return false;
	}
	return ;
}

 2、这个是用客户端导的数据,就是用ActiveX插件导,比较简单,一个一个td取值,一个一个单元格放数据,数据较多时浏览器容易卡死。

/**
 * 通过客户端导出数据到Excel中
 * @param viewID:数据源所在的视图ID
 * @param flag:服务器端导出是否出错,默认为0
 * */
function exportToExcelForClient(viewID,flag){
	//若使用客户端判断是否支持ActiveX插件,若是支持使用插件导出,否则用服务器端导出
	try {
		var oXL = new ActiveXObject("Excel.Application"); //创建excel应用程序对象
	}catch(e) {//可能不是IE,也可能是IE没有启用ActiveX控件,使用服务器导出数据
		if(flag==1){//说明服务器端导出出错,且没有启用ActiveX控件,那么提示
			alert("要将该表导出到Excel,您必须安装Excel电子表格软件,同时浏览器须使用“ActiveX 控件”,您的浏览器须允许执行控件。\n请到公共模块-下载中心查找相应帮助文档");
		}else{//说明可以用服务器端导出
			exportToExcelForServer(viewID);  
		}
	    return;
	}
	//使用ActiveX插件导出
	var oWB = oXL.Workbooks.Add(); //创建工作簿
	var oSheet = oWB.ActiveSheet;  //获取当前活动的工作簿
	oSheet.Columns.AutoFit;//设置自动调整列宽
	var $head = $("#table_"+viewID+">thead>tr.tabFirstTr>td:visible");
	var $body = $("#table_"+viewID+">tbody>tr>td :checkbox:checked").parent().parent().parent("tr");
	oSheet.Rows(1).RowHeight = 23;//行高
	//标题行
	var headText = null;
	var checkboxNum="";
	var count=0,count2=0;
	$head.each(function(){
		if($(this).is("[MSelect]")){
			checkboxNum=count;
			return ;//不执行该循环,直接下一个循环
		}
		headText = (isempty($(this).attr("title"))?$(this).text():$(this).attr("title"));
		oSheet.Columns(count+1).ColumnWidth = 23;//列宽
		oSheet.Cells(1,count+1).Font.Bold=true;//加粗
		oSheet.Cells(1,count+1).Font.Size=14;
		//设置单元格底色(1-黑色,2-白色,3-红色,4-绿色,5-蓝色,6-黄色,7-粉红色,8-天蓝色,9-酱土色)
		oSheet.Cells(1,count+1).Interior.ColorIndex = 35;//浅绿色  
		oSheet.Cells(1,count+1).HorizontalAlignment = 3;//水平对齐方式:居中
		oSheet.Cells(1,count+1).VerticalAlignment = 2;//垂直对齐方式:居中
		oSheet.Cells(1,count+1).Borders.Weight = 2; //设置单元格边框*()
		oSheet.Cells(1,count+1).Value = (isempty($(this).attr("alias"))?headText:$(this).attr("alias"));//设置标题的内容
		count++;
	});
	//内容行
	var tdText=null;
	var tdArray=null;
	$body.each(function(m){
		count2=0;
		oSheet.Rows(m+2).RowHeight = 23;//行高
		$(this).children("td:visible").each(function(n){//td的内容
			oSheet.Columns(count2+1).ColumnWidth = 23;//列宽
			if(n==0){//说明是序号列
				tdText=m+1;
			}else{
				if(n==checkboxNum){
					return ;//说明是复选框,直接跳出
				}
				tdText = isempty($(this).attr("title"))?$(this).text():$(this).attr("title");//先取title属性的值,若没有则取text()
				tdArray= tdText.split(",");
				if(tdArray.length==1){
					tdArray= tdText.split(",");
				}
				//处理"当数据用,号隔开,倒入到Excel时,Excel自动用科学技术发表示"的情况
				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,count2+1).Interior.ColorIndex = 35;//浅绿色 
			oSheet.Cells(m+2,count2+1).HorizontalAlignment = 3;//水平对齐方式:居中
			oSheet.Cells(m+2,count2+1).VerticalAlignment = 2;//垂直对齐方式:居中
			oSheet.Cells(m+2,count2+1).Borders.Weight = 2; //设置单元格边框*()
			oSheet.Cells(m+2,count2+1).Font.Size=12;//12号字体
			oSheet.Cells(m+2,count2+1).Value = tdText;
			count2++;
		});
	});
	oXL.Visible = true; //设置Excel的属性
	oXL.UserControl = true;
	oSheet = null;
	oWB = null;
	oXL = null;
}

 

 3、这个是服务器端导数据,用的JXL。第一步获取参数键,这个参数键用来匹配主键参数键提高性能和精确度的;第二步获取标题,其实获取的是绑定字段的序号——这个绑定字段是存在数据库中的,是变动的,因为通过序号可以获取到除了标题之外别的以后可能要用的数据;第三步获取参数集合,也就是要到导出的数据信息。第四步拼接成XML通过AJAX提交导后台处理并返回生成的Excel文件路径及名称,并采用模态进行下载。
/**
 * 通过服务器端导出数据到Excel中
 * @param viewID:数据源所在的视图ID
 * */
function exportToExcelForServer(viewID){
	//1、获取参数键
	var runKey="";
	$("#table_"+viewID+">thead>tr.tabFirstTr").children("td[isPK]").each(function(){
		runKey +=","+$(this).attr("isPK");//获取参数集合
	});
	if(runKey.length>1){
		runKey = runKey.substring(1);
	}else{//弹出提示
		alert("无法获取参数键集合");
		return false;
	}
	
	//2、获取标题
	var titleStr="",headText="",dbStr="",dbText="";
	$("#table_"+viewID+">thead>tr.tabFirstTr").children("td:visible").each(function(){
//		headText = (isempty($(this).attr("title"))?$(this).text():$(this).attr("title"));
//		titleStr +=","+(isempty($(this).attr("alias"))?headText:$(this).attr("alias"));//设置标题的内容
		dbText = $(this).attr("databindId");
		if(!isempty(dbText)){
			dbStr +=","+dbText;
		}
	});
//	titleStr = titleStr.split(",,")[1];//,,是复选框导致的所以可以直接截取
	dbStr=dbStr.substring(1);//将第一个逗号截去
//	alert(dbStr);
	
	//3、获取参数集合
	var datas="<datas>";
	$("#table_"+viewID+">tbody>tr>td :checkbox:checked").each(function(){
		//去含有isPK属性的值
		var tr_obj=$(this).parent().parent().parent();
		datas+="<row>";
		$(tr_obj).find("td[isPK]").each(function(){
			//获取td的内容
			var tdContent=$(this).attr("title");
			//获取isPK的值
			var isPKVal=$(this).attr("isPK");
			datas+="<col key=\""+isPKVal+"\" val=\""+EscapeSymbol(tdContent)+"\"/>";			
		});		
		datas+="</row>";
	});
	datas+="</datas>";
	
	var xml="<tsp><relatedBIDS>"+runKey+"</relatedBIDS><databindid>"+dbStr+"</databindid><viewid>"+viewID+"</viewid>"+datas+"</tsp>";
//	alert(xml);
	var param = {"parametersStr":xml,"time":new Date()};
	param = JSON.stringify(param);//将Object类型的param转成字符串  
//    alert(param);  
    $.ajax({
		url :"fileRouter!exportToExcel.action",
		async :false,
		type :"post",
		dataType :"text",
		data : {"param":param},		
		error : function(C) {
			exportConfirm(viewID);
		},
		success : function(C) {
			if(C.toString()!="false"){//说明是访问成功了,返回的是Excel文件的路径和名称
				//从后台获取Excel文件模拟下载 
			    var urls = "fileRouter!downloadExcelFile.action?nodeid=0&path="+C;  
			    if ($("#bodyFileDown").length <1){  
			        $("body").append("<iframe id='bodyFileDown' src='' ></iframe>");  
			        $("#bodyFileDown").hide();  
			    }  
			    $("#bodyFileDown").attr("src", urls);//设置src属性,iframe通过src自动请求Servlet 
			}else{
				exportConfirm(viewID);//导出失败,询问意见是否使用客户端导出
			}							
		}
	});
}
 4、这个方法是为了防止服务器导出数据失败,到时可以建议采用客户端导数据。因为客户端导数据除了慢之外其他还是比较靠谱的。
/***
 * 导出确认提示框
 * viewID:参数键名称
 * */
function exportConfirm(viewID){
	if(confirm("服务器端导出失败!试图尝试用客户端导出,导出较慢,是否继续?")){
		exportToExcelForClient(viewID,1);
	}
}
 5、exportToExcel()方法就是根据传递过来的参数用来生成Excel文件的,它只负责生成Excel文件,并不提供下载。生成的Excel背景色是护眼色,有边框,12号字体,有sheet名,有标题,有自动生成的序号,看着还挺舒服。
/**
 * 将选定数据导出到Excel中
 * */
public void exportToExcel() throws Exception{
	HttpServletRequest request = ServletActionContext.getRequest();
	HttpServletResponse response = ServletActionContext.getResponse();
	Object userInfo = request.getSession().getAttribute("userInfo");
	SUser user=null;
	if(userInfo==null){
		throw new TspException("获取用户信息失败:userInfo=null");
	}else{
		user = (SUser)userInfo;
	}
	
	String param = "1"; 
	String result="false";
    //获取传递过来的参数值  
    if(null!=request.getParameter("param") && !"".equals(request.getParameter("param"))){  
        param = request.getParameter("param");  
    }  
    param = new String(param.getBytes("ISO8859-1"),"UTF-8");//解决乱码的问题  
    if(!param.equals("1")){//说明有传递参数  
        JSONObject jsobj = JSONObject.fromObject(param);  
        String parametersStr = jsobj.getString("parametersStr");//参数  
        //String dbStr = jsobj.getString("dbStr");//数据绑定编号
        //String titleStr = jsobj.getString("titleStr");//标题
        
        try {  
        	Parameters paramters=getParameters(parametersStr);//解析传递过来的XML
        	List<Object[]> dataList = dataEngine.getTableData(paramters,user,1);//拼接SQL获取查询结果
        	if(dataList!=null && dataList.size()>0){            	
        		String fileName = System.currentTimeMillis()+".xls";//以当前时间作为Excel的名称:2003版本的  
                File saveDir = initFileDir();//获取Excel文件导出后保存路径
//	            	System.out.println(saveDir+ java.io.File.separator + fileName);  
                String filePath = saveDir+ java.io.File.separator + fileName;
                File excel = new File(filePath);  
                 
                //工作簿名称 list
                WritableWorkbook workBook = Workbook.createWorkbook(excel);//创建可写入的Excel工作薄  
                Object [] sheetName= dataList.get(dataList.size()-1); 
                WritableSheet sheet = workBook.createSheet(sheetName[0].toString(), 0);//生成名为“当前视图名称”的工作表,参数0表示这是第一页,1表示第二页,以此类推  
                  
                /** 
                 * 定义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);//设置背景色  
                  
                /** 
                 * 定义excel列标题的格式 
                 */  
                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);//设置背景色  
                  
                /** 
                 * 定义excel内容的格式 
                 */  
                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);//设置背景色  
                 
                String objStr="";
                //遍历“标题”内容并添加到Excel中
                Object [] title = dataList.get(dataList.size()-2);//倒数第一个是sheet名称,倒数第二个才是标题,所以需要减去2  
            for(int i=0;i<title.length;i++){  
                sheet.setColumnView(i, 23);//设置列宽
                sheet.setRowView(0, 20*23,false);//设置单元格的高度,目前为23,高度大概得设置成Excel里面行高的20倍才能达到相应的效果
                objStr=(title[i]==null?"":title[i].toString());
                Label label=new Label(i,0,objStr,wcf);//在第一行中添加文本类单元格  
                sheet.addCell(label);  
            }  
                  
                //遍历list中的内容并添加到Excel中
                for(int i=0;i<dataList.size()-2;i++){  
                	Object [] objs= dataList.get(i);  
                    for(int j=0;j<objs.length;j++){
                         sheet.setRowView(i+1, 20*23,false);//行高
                    	objStr=objs[j]==null?"":objs[j].toString();
//	                    	System.out.println(i+"        "+j+"    "+objStr);
                    	//添加序号列
                    	Label orderLabel = new Label(0,i+1,new Integer(i+1).toString(),comtent_c);//第一列为序号列
                        sheet.addCell(orderLabel); 
                        
                    	Label label = new Label(j+1,i+1,objStr,comtent_c);//从第二行开始添加单元格,第一行是标题  
                        sheet.addCell(label);  
                    }  
                }  
                //在Excel中写入数据并关闭文件  
                workBook.write();  
                workBook.close();  
                
                result=filePath;
        	}
        } catch (Exception e) {  
            e.printStackTrace();  
        }finally{
			response.setCharacterEncoding("UTF-8");
			response.setContentType("text/html");
			response.setHeader("Pragma", "No-cache");
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Cache-Control", "no-store");
			response.setDateHeader("Expires", 0);
			response.getWriter().write(result);
			response.getWriter().flush();
			response.getWriter().close();
		}  
    } 
}
 

6、以下方法用来下载文件。值得注意的是:

a、一定要设置头文件,否则系统会自动将文件以txt的形式下载

b、总是会报错(具体问题忘记了),但是不影响系统运行(这也就是为什么要分两步走的原因,报错导致Ajax失败不能继续执行)

/**
 * 下载指定Excel文件
 * */
public void downloadExcelFile(){
	HttpServletRequest request = ServletActionContext.getRequest();
	HttpServletResponse response = ServletActionContext.getResponse();
    String path = null;
    if(null!=request.getParameter("path") && !"".equals(request.getParameter("path"))){  
    	path = request.getParameter("path");  
    }
    try{
        File excel = new File(path);
        FileInputStream in = new FileInputStream(excel);
//这个头文件很关键,必须告知filename,否则系统会自动将文件以txt的形式下载,且文件名称为请求的Servlet/Action名称(如文件名称:ExcelServlet.txt)  
        response.setHeader("Content-Disposition", "attachment; filename="+ new String(excel.getName().getBytes("GB2312"),"ISO-8859-1"));
        //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();
    }
}
 7、这三个方法是辅助方法,第一个方法用来解析前台传递过来的XML文件并填充到各个属性中;第二个方法用来初始化文件目录,首先从配置文件中获取文件目录,若有配置就采用配置的目录,否则手动指定目录,然后判断指定的目录是否存在,若不存在就新建目录,若存在先删除目录下指定的文件,也就是第三个方法的功能,它主要用来删除今天以前的文件,因为每次导数据都会生成一个Excel文件,时间久了占用的空间会很大,所以每次导之前都自动删除掉以前的文件避免空间不足的问题。
/***
*解析字符串并返回Parameters对象,可以通过访问该对象的属性值获取从前台传递过来的对应参数
*@param parametersStr:字符串类型的XML
*/
public Parameters getParameters(String parametersStr) {
	logger.debug(parametersStr);
	return ParametersUitls.getParametersByStrForXML(parametersStr);
}

/** 
 * 导出数据时,先判断指定目录是否存在,若不存在则新建 
 * 若存在,则删除指定目录下的文件,避免每次下载都生成文件导致硬盘容量不够 
 */  
public File initFileDir() {  
	String savePath = WebAppConfig.app("excelDir");//从配置文件中获取保存Excel的目录
	savePath=savePath.trim();
	if(savePath==null || savePath.equals("null") || savePath.length()<=0 ){
		savePath = "D:"+java.io.File.separator+"bfp"+java.io.File.separator+"ed";//手动拼接文件目录
	}
    File saveDir = new File(savePath);    
    if(!saveDir.exists() || !saveDir.isDirectory()){//指定目录不存在则新建   
        saveDir.mkdir();    
    }else{//若是已经存在,那么删除里面的内容,避免每次下载都生成文件导致硬盘容量不够  
      deleteFiles(saveDir);  
        //saveDir.mkdir();   
    } 
    return saveDir;
}  
  
/** 
 * 删除文件 
 * @param file:File类型,指定要删除的文件 
 * */  
private void deleteFiles(File file){
	Calendar cal = Calendar.getInstance();
	Calendar cal2 = Calendar.getInstance();
	cal2.setTime(new Date());//设置当前时间
	int day1=0,day2=0;
    if(file.isDirectory()){  
        File[] files = file.listFiles();//获取指定目录下的所有文件  
            for(int i=0;i<files.length;i++){
                cal.setTimeInMillis(files[i].lastModified()); //获取文件的最后修改时间并设置为Calendar的前时间值
                if(cal2.get(Calendar.YEAR)-cal.get(Calendar.YEAR)>0){//說明是以前的文件,那麼直接刪除
                	//System.out.println("修改时间[1] " + cal.getTime().toLocaleString());
                	//System.out.println("修改时间[2] " + cal2.getTime().toLocaleString());
                	deleteFiles(files[i]);
                }else{//說明是今年或以後的文件
//                    	 System.out.println("修改时间[3] " + cal.getTime().toLocaleString());
//                    	 System.out.println("修改时间[4] " + cal2.getTime().toLocaleString());
                	 day1= cal.get(Calendar.DAY_OF_YEAR);
                     day2 = cal2.get(Calendar.DAY_OF_YEAR);
                      if((day2-day1)>0){//說明是今天之前的文件
                    	  deleteFiles(files[i]);
                      }
                }
             }  
    }  
    file.delete();//删除文件  
}
 8、以下是拼接SQL获取数据集合的方法,需要说明的一点:系统里面在获取选定的数据时有两种处理方式,一种找当前表的主键一旦找到即用主键信息进行查找,若找不到就采用其他字段联合起来查询。
/**
 * 根据传递的参数获取需要导出到Excel中的数据
 * @param params:包括参数键值和需要显示的数据绑定ID
 * @param userinfo:当前登录人ID
 * @param flag:查询标记 1-模糊查询 0-精确查询
 * */
public List<Object[]> getTableData(Parameters params, SUser userinfo,int flag) throws Exception{
	List<Object[]> list=null;
	SView view = viewdao.findById(Integer.parseInt(params.getViewid()));//获取视图信息,方便获取sheet名称,from,where,order by等信息
	if (view == null) {
		logger.error("获取视图实体失败!");
		return null;
	}
	getParams(params);//将fieldList和queryList赋值
	String dbId = params.getDatabindid();//获取需要导出的数据信息
	dbId = dbId.trim();
//		System.out.println(dbId);
	if(dbId!=null && dbId.length()>0){
		String tableid="",fieldStr="",fieldid="",tafd="";;
		String[] aliasStr=null;//声明数组用来储存Excel的标题信息(即第一行的标题信息)
		String PKMapkey = "",mapkey="";
		String runKey = params.getRelatedBIDS();//参数键集合
		String PKField="",MKey="";
		//1、处理select字段
		String hql="from com.tzj.tsp.entity.SDatabindView where SViewId="+ view.getSViewId() +" and SDatabindId in ("+ dbId +")";
		List<SDatabindView> databingviewlist =databindviewdao.get(hql);
		SDatabindView dbView=null;
		if(databingviewlist!=null && databingviewlist.size()>0){
			aliasStr = new String[databingviewlist.size()+1];//分配内存空间
			aliasStr[0]="序号";
			for(int i=0;i<databingviewlist.size();i++){
				dbView = databingviewlist.get(i);
				tableid= dbView.getEntityname();//获取表名
				fieldid = dbView.getAttributephysic();//获取字段名称
				String bieming=tableid;
				if(bieming.length()>7)bieming=bieming.substring(0, 6);
				tafd= tableid + "." + commonxml.tableAndField(fieldid);//拼接字段
				if(dbView.getOcxtype()!=null){
					tafd= commonxml.tableField(tafd, dbView.getOcxtype());
					if(dbView.getOcxtype()==28 || dbView.getOcxtype()==32){//单位件上传、单图片上传:多文件多图片上传类型的暂时不支持
						tafd="(select FILENAME from S_ACCESSORIES where ID="+tafd+")";//将文件序号替换成文件名称(表中只保存文件序号,其他的文件信息保存在S_ACCESSORIES表中)
					}
				}
				/*
				if(dbView.getStaticcontent()!=null && (!dbView.getStaticcontent().equals(""))){
					//统一转换成字符型数据 fieldid 表示别名
					tafd=commonxml.staticValue(tafd, dbView.getStaticcontent());
				}
				*/
				aliasStr[i+1]=dbView.getAlias();
				fieldStr += "," + tafd+" "+bieming+"_"+fieldid;
			}
		}
		//2、处理from
		String selectcondition = view.getSelectcondition();
		//3、处理where:原视图中有的条件
		String querySQL = view.getQuery();
		// 替换 selectcondition与query 中的标记
		if (fieldList != null && fieldList.size() > 0) {
			for (int j = 0; j < fieldList.size(); j++) {
				if (fieldList.get(j) != null) {
					Map<String, String> mapfield = fieldList.get(j);
					Set<String> con = mapfield.keySet();
					for (String c : con) {
						String key = "<" + c + ">";
						if(querySQL!=null && (!querySQL.equals(""))) {
							querySQL = querySQL.replaceAll(key, mapfield.get(c));
						}
						selectcondition = selectcondition.replaceAll(key,mapfield.get(c));
					}
				}
			}
		}
		//3、处理where:选定的数据
		String hql2="from com.tzj.tsp.entity.SDatabindView where SViewId="+ view.getSViewId() +" and (key>0 and key<>93) order by key asc";
		List<SDatabindView> sdbViewList = databindviewdao.get(hql2);
		SDatabindView sdbView = null;
		if(sdbViewList!=null && sdbViewList.size()>0 ){
			for(int i=0;i<sdbViewList.size();i++){
				sdbView = sdbViewList.get(i);
				tableid = sdbView.getEntityname();
				fieldid = sdbView.getAttributephysic();
				tafd= tableid + "." + commonxml.tableAndField(fieldid);
				if(sdbView.getOcxtype()!=null){
					tafd= commonxml.tableField(tafd, sdbView.getOcxtype());
				}
				if(sdbView.getStaticcontent()!=null && (!sdbView.getStaticcontent().equals(""))){
					//统一转换成字符型数据 fieldid 表示别名
					tafd=commonxml.staticValue(tafd, sdbView.getStaticcontent());
				}
				PKField=commonxml.getPrimaryKey(tableid); //获取主键所在列
				MKey=sdbView.getKey().toString();//获取参数键
				if(fieldid.equals(PKField) && runKey.indexOf(("M"+MKey))!=-1){//说明当前字段与主键所在列相同,且参数键在给定的参数键中
					if (fieldList != null && fieldList.size() > 0) {
						mapkey="";
						for (int j = 0; j < fieldList.size(); j++) {
							Map<String, String> mapfield = fieldList.get(j);
								String value = commonxml.getValueByTypeOn(0,sdbView.getAttributedetype(), mapfield.get("M"+ MKey));
								if (mapkey.equals(""))mapkey = tafd + "=" + value;
								else {
									if(flag==0) mapkey += " and " + tafd + "=" + value;
									else mapkey += " or " + tafd + "=" + value;
								}
						}
						break;//找到对应主键数据之后结束循环
					}
				}else{//说明当前字段与主键所在列不相同
					if (fieldList != null && fieldList.size() > 0) {
						for (int j = 0; j < fieldList.size(); j++) {
							Map<String, String> mapfield = fieldList.get(j);
								String value = commonxml.getValueByTypeOn(0,sdbView.getAttributedetype(), mapfield.get("M"+ MKey));
								if (mapkey.equals("")) mapkey = tafd + "=" + value;
								else {
									if(flag==0)	mapkey += " and " + tafd + "=" + value;
									else mapkey += " or " + tafd + "=" + value;
								}
						}
					}
				}
			}
			
		}
		
		//4、处理order by
		String orderSQL = view.getOrdersql();
		
		if(fieldStr.length()>1) fieldStr= fieldStr.substring(1);//除去第一个逗号
		//System.out.println(aliasStr+"\n"+fieldStr);
		
		String sql=" select "+fieldStr;
		if(querySQL!=null && (!querySQL.equals(""))) {//说明原来的where字段中就有条件
			//判断是否有<M,<E,<Q打头的数据,若有那么视图中的querySQL不拼接到SQL中,否则拼接
			if(querySQL.indexOf("<M")==-1 || querySQL.indexOf("<E")==-1 || querySQL.indexOf("<Q")==-1){
				querySQL="";//因为有不能替代的参数存在,SQL无法执行,所以去除当前查询条件
			}
		}
		if(querySQL!=null && (!querySQL.equals(""))){
			if (mapkey != null && mapkey.trim() != "") {querySQL = querySQL + " and (" + mapkey+")";}
		}else{
			if (mapkey != null && (!mapkey.trim().equals("")))querySQL = mapkey;
		}
		
		if(querySQL!=null && (!querySQL.equals("")))
			sql = sql + " from " + selectcondition + " where " + querySQL + " ";
		else
			sql = sql + " from " + selectcondition;
		if(orderSQL!=null && (!orderSQL.equals("")))sql = sql +" "+ orderSQL;
		if (userinfo != null) {sql=formatSQL(userinfo,sql);}
		//String sql2 = this.getTableSQL(view, fieldList, queryList, userinfo, params.getOrderList(), flag);
		list = execSQL.selectQuery2(sql);
		if(list!=null && list.size()>0){//说明查询之后有结果
			list.add(aliasStr);//保存别名用作Excel的标题
			list.add(new String[]{view.getViewname()});//保存视图名称作为工作簿名称
		}
	}
	return list;
}

 9、以下的方法用来查询SQL并将结果以数组的形式添加到List中,一条数据作为一个数组,一个字段作为一个数组中的一个值,最后返回包含多个Object数组的List集合。

/***
 * 执行sql语句获得结果集
 * 
 * @param sql
 * @return Object数组
 */
@SuppressWarnings("unchecked")
public List<Object[]> selectQuery2(final String sql) throws Exception {
	log.debug("执行sql语句: " + sql);
	List<Object[]> result=null;
	try {
		if(!this.checkSQL(sql)){
			throw new Exception("sql语句【"+ sql +"】不正确!");
		}
			result = (List<Object [] > ) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session arg0) throws HibernateException,
					SQLException {
				return arg0.createSQLQuery(sql).list();
			}
		});
	} catch (Exception e) {
		System.out.println("ERROR:" + e.getMessage());
		log.info("执行sql:[" + sql + "]失败:" + e.getMessage());
		log.error("执行sql:[" + sql + "]失败:" + e.getMessage(), e);
		throw e;
	}
		if(result!=null && result.size()>0){
			return result;
		}else{
			return null;
		}
}

 

 

分享到:
评论

相关推荐

    struts2+jxl导出excel

    在"struts2+jxl导出excel"的场景中,我们将讨论如何利用Struts2框架与JXL库配合,实现从web应用中导出数据到Excel的工作。 首先,我们需要理解Struts2的动作(Action)和结果(Result)。动作是处理用户请求的核心...

    Ext中用jxl导出全部数据和当前页数据的实现

    根据提供的文件信息,本文将详细解释如何在ExtJS框架中使用jxl库...通过上述步骤,我们成功地实现了在ExtJS中使用jxl导出全部数据和当前页数据的功能。这种方法不仅提高了工作效率,也为用户提供了更加方便的操作方式。

    js导出excel

    在现代Web应用中,将数据导出到Excel文件是一种常见的需求,这可以帮助用户方便地存储和处理大量数据。本文将详细介绍如何使用JavaScript(js)和JXL库来实现从JSP页面的table表格导出到Excel,同时确保兼容所有...

    dwr结合jQuery实现Ajax技术 ,Oracle作为后台数据库,jxl + poi报表

    当需要生成报表时,应用可以利用jxl或POI库将数据库中的数据转化为Excel格式,供用户下载或在线查看。这种架构允许创建响应式、高效的Web应用,同时提供了灵活的数据管理和报告功能。开发者需要掌握Java编程、Ajax...

    jxl以及jquery的form提交

    `jxl`库允许Java开发者以编程方式操作Excel文件,这在数据分析、报表生成或者数据导入导出时非常有用。它支持多种操作,如读取单元格内容、修改工作表、创建新的工作簿、合并单元格、设置样式等。以下是一些使用`jxl...

    jquery使用jxl插件导出excel示例

    ### Jquery与jxl插件导出Excel示例知识点解析 #### jQuery简介 jQuery是一个快速、小巧、功能丰富的JavaScript库。它通过一个简洁的API使得HTML文档遍历和操作、事件处理、动画和Ajax等操作变得更加容易。jQuery的...

    基于excel的文件导入的java实现代码

    在前后台代码中,前端可能通过表单上传Excel文件,后端接收文件,处理数据,再将结果返回给前端。这涉及到文件上传、文件流处理和HTTP响应等知识。 - 前端:使用HTML5的 `&lt;input type="file"&gt;` 元素和JavaScript...

    jxl、javascript、dhtml的api参考手册包

    例如,如果你正在开发一个需要导出数据到Excel的应用,JXL的API能帮助你实现这一功能;如果需要在网页上实现交互功能,JavaScript的手册将提供必要的指导;而DHTML的手册则可帮助你创建更加生动和互动的网页体验。 ...

    用jxl实现java对Excel表格的增删改查

    在Java编程环境中,处理Excel文件是一项常见的任务,特别是在数据导入导出、数据分析或者报表生成时。JXL是一个广泛使用的开源库,它允许开发者通过Java语言方便地读写Microsoft Excel文件。本文将深入探讨如何利用...

    各种jar包

    这对于需要将数据导出为Excel格式或者从Excel文件导入数据的应用场景非常有用。 5. **COS (China Online System)**: COS是早期的Java库,用于处理与FTP服务器交互,包括上传、下载文件等功能。这个库在一些旧项目...

    企业信息管理系统

    这些库在企业信息管理系统中起到数据导出的作用,允许用户将系统内的数据导出为Excel格式,方便数据分析和报表生成。 最后,`word 报表`可能指的是使用Java库如Apache POI来创建和编辑Microsoft Word文档。这可以...

    noka-tag-5.0.26-bin.zip

    在Noka 5.0.26版本中集成JXL,意味着开发者可以轻松地将数据导出到Excel格式,或者从Excel文件中导入数据,这对于数据报告和分析场景非常实用。 Prototype 1.6.3则是一个JavaScript库,它提供了许多高级的DOM操作...

    在线请假系统

    在在线请假系统中,JXL库用于将请假申请数据导出到Excel文档。 第三部分:系统总体设计 在线请假系统的总体设计涉及到多个方面,包括系统架构、数据库设计、用户界面设计和系统测试等。 系统架构是在线请假系统的...

    soaoffice示例代码

    soaoffice示例代码 SOAOffice是一种中间件软件,不能直接给最终用户使用,需要软件编程人员...需要控制不同的用户在Word/Excel中不同的区域中编辑权限的; 23.需要在企业局域网内架设在线Office文档中心、知识管理的;

    SOAOFFICE - 微软 OFFICE 中间件

    24.需要在web页面导入导出Excel单元格数据的; ……… SOAOFFICE中间件包括三个内置组件:SOAExcel、SOAWord、SOAPowerPoint。另外企业版还包括支持PDF文件的SOAPDF组件。 SOAOFFICE 中间件采用标准HTTP传输协议,...

    java javamail 发送邮件 源代码 例子

    - `java导入导出excel操作(jxl) - 导出Excel - JavaEye技术网站.htm`:关于使用jxl库读写Excel文件的教程。 - `破解无线路由密码...`:这些文件看似与Java编程无关,而是关于无线网络的安全和破解教程。 - `EJB初学...

    程序员实习总结.doc

    - 在数据导入导出方面,实习生可能接触到了两种主要技术:Apache POI(支持Excel 07和03版本)和JXL(仅支持Excel 03版本)。尽管POI支持更多格式,但在效率上,JXL可能更具优势。 7. **学习与成长**: - 学习...

    ttshop-b-s-:ttshop bs 在线销售管理系统

    ttshop-b-s-ttshop b/s... 结合 jxl ,实现基本数据利用 excel导出数据和导入数据功能.10 . 系统中大量利用到 jquery ajax,实现极少页面跳转完成系统各种功能操作11. 产品图片的 html5 ajax上传 , 美图秀秀 web 插件进行

    html,css,javascript,jquery,java,oracle技术资料

    6. **JXL_API .chm**:JXL是一个用于读写Excel文件的Java库,对于处理数据导入导出非常有用。API文档将介绍如何使用JXL来操作Excel表格。 7. **Ext2.2API中文版.CHM**:ExtJS是一个用于构建富互联网应用程序的...

    ssh+dwr坚决不冲突的jar

    DWR是一种允许Web浏览器与服务器进行实时交互的技术,它通过Ajax提供JavaScript到服务器端的方法调用,使前端页面能动态更新数据,实现类似桌面应用的用户体验。 描述中提到的"下好用就顶一下"表明这个压缩包可能...

Global site tag (gtag.js) - Google Analytics