1.同一个页面单个导出
1.1 增加导出按钮
找到对应的页面,导出按钮增加在合适的位置,【count】关键字可调整排序。
<div style="display: inline-block; float:right;vertical-align: middle;"><ui:toolbar id="toolbarOperate" count="3"><c:import url="/pro/word/common/common_downloadExcel.jsp"><c:param name="type" value="htbb" /></c:import></ui:toolbar>
</div>
1.2 找到Action
找到com.landray.kmss.pro.word.actions.ProExcelDownloadAction类的downloadExcel方法
<?xml version="1.0" encoding="UTF-8"?>
<beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><bean class="com.landray.kmss.pro.word.actions.ProWordDownloadAction"parent="KmssBaseAction" name="/pro/word/proWordDownload.do"lazy-init="true"></bean><beanclass="com.landray.kmss.pro.word.actions.ProExcelDownloadAction"parent="KmssBaseAction"name="/pro/word/proExcelDownload.do"lazy-init="true"></bean>
</beans>
1.3 增加导出逻辑
在action获取到type进行判断,调用相应的导出方法(此处的type为之前的<c:param>设置的入参)。
else if ("htbb".equals(type)) {// 测量产值计算表// 导出的数据getProExcelDownloadServiceImp().exportHtbbTable(request, response);}
1.4 增加实现类导出方法
src\com\landray\kmss\pro\word\service\spring\ProExcelDownloadServiceImp类增加相应的方法,根据需求设置相应的样式getXmylbArrayList(request, response)方法获取导出的具体内容,按相应内容写出后关闭流。
@Overridepublic void exportXmylbTable(HttpServletRequest request, HttpServletResponse response) throws Exception {ExcelWriter writer = ExcelUtil.getWriter();writer.renameSheet(0, "项目一览表");// 跳过前两行writer.passRows(2);//全局CellStyle cellStyle = writer.getCellStyle();//创建标题字体Font font = writer.createFont();font.setFontHeightInPoints((short) 11);font.setFontName("宋体");cellStyle.setFont(font);//全局 宽15writer.setColumnWidth(-1, 30);//全局 高25writer.setDefaultRowHeight(15);cellStyle.setWrapText(true);//标题样式CellStyle headCellStyle = writer.getHeadCellStyle();headCellStyle.setAlignment(HorizontalAlignment.CENTER);Font headFont = writer.createFont();headFont.setFontName("宋体");headFont.setFontHeightInPoints((short) 12);headFont.setBold(true);headCellStyle.setFont(headFont);//第一行单独标题样式CellStyle oneHeadCellStyle = writer.createCellStyle();// 设置边框oneHeadCellStyle.setBorderBottom(BorderStyle.THIN);oneHeadCellStyle.setBorderTop(BorderStyle.THIN);oneHeadCellStyle.setBorderLeft(BorderStyle.THIN);oneHeadCellStyle.setBorderRight(BorderStyle.THIN);oneHeadCellStyle.setAlignment(HorizontalAlignment.CENTER);oneHeadCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);Font oneHeadFont = writer.createFont();oneHeadFont.setFontName("宋体");oneHeadFont.setFontHeightInPoints((short) 15);oneHeadFont.setBold(true);oneHeadCellStyle.setFont(oneHeadFont);//第二行单独标题样式CellStyle twoHeadCellStyle = writer.createCellStyle();// 设置边框twoHeadCellStyle.setBorderBottom(BorderStyle.THIN);twoHeadCellStyle.setBorderTop(BorderStyle.THIN);twoHeadCellStyle.setBorderLeft(BorderStyle.THIN);twoHeadCellStyle.setBorderRight(BorderStyle.THIN);twoHeadCellStyle.setAlignment(HorizontalAlignment.LEFT);twoHeadCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);Font twoHeadFont = writer.createFont();twoHeadFont.setFontName("宋体");twoHeadFont.setFontHeightInPoints((short) 15);twoHeadFont.setBold(true);twoHeadCellStyle.setFont(twoHeadFont);int lastColumn = 27;// 单独设置样式,数据写入后再设置writer.setRowHeight(0, 28);writer.setRowHeight(1, 20);writer.setColumnWidth(0, 10);writer.merge(0, 0, 0, lastColumn, "项目一览表", oneHeadCellStyle);//一次性写出内容,强制输出标题writer.write(getXmylbArrayList(request, response), true);//导出的为xlsresponse.setContentType("application/vnd.ms-excel;charset=utf-8");String fileName = new String("项目一览表.xls".getBytes("GBK"), "iso8859-1");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);ServletOutputStream out = response.getOutputStream();writer.flush(out, true);writer.close();IoUtil.close(out);}
1.5 设置导出内容
将对应的参数舍之道row的map中,然后添加到rows的ArrayList中,设置好格式后,在1.4调用,进行导出。
private ArrayList<Map<String, Object>> getXmylbArrayList(HttpServletRequest request, HttpServletResponse response) throws Exception {ArrayList<Map<String, Object>> rows = new ArrayList<>();DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");List<ScProduceRws> list = getXmylbList(request, response);for (int i = 0; i < list.size(); i++) {ScProduceRws scProduceRws = list.get(i);Map<String, Object> row = new LinkedHashMap<>();row.put("序号", String.valueOf(i + 1));// 序号row.put("项目编号", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdProject().getFdNo());row.put("项目名称", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdProject().getFdName());// 获取工程状态ScProduceGcjd scProduceGcjd = scProduceRws.getFdProduceGcjd();String fdGcztName = EnumerationTypeUtil.getColumnEnumsLabel("sc_produce_gczt", scProduceGcjd.getFdGczt());if ("S".equals(scProduceRws.getFdUnit())) {// 规划设计GhPlanningCpcb ghPlanningCpcb = GhPlanningUtil.getCpcbByFdProduceGcjd(scProduceGcjd);if (ghPlanningCpcb != null) {fdGcztName = "完成";}} else if ("C".equals(scProduceRws.getFdUnit())) {// 测绘MeasureManageCheckApprove measureManageCheckApprove = MeasureManageUtil.getCheckApproveByFdProduceGcjd(scProduceGcjd);if (measureManageCheckApprove != null) {fdGcztName = "完成";}} else if ("K".equals(scProduceRws.getFdUnit())) {// 勘察KcProjectCpcb kcProjectCpcb = KcProjectUtil.getCpcbByFdProduceGcjd(scProduceGcjd);if (kcProjectCpcb != null) {fdGcztName = "完成";}}row.put("工程状态", fdGcztName);ScProduceXmxx scProduceXmxx = scProduceGcjd.getFdProduceGcxx().getFdProject();// 获取收入合同IContractManageSrhtService contractManageSrhtService = (IContractManageSrhtService) SpringBeanUtil.getBean("contractManageSrhtService");HQLInfo srContractHQLInfo = new HQLInfo();srContractHQLInfo.setWhereBlock("contractManageSrht.fdProjectId=:fdProjectId and contractManageSrht.docStatus = 30 ");srContractHQLInfo.setParameter("fdProjectId", scProduceXmxx.getFdId());srContractHQLInfo.setOrderBy("docCreateTime desc");List<ContractManageSrht> contractManageSrhtList = contractManageSrhtService.findList(srContractHQLInfo);StringBuilder srhtBh=new StringBuilder();StringBuilder srhtMc=new StringBuilder();StringBuilder srhtJe=new StringBuilder();for (ContractManageSrht contractManageSrht : contractManageSrhtList) {srhtBh.append(contractManageSrht.getFdHtbh()).append(";").append("\n");srhtMc.append(contractManageSrht.getFdHtmc()).append(";").append("\n");String format = contractManageSrht.getFdHtje()==null?"":decimalFormat.format(contractManageSrht.getFdHtje());srhtJe.append(format).append(";").append("\n");}row.put("收入合同编号", srhtBh);row.put("收入合同名称", srhtMc);row.put("收入合同金额", srhtJe);// 获取支出合同IContractManageZchtService contractManageZchtService = (IContractManageZchtService) SpringBeanUtil.getBean("contractManageZchtService");HQLInfo zcContractHQLInfo = new HQLInfo();zcContractHQLInfo.setWhereBlock("contractManageZcht.fdXmbhId=:fdProjectId");zcContractHQLInfo.setParameter("fdProjectId", scProduceXmxx.getFdId());zcContractHQLInfo.setOrderBy("docCreateTime desc");List<ContractManageZcht> contractManageZchtList = contractManageZchtService.findList(zcContractHQLInfo);StringBuilder zchtBh=new StringBuilder();StringBuilder zchtMc=new StringBuilder();StringBuilder zchtJe=new StringBuilder();for (ContractManageZcht contractManageZcht : contractManageZchtList) {zchtBh.append(contractManageZcht.getFdHtbh()).append(";").append("\n");zchtMc.append(contractManageZcht.getFdHtmc()).append(";").append("\n");String format = contractManageZcht.getFdHtje()==null?"":decimalFormat.format(contractManageZcht.getFdHtje());zchtJe.append(format).append(";").append("\n");}row.put("支出合同编号", zchtBh);row.put("支出合同名称", zchtMc);row.put("支出合同金额", zchtJe);row.put("工程编号", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdNo());row.put("工程名称", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdName());row.put("工程阶段编号", scProduceRws.getFdProduceGcjd().getFdGcjdbh());row.put("工程阶段", scProduceRws.getFdProduceGcjd().getFdCateGcjd().getFdName());row.put("任务书编号", scProduceRws.getFdRwsbh());row.put("任务书名称", scProduceRws.getFdRwsmc());row.put("工程位置", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdGcwz());row.put("工程类型", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdGclx().getFdName());row.put("项目来源", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdGcly()==null?"":EnumerationTypeUtil.getColumnEnumsLabel("sc_produce_gcly", scProduceRws.getFdProduceGcjd().getFdProduceGcxx().getFdGcly()));row.put("牵头院", scProduceRws.getFdCjy().getFdName());row.put("设总/项目负责人", scProduceRws.getFdProduceGcjd()==null?"": scProduceRws.getFdProduceGcjd().getFdSzxm()==null?"":scProduceRws.getFdProduceGcjd().getFdSzxm().getFdName());StringBuilder hdr=new StringBuilder();for (SysOrgPerson sysOrgPerson : scProduceRws.getFdHdr()) {hdr.append(sysOrgPerson.getFdName()).append(";");}row.put("核定人", hdr);row.put("成果提交日", scProduceRws.getFdCgtjr()==null?"":dateFormat.format(scProduceRws.getFdCgtjr()));row.put("经营负责人", scProduceRws.getFdJyfzr().getFdName());row.put("创建人", scProduceRws.getDocCreator().getFdName());row.put("预算产值(元)", scProduceRws.getFdYscz()==null?"":decimalFormat.format(Double.parseDouble(scProduceRws.getFdYscz())));row.put("创建时间", scProduceRws.getDocCreateTime()==null?"":dateFormat.format(scProduceRws.getDocCreateTime()));rows.add(row);}return rows;}
2<c:import>覆盖问题
在实际应用中,若一个页面仅需引入一次的导出功能时,由于
<c:import>
标签的特性限制,如果在同一页面内连续引入两个或更多的相同导出页面,即使每次引入时传递的参数各异,也会出现后引入的页面内容覆盖先引入的情况。具体表现为:无论导入多少次相同的页面,最终生效的仅仅是最后一次导入的结果,这使得基于不同参数实现区分性导出的功能失效。因此,在遇到在一个页面中通过<c:import>
标签多次引入同一导出页面且期望根据参数生成不同输出时,需要采取相应的优化措施来避免内容覆盖问题并确保各个导出请求能够独立有效执行。
3 问题修复
对于2问题做出以下优化:
(1)自定义路径参数,进行不同页面区分。
(2)自定义按钮,不用<c:import>标签。
(3)自定义拼接参数逻辑,存入到变量【param】中。
(4)自定义提交方法,对参数进行处理(此处可以复用兰陵框架定义好的)。
3.1自定义路径参数
在列表访问时,携带不同参数用以区分不同业务功能对同页面的访问(在对应的模块下的index.js中配置)。
3.1.1 规划模块
(2)找到index.jsp页面 WebContent/gh/planning/index.jsp
<ui:source type="Static">[ { "text" : "工程概况","href" : "/overview","router" : true},{ "text" : "项目进度监控","href" : "/xmgk","router" : true},] </ui:source>
(2)找到页面对应路径下的 WebContent/gh/planning/resource/js/index.js
{path: '/overview',action: {type: 'pageopen',options: {url: $var.$contextPath + '/sc/produce/sc_produce_gcjd/overviewIndex.jsp?exportType=gh&meoel=com.landray.kmss.gh.planning.model.GhPlanningZyap&main=com.landray.kmss.gh.planning.model.GhPlanningSzrm&fdModel=com.landray.kmss.gh.planning.model.GhPlanningRyap&plan=/gh/planning/kc_project/tree.jsp',target: '_rIframe'}} },
(3)找到对应的访问请求这里的【path:'/overview'】表示在对应路径的上层目录配置的访问路由名称。
(4)对路径参数进行修改,此处添加参数为【exprotType=gh】
3.1.1 勘察模块
以规划为例,对路径参数进行修改,此处添加参数为【exprotType=kc】
3.1.1 测绘模块
对路径参数进行修改,此处添加参数为【exprotType=cl】
3.2 自定义导出按钮
导出按钮传入需要的参数,此处可以只传入exprotType,代码后续判断需要取值。
<ui:button order="3" parentId="toolbarOperate01" text="Excel导出1" onclick="downloadExcel(`${param.meoel}`,'',01,`${param.exportType}`)"> </ui:button><ui:button order="3" parentId="toolbarOperate02" text="Excel导出2" onclick="downloadExcel(`${param.main}`,'',02,`${param.exportType}`)"> </ui:button><ui:button order="3" parentId="toolbarOperate03" text="Excel导出3" onclick="downloadExcel(`${param.main}`,`${param.fdModel}`,03,`${param.exportType}`)"> </ui:button>
3.3自定义拼接参数逻辑
定义变量拼接参数以及url(此处可以直接拼接,不用定义变量)
【searchParam】:查询条件
【methodParam】:方法使用参数
【url】为具体实现导出功能的SpringMvc配置的访问路径以及方法。
{window.downloadExcel = function (fdType,fdModel,isTrue,exportType) {var searchParams="";params += '&&fdProjectNo=' + $("[name=fdProjectNo]").val();params += '&&fdProjectName=' + $("[name=fdProjectName]").val();params += '&&fdGcjdNo='+$("[name=fdGcjdNo]").val();params += '&&fdGcxxName='+$("[name=fdGcxxName]").val();params += '&&fdRwsNo='+$("[name=fdRwsNo]").val();params += '&&fdRwsName='+$("[name=fdRwsName]").val();params += '&&fdJyfzrId='+ $("[name=fdJyfzrId]").val();params += '&&docCreatorId'+ $("[name=docCreatorId]").val();params += '&&fdCgtjr1='+ $("[name=fdCgtjr1]").val();params += '&&fdCgtjr2='+ $("[name=fdCgtjr2]").val();params += '&&docCreateTime1='+ $("[name=docCreateTime1]").val();params += '&&docCreateTime2='+ $("[name=docCreateTime2]").val();var methodParam = "&type=gcgk&fdType="+fdType+"&fdModel="+ fdModel+"&isTrue=0"+isTrue+"&exportType="+exportTypevar url = "/pro/word/proExcelDownload.do?method=downloadExcel"submitForm('${LUI_ContextPath}' + url+param, "post", "json", encodeURI(param));}});
3.4自定义提交方法
此方通用,具体实现为打开一个新的页面,逻辑执行结束后,页面自动关闭
window.submitForm = function (url, name, key, values) {var newWindow = window.parent.open(name);if (!newWindow)return false;var html = "";html += "<html><head></head><body><form id='formid' method='post' action='" + url + "'>";if (values) {html += "<input type='hidden' name='values' value='" + values + "'/>";}html += "</form><script type='text/javascript'>document.getElementById('formid').submit();";html += "<\/script></body></html>".toString().replace(/^.+?\*|\\(?=\/)|\*.+?$/gi, "");newWindow.document.write(html);return newWindow;};
3.5 结束
由于不同路径入参不同,拼接参数不同,根据不同参数执行不同业务逻辑,执行结果也会不相同,至此【2 问题】 提到的同页面引用覆盖问题,已解决。
完..