最近使用ireport整合项目框架,并且使用PDF打印,遇到了很多坑,也学到了很多东西,所以特意来总结一番,也让其他人少走点弯路;
开发工具:Ireport 5.1.0,JDK7,eclipe,jasperReport6.1
ireport模板使用:
可以参考一下我上一篇转载的博客http://blog.csdn.net/liaodehong/article/details/51175917;
ireport的坑:
PDF不显示中文,或者乱码;
点击打开链接
ireport报错:
我们看XML里面生成的field;
<field name="traceId" class="java.lang.String"> <fieldDescription><![CDATA[追溯号]]></fieldDescription> </field>
ireport日期格式的问题:
点击日期找到属性里面的
pattern可以格式化属性;然后再去修改一下XML里面的配置
<field name="docArrivalDate" class="java.sql.Timestamp"/>
把这个改成java.util.Date,不然再后面会出现一些日期转换的问题;
ireport之编写表格:
编写表格有两种方式,一种是点击属性面板里面的table组件进行编辑
另外一种就是给text添加padding;
ireport模板基本上就这些,以后用到的话还会整理;接下来关键是和现有的系统进行整合;
我们采用的系统是spring+springMVC+ibatis;
1、继承JasperReportsMultiFormatView类,并重写fillReport()方法,在该方法中增加setUrl()实现,这样就可以在controller中指定要使用的报表模板文件了。这样做的好处是,只需要一个jasperReport配置文件,可以在controller中动态的设定报表模板url。
/** * SpringMVC + IReport整合 视图处理扩展 * @Author lyg * @Create 2016-5-4 3:00 */ public class ApplicationIReportView extends JasperReportsMultiFormatView{ private JasperReport jasperReport; public ApplicationIReportView() { super(); } @Override protected JasperPrint fillReport(Map<String, Object> model) throws Exception { if (model.containsKey("url")) { setUrl(String.valueOf(model.get("url"))); this.jasperReport = loadReport(); } return super.fillReport(model); } @Override protected JasperReport getReport() { return this.jasperReport; } }2、在/WEB-INF/jasper/目录下创建报表视图配置文件jasper-defs.xml,并指定解析器类为自定义的视图解析器类:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="iReportView" class="com.odianyun.owms.web.view.ApplicationIReportView"> <!-- <property name="url" value="/WEB-INF/jasper/report2.jasper"/> --> <property name="reportDataKey" value="jrMainDataSource"/> </bean> </beans>3、Jasper报表的渲染需要用到XmlViewResolver视图解析器,这样你的项目中就会存在多个视图解析器。需要注意的是,项目中如果使用了多个视图解析器,则需要设置order的值来区分解析器的使用顺序,order值越小则越靠前。增加XmlViewResolver视图解析器的同时,并指定其要解析的配置文件路径。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <!-- <property name="suffix" value=".jsp"/> --> </bean> <!-- 注册XmlViewResolver,用于iReport & JasperReports报表生成 --> <bean id="jasperReportResolver" class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="order"> <value>0</value> </property> <property name="location"> <value>WEB-INF/jasper-defs.xml</value> </property> </bean>另外如果我们是导出PDF的话,那么请求后缀最好是改为.pdf的,这样导出的会是PDF格式的,所以要配置一下我们的拦截器
<servlet-mapping> <servlet-name>web</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>web</servlet-name> <url-pattern>*.pdf</url-pattern> </servlet-mapping>这里要说一个小技巧,就是我报表页面的话,有一个字段是比较复杂的字表查询,我们没有比较去写一个很复杂的sql去关联,这里只需要给它预留一个空白字段,然后通过我们的数据源去填充就好了;
比如说我这里面有一个属性字段,这个属性是通过另外几张表关联出来的,这里我不通过sql语句去关联,而是先把整个收货明细给查出来,再去遍历这个明细去查这个货品属性;
还有一个小技巧就是我们通过javaBean给ireport模板填充数据,所以模板里面不需要传入查询条件,只要数据源去过滤一遍查询条件就OK了;
/** * 返回iReport报表视图 * * @param model * @return * @throws Exception */ @RequestMapping(value = ReportConstant.ASN_TASK_LIST+ReportConstant.PDF, method = RequestMethod.POST) public String report(String docGuid,HttpServletRequest request,Model model) throws Exception { List listBean=new ArrayList<>(); // 报表数据源 SysUserPO user = (SysUserPO) OwmsUtils.getCurrentUser(request); DocAsnItemVO areaVO=new DocAsnItemVO(); areaVO.setDocGuid(docGuid); //areaVO.setDocGuid("5be937b0-6899-48e8-8a63-62d1837edae4"); listBean=DocAsnItemManager.listDocAsnItemReport(areaVO, user); JRDataSource jrDataSource = new JRBeanCollectionDataSource(listBean); // 动态指定报表模板url model.addAttribute("url", "/WEB-INF/jasper/asnTaskRepost.jasper"); model.addAttribute("format", "pdf"); // 报表格式 model.addAttribute("jrMainDataSource", jrDataSource); return "iReportView"; // 对应jasper-defs.xml中的bean id }
最后是js和html页面:
<button class="btn btn-primary btn-sm" ng-click="asnReport()" type="button">打印</button>我们在一个form里面放了一个button,然后botton点击事情去提交这个请求;
$scope.asnReport =function(){ $scope.docGuid=$scope.saveContent.docGuid; document.getElementById("docGuid").value=$scope.saveContent.docGuid; //$("#docGuid").attr("value",$scope.saveContent.docGuid); var form=$("#headerForm"); form.attr("action","asnTaskList.pdf"); form.attr("method","post"); form.attr("target","_blank"); form.submit(); };