LOFTER for ipad —— 让兴趣,更有趣

点击下载 关闭
报表如何批量导出成 excel 文件
飘然轻落 2019-12-06

需求说明

报表展现后可以通过工具栏中的导出按钮将当前展现的报表导出成 excel 文件,但是在实际使用中通常会要求报表不需要展现,直接通过一些操作将报表导出成 excel 文件,并且往往会要求批量导出成 excel 文件,下面通过几个示例介绍下报表不展现,如何批量生成 excel 文件。

实现这种需求一般要用到 api 方式,批量生成 excel 文件,按照方式上来分大体上可以分为三类:

一:单表导出单 excel 多 sheet

二:多表导出单 excel 多 sheet

三:多表导出多 excel 文件

单表多 sheet

此种方式通常是报表格式固定,然后根据某个参数对数据过滤,导出 excel 时需要导出多个参数的数据,并且每个参数的数据放到同一个 excel 的不同 sheet 里,比如本例中按照地区统计订单信息,要求导出时每个地区数据导出到一个 sheet 中,地区名称做为 sheet 名,下面看下这种做法:

报表设计界面不必多说,按照需求设计就行,如下图:

报表中增加一个参数:area,用于接收地区参数,然后在数据集中通过这个参数过滤数据就行。

Api 中用到 jsp 代码如下:

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <% String report = request.getParameter( "report" );//获取报表名称 if(report==null) report="订单.rpx";//如果url上报表名为空,则取订单表 String fileName=report.substring(0,report.length()-4);//读取文件名,用于设置excel名称 String reportName = request.getRealPath("WEB-INF\\\reportFiles\\\"+report);// String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 ReportDefine rd = (ReportDefine)ReportUtils.read(reportName);//读取报表 String areas="华北,东北,西北,华南,西南";//此例按照地区循环,实际中可以接收其他参数,也可以从数据库中获取数据 String\[\] area=areas.split(","); ExcelReport er=new ExcelReport(); for(int i=0;i<area.length;i++){//按照地区做循环 Context cxt = new Context(); cxt.setParamValue("area",area\[i\]);//area是报表中定义参数,此处设置参数值   Engine engine = new Engine(rd, cxt); //构造报表引擎   IReport iReport = engine.calc(); //运算报表 er.export(area\[i\],iReport);//将报表结果设置到excel sheet里 } er.saveTo(exportPath+"/"+fileName+".xls");//生成excel %>

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <% String report = request.getParameter( "report" );//获取报表名称 if(report==null) report="订单.rpx";//如果url上报表名为空,则取订单表 String fileName=report.substring(0,report.length()-4);//读取文件名,用于设置excel名称 String reportName = request.getRealPath("WEB-INF\\\reportFiles\\\"+report);// String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 ReportDefine rd = (ReportDefine)ReportUtils.read(reportName);//读取报表 String areas="华北,东北,西北,华南,西南";//此例按照地区循环,实际中可以接收其他参数,也可以从数据库中获取数据 String\[\] area=areas.split(","); ExcelReport er=new ExcelReport(); for(int i=0;i<area.length;i++){//按照地区做循环 Context cxt = new Context(); cxt.setParamValue("area",area\[i\]);//area是报表中定义参数,此处设置参数值 Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); //运算报表 er.export(area\[i\],iReport);//将报表结果设置到excel sheet里 } er.saveTo(exportPath+"/"+fileName+".xls");//生成excel %>

这样,就会在应用根目录的 export 目录下生成对应的 excel 文件,生成 excel 文件如下:

多表多 sheet

此种情况应用于导出的 excel 由多个报表组成,然后每个报表导出到 excel 中不同 sheet 中,并且有可能每个报表的参数不同(如果参数相同,那么和示例一类似,只是按报表名称循环就行),下面看下具体实现过程:

由于不同报表参数可能会不同,所以在 api 中解析每个报表以及对应参数难度会比较大,此例要求通过 url 访问报表时,按照特定格式访问,比如:

https://localhost:6868/demo/reportJsp/exportExcel1.jsp?report={无参数报表名 1}{无参数报表名 2}{报表 1( 参数 1=value1; 参数 2=value2;…)}{报表 2( 参数 1=value1; 参数 2=value2;…)},比如:https://localhost:6868/demo/reportJsp/exportExcel1.jsp?report={test1.rpx}{test2.rpx(arg1=11;arg2=22;arg3=33)}这种方式,现在在高版本的 tomcat 中,会有一些特殊符号的限定,使用时可以将 {} 转换成对应的 urlencode 方式,{为 %7B,}为 %7B,如果有其他值的话,做对应转换就行,url 设置完成后,接下来就看下如何解析这个 url,并且批量生成 excel,代码如下:

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <%  //此JSP参数格式为:report={无参数报表名1}{无参数报表名2}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)} request.setCharacterEncoding( "UTF-8" ); String report = request.getParameter( "report" ); if( report == null || report.trim().length() == 0 ) throw new Exception( "请输入报表文件名及参数串report={无参数报表名}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)}..." ); String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 String report1=report.replace("}","");//去掉串中的} String report2=report1.substring(1,report1.length());//去掉串中的最左侧的{ String\[\] a=report2.split("\\\{");//此时串中多个报表之间用{分隔,所以此处按照该符号split生成数组 ExcelReport er=new ExcelReport(); for(int i=0;i<a.length;i++){//按数组进行循环,也就是按报表循环 if(a\[i\].lastIndexOf("(")<=0)//判断分割后的子串中是否包含(,如包含,代表有参数,不包含,则没有参数 { String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\]);//获取报表路径 String sheetName=a\[i\].substring(0,a\[i\].length()-4);//获取sheet名称 ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath);//读取报表 Context cxt = new Context(); Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); //计算报表 er.export(sheetName,iReport);//将报表结果放入sheet } else{ System.out.println("报表有参数,报表名为="+a\[i\].split("\\\(")\[0\]);//如果有参数,则按(字符split,左侧为报表名 String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\].split("\\\(")\[0\]); String sheetName=a\[i\].split("\\\(")\[0\].substring(0,a\[i\].split("\\\(")\[0\].length()-4); ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath); Context cxt = new Context(); String\[\] cs=a\[i\].split("\\\(")\[1\].replace(")","").split(";");//右侧为参数串,并且去掉参数串的),多个参数用;隔开,所以此处按照;split for(int j=0;j<cs.length;j++){//按参数循环 cxt.setParamValue(cs\[j\].split("=")\[0\],cs\[j\].split("=")\[1\]);//设置参数  } Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); er.export(sheetName,iReport); } } er.saveTo(exportPath+"/test.xls");//生成excel %>

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <% //此JSP参数格式为:report={无参数报表名1}{无参数报表名2}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)} request.setCharacterEncoding( "UTF-8" ); String report = request.getParameter( "report" ); if( report == null || report.trim().length() == 0 ) throw new Exception( "请输入报表文件名及参数串report={无参数报表名}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)}..." ); String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 String report1=report.replace("}","");//去掉串中的} String report2=report1.substring(1,report1.length());//去掉串中的最左侧的{ String\[\] a=report2.split("\\\{");//此时串中多个报表之间用{分隔,所以此处按照该符号split生成数组 ExcelReport er=new ExcelReport(); for(int i=0;i<a.length;i++){//按数组进行循环,也就是按报表循环 if(a\[i\].lastIndexOf("(")<=0)//判断分割后的子串中是否包含(,如包含,代表有参数,不包含,则没有参数 { String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\]);//获取报表路径 String sheetName=a\[i\].substring(0,a\[i\].length()-4);//获取sheet名称 ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath);//读取报表 Context cxt = new Context(); Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); //计算报表 er.export(sheetName,iReport);//将报表结果放入sheet } else{ System.out.println("报表有参数,报表名为="+a\[i\].split("\\\(")\[0\]);//如果有参数,则按(字符split,左侧为报表名 String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\].split("\\\(")\[0\]); String sheetName=a\[i\].split("\\\(")\[0\].substring(0,a\[i\].split("\\\(")\[0\].length()-4); ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath); Context cxt = new Context(); String\[\] cs=a\[i\].split("\\\(")\[1\].replace(")","").split(";");//右侧为参数串,并且去掉参数串的),多个参数用;隔开,所以此处按照;split for(int j=0;j<cs.length;j++){//按参数循环 cxt.setParamValue(cs\[j\].split("=")\[0\],cs\[j\].split("=")\[1\]);//设置参数 } Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); er.export(sheetName,iReport); } } er.saveTo(exportPath+"/test.xls");//生成excel %>

多表多 excel

此种方式和示例二类似,在实际使用中导出 excel 时要求每个报表导出成不同的 excel 文件,但是后续可能会涉及到下载问题,所以此种方式一般是要建立个临时目录,然后将多个 excel 放到临时目录内,可以进行打包下载。具体代码如下:

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <%  //此JSP参数格式为:report={无参数报表名1}{无参数报表名2}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)} request.setCharacterEncoding( "UTF-8" ); String report = request.getParameter( "report" ); if( report == null || report.trim().length() == 0 ) throw new Exception( "请输入报表文件名及参数串report={无参数报表名}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)}..." ); String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 String fileName=Double.toString(Math.random()*100000000).toString().substring(0,6); String excelPath=exportPath+"\\\"+fileName; java.io.File file = new java.io.File(excelPath); if(!file.exists()) { file.mkdirs();  } else {  } String report1=report.replace("}","");//去掉串中的} String report2=report1.substring(1,report1.length());//去掉串中的最左侧的{ String\[\] a=report2.split("\\\{");//此时串中多个报表之间用{分隔,所以此处按照该符号split生成数组 ExcelReport er=new ExcelReport(); for(int i=0;i<a.length;i++){//按数组进行循环,也就是按报表循环 if(a\[i\].lastIndexOf("(")<=0)//判断分割后的子串中是否包含(,如包含,代表有参数,不包含,则没有参数 { String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\]);//获取报表路径 String sheetName=a\[i\].substring(0,a\[i\].length()-4);//获取sheet名称 ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath);//读取报表 Context cxt = new Context(); Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); //计算报表 ReportUtils.exportToExcel2007(excelPath+"/"+sheetName+".xlsx",iReport,false); er.export(sheetName,iReport);//将报表结果放入sheet } else{ System.out.println("报表有参数,报表名为="+a\[i\].split("\\\(")\[0\]);//如果有参数,则按(字符split,左侧为报表名 String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\].split("\\\(")\[0\]); String sheetName=a\[i\].split("\\\(")\[0\].substring(0,a\[i\].split("\\\(")\[0\].length()-4); ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath); Context cxt = new Context(); String\[\] cs=a\[i\].split("\\\(")\[1\].replace(")","").split(";");//右侧为参数串,并且去掉参数串的),多个参数用;隔开,所以此处按照;split for(int j=0;j<cs.length;j++){//按参数循环 cxt.setParamValue(cs\[j\].split("=")\[0\],cs\[j\].split("=")\[1\]);//设置参数  } Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); ReportUtils.exportToExcel2007(excelPath+"/"+sheetName+".xlsx",iReport,false); } } er.saveTo(exportPath+"/test.xls");//生成excel %>

<%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="com.raqsoft.report.model.*"%> <%@ page import="com.raqsoft.report.usermodel.*"%> <%@ page import="com.raqsoft.report.view.*"%> <%@ page import="com.raqsoft.report.util.*"%> <%@ page import="com.raqsoft.report.view.excel.ExcelReport"%> <% //此JSP参数格式为:report={无参数报表名1}{无参数报表名2}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)} request.setCharacterEncoding( "UTF-8" ); String report = request.getParameter( "report" ); if( report == null || report.trim().length() == 0 ) throw new Exception( "请输入报表文件名及参数串report={无参数报表名}{报表1(参数1=value1;参数2=value2;...)}{报表2(参数1=value1;参数2=value2;...)}..." ); String exportPath=request.getRealPath("/export");//在应用根目录下建export目录,放置导出文件 String fileName=Double.toString(Math.random()*100000000).toString().substring(0,6); String excelPath=exportPath+"\\\"+fileName; java.io.File file = new java.io.File(excelPath); if(!file.exists()) { file.mkdirs(); } else { } String report1=report.replace("}","");//去掉串中的} String report2=report1.substring(1,report1.length());//去掉串中的最左侧的{ String\[\] a=report2.split("\\\{");//此时串中多个报表之间用{分隔,所以此处按照该符号split生成数组 ExcelReport er=new ExcelReport(); for(int i=0;i<a.length;i++){//按数组进行循环,也就是按报表循环 if(a\[i\].lastIndexOf("(")<=0)//判断分割后的子串中是否包含(,如包含,代表有参数,不包含,则没有参数 { String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\]);//获取报表路径 String sheetName=a\[i\].substring(0,a\[i\].length()-4);//获取sheet名称 ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath);//读取报表 Context cxt = new Context(); Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); //计算报表 ReportUtils.exportToExcel2007(excelPath+"/"+sheetName+".xlsx",iReport,false); er.export(sheetName,iReport);//将报表结果放入sheet } else{ System.out.println("报表有参数,报表名为="+a\[i\].split("\\\(")\[0\]);//如果有参数,则按(字符split,左侧为报表名 String reportPath = request.getRealPath("WEB-INF\\\reportFiles\\\"+a\[i\].split("\\\(")\[0\]); String sheetName=a\[i\].split("\\\(")\[0\].substring(0,a\[i\].split("\\\(")\[0\].length()-4); ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath); Context cxt = new Context(); String\[\] cs=a\[i\].split("\\\(")\[1\].replace(")","").split(";");//右侧为参数串,并且去掉参数串的),多个参数用;隔开,所以此处按照;split for(int j=0;j<cs.length;j++){//按参数循环 cxt.setParamValue(cs\[j\].split("=")\[0\],cs\[j\].split("=")\[1\]);//设置参数 } Engine engine = new Engine(rd, cxt); //构造报表引擎 IReport iReport = engine.calc(); ReportUtils.exportToExcel2007(excelPath+"/"+sheetName+".xlsx",iReport,false); } } er.saveTo(exportPath+"/test.xls");//生成excel %>

打包下载

文件生成到对应目录下后,可以自己单独做个链接指向这个 excel 文件下载,也可以直接生成 excel 文件后直接进行下载,在对应 jsp 文件中增加如下代码:

response.setContentType("application/msword"); response.setHeader("Content-disposition","attachment; filename="+java.net.URLEncoder.encode(fileName+".xls", "UTF-8")); BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream( exportPath+"/"+fileName+".xls")); bos = new BufferedOutputStream(response.getOutputStream()); byte\[\] buff = new byte\[2048\]; int bytesRead; while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff,0,bytesRead);  }  } catch(final IOException e) { System.out.println ( "出现IOException." + e );  } finally { if (bis != null) bis.close(); if (bos != null) bos.close();  } System.out.println ( "下载完成----------------" ); File file = new File(exportPath+"/"+fileName+".xls"); if (file.exists()) file.delete();//删除文件 实际应用中可能会需要将文件大成zip包方式,比如示例三,这个直接百度下java程序打zip包,然后下载zip包就行。

response.setContentType("application/msword"); response.setHeader("Content-disposition","attachment; filename="+java.net.URLEncoder.encode(fileName+".xls", "UTF-8")); BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream( exportPath+"/"+fileName+".xls")); bos = new BufferedOutputStream(response.getOutputStream()); byte\[\] buff = new byte\[2048\]; int bytesRead; while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff,0,bytesRead); } } catch(final IOException e) { System.out.println ( "出现IOException." + e ); } finally { if (bis != null) bis.close(); if (bos != null) bos.close(); } System.out.println ( "下载完成----------------" ); File file = new File(exportPath+"/"+fileName+".xls"); if (file.exists()) file.delete();//删除文件 实际应用中可能会需要将文件大成zip包方式,比如示例三,这个直接百度下java程序打zip包,然后下载zip包就行。

总结

本文中介绍了如何通过 api 将报表批量导出成 excel 的方法,实际中也有可能生成 pdf 或者 txt 等,思路是一样到,到时候换用不同的 api 就行。

详情链接:https://c.raqsoft.com.cn/article/1571624596905?r=gxy


推荐文章
评论(0)
联系我们|招贤纳士|移动客户端|风格模板|官方博客|侵权投诉 Reporting Infringements|未成年人有害信息举报 0571-89852053|涉企举报专区
网易公司版权所有 ©1997-2024  浙公网安备 33010802010186号 浙ICP备16011220号-11 增值电信业务经营许可证:浙B2-20160599
网络文化经营许可证: 浙网文[2022]1208-054号 自营经营者信息 工业和信息化部备案管理系统网站 12318全国文化市场举报网站
网信算备330108093980202220015号 网信算备330108093980204230011号
分享到
转载我的主页