JasperReport 各种莫名奇妙问题的解决

原文地址:JasperReport 各种莫名奇妙问题的解决


也许你不曾遇到如下问题,那恭喜你,但你是否会疑惑为何我没有遇到而你们却遇到这种问题呢,我们可都是应用的struts2框架哦!!!是啊,为什么呢?

有兴趣的不妨看看这篇博文http://peterliuye.javaeye.com/blog/418001以及http://www.blogjava.net/sterning/archive/2008/01/02/172317.html,也讲述了同样的问题,都给出了相应的解决方案,咱不说前者,因为前者给我的感觉是并没有使用struts2-jasperreport-plugin,在此说说后者吧,其核心思想是修改struts-jasperreport-plugin插件代码,

原文内容如下:采用HTML格式预览时,莫名的出现一些图片的xx,但是我们并没有使用图片啊,关于这个为什么网上的资料很详细本人只是解读一下Struts2这个插件的源码最终解决图片显示问题:

protected String imageServletUrl = "/images/";
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap); 
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl);

现在明白为什么要新建一个images目录复制象素图片了吧!
  对于HTML预览时右击查看源代码出现的是相对路径,但是大多数情况下根据生成的路径不能指定到px图片,不知道是不是这个插件包本身的问题还是其它的原因,总之先做出效果来、修改上句换成绝对路径吧!
  exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, servletContext.getRealPath(File.separator) + imageServletUrl);

这个图片xx问题自然就会解决了。
  上面的方法真的可以吗?咋一看,再在本机一试,你将豁然惊喜,的确图片可以正常显示了,然若此时以你的机器作为server,到另一台机访问顿时傻眼了,因为问题依旧在,这是为什么呢?我们看一下修改前后的代码就一清二楚原因何在了:
修改前:exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl) 
这是一个web的相对请求路径,将展示server端的相对资源,在server方、client均可正常工作 
修改后:exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, servletContext.getRealPath(File.separator) + imageServletUrl) 
这是一个web的绝对请求路径,将展示server端的绝对路径资源,也就是含有实际盘符信息的资源,以server作为client机访问完全正常,因为实际盘符信息存在client(serve)r方,然而到脱离server的client方访问就异常了,因为请求的实际资源并不在此时的client机(尽管依旧在server机)。
那究竟如何解决如题问题呢?治病需除根,问题的核心在于struts2拦截的太多了,他把我们jasperreport需要的图片资源请求:

<img src="/webserver/images/px"/>中的src内容作为action来处理了,后台server会报类似:no aciont or result for namespace xxx action images/px这样的warning,这是为什么呢?为什么同样的struts2有人遇到如此烦恼的问题,而有人纳闷为何这傻瓜遇到而我没有遇到(偷着乐,嘻嘻),难道真的第三方插件出问题了?

遇到不遇到取决于我们使用的struts2的版本,若你用的是struts2.0系列(如2.0.11,2.0.14),恭喜你,无此问题烦恼,若你像我一样用了struts2.1.6,那不好意思,我们有缘了,你肯定会搜到此篇博文。问题解决方案:

在struts.xml中加入 <constant name="struts.action.extension" value="action"/> 
如此解决的原因:sturts2默认的后缀扩展时action,是在struts2-core-xxxxx.jar的org.apache.struts2下的default.properties中定义的,正常情况下是
 struts.action.extension=action,而在struts2.1.6中,却是struts.action.extension=action,,

多了两个逗号, 这便是问题的所在,如此的配置使得struts2的拦截器除了拦截后缀为action的url及uri外,还额外拦截任何没有后缀的url及uri,那些不期待被拦截的咚咚也被拦截去找相应的action了,致使产生了如题问题,怨啊~~~怎么会是~~~是tmd挺怨的,原来默认的咚咚里面冒出了"臭虫"。
 然后创建一个images文件夹添加px到该文件:记住是px而不是px.jpg.


Servlet应用如下:

方案一隐藏:

  1. exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, false);

方案二隐藏:添加图片images目录和文件px

 

exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, true);
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + "/images/px.");

 

struts2应用添加:添加图片images目录和文件px

<constant name="struts.action.extension" value="action"/>

 

把jasperreport.jar包放到JDK/lib下,把JDK的Tools.jar和数据库驱动包放到iReport/lib下;如果iReport/lib下没有iTextAsian.jar包,要下载。

总结:

1.Report0.3.2Jasperreport0.5.3以上都要求JDK1.4以上版本,所以要注意Oracle9装好会自动把java环境设为Oracle自带的JDK1.3.1,会导致无法运行iReport。这时候卸了JDK或者jbuilder,重装一下。如果项目用ORACLE的话,机器上至少装oracle客户端了,一般可能先装JDK,再装oracle什么的,就出麻烦了!


2.   安装完毕后第一次打开时可能菜单会出些乱码,在Options->选项->general->语言,择最上面的中文(中国),如果还不行的话就重启一下iReport一般都没问题了。


3.设计静态报表模板时,word输出格式问题,预览时总是空白页。
解决办法:可以通过设置报表属性中的“当没有数据时的显示方式”为:除detail外的所有地方。


4. net.sf.jasperreports.engine.JRRuntimeException: Could not load the following font :

pdfFontName   : STSong-Light

pdfEncoding   : Cp1252

isPdfEmbedded : false

ireport为了以PDF格式输出中文,需要在“PDF Font Name”选项中选择STSong-Light,在中文字体定义中勾选“Default”、“PDF Embedded”,“PDF Encoding”选择“UniGB-UCS2-H (Chinese Simplified)”。


5.Java.lang.IllegalStateException: getOutputStream() has already been called for this response

在写JSP程序的时候,如果程序中调用了response.getOutputStream()去向客户端输出文件等数据流,容器就会抛出这样的异常。

产生这样的异常原因:是web容器生成的servlet代码中有out.write(""),这个和JSP中调用的response.getOutputStream()产生冲突.即Servlet规范说明,不能既调用response.getOutputStream(),又调用response.getWriter(),无论先调用哪一个,在调用第二个时候应会抛出IllegalStateException,因为在jsp中,out变量实际上是通过response.getWriter得到的,你的程序中既用了response.getOutputStream,又用了out变量,故出现以上错误。
  解决方案:在程序的最后添加:out.clear(); out = pageContext.pushBody(); 或者直接用servlet写


6.detai与ColumnFooter间有一大段空白,

从 iReprot 工具列社定 [编辑]>[报表属性] ,开启后的窗口选[More...] -> [Floating column footer] 打勾


      7.在浏览器中显示JasperReports PDF文档

http://www.ensode.net/jasperreports_pdf_send_to_browser_pg2.html

把PDF直接“流向”浏览器。为此,我们必须首先通过调用ServletContext中的getResourceAsStream()方法以流形式得到编译的资源。这个方法返回一个java.io.InputStream的实例—我们可以把它作为一个参数传递给JasperRunManager类的runReportToPdfStream()方法。

 

8.分组时注意sql语句加上order by+分组字段,否则无法显示分组功能


9. jasperreports:pdf,ecxel都没出现乱码,html乱码

问题:exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
我改成:OutputStream out = response.getOutputStream();
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);

发现OutputStream还真好,不会出现乱码。



1 运行环境
    1.1 JasperReport 3.5
    JasperReports 是iReport的核心内容。它是一个强有力的开源报表产生工具,可以将内容输出到屏幕上、打印机或生成PDF, HTML, XLS, CSV和XML等文件。它完全用Java编写,并可在各种Java应用(包括J2EE或WEB应用)中用来产生动态报表内容。JasperReports 组织根据在一个XML文件中定义的报表设计通过JDBC访问关系数据库中的数据.填充报表数据之前必须先将报表设计被编译成一个jasper文件。
下载地址:
 http://jasperreports.sourceforge.net/


    1.2 iReport3.5.2
    iReport是一个制作Jasperreport XML文件的优秀可视化开发工具,通过它可以方便的设计报表模板。目前最高版本为iReport3.5.2 
下载地址: http://ireport.sourceforge.net


   1.3 iText 1.3.1
   iText是一个开放源码的Java类库,是用来生成PDF文件的。下载地址: http://itext.sourceforge.net


   1.4 iTextAsian.jar
   如果要在生成的pdf文件显示中文等亚洲字符,还必须下载itext的亚洲字符包。下载地址: http://itextdocs.lowagie.com/downloads/iTextAsian.jar


以上四个包必须加到应用程序的构建路径中或加到CLASSPATH,若是Web应用放入相应的WEB-INF\lib\中。


2 设置中文支持

    为了在报表中能够显示中文,加入以上四个包还不够(因为以上四个包仅对报表生成及中文显示提供了支持),必须设置报表上各显示对象的相关属性,各属性设置说明如下:
   
 Font        name:    宋体 (中文字体)
    PDF font name:   STSong-Light
    PDF  Encoding:  UniGB-UCS2-H(Chinese Siplified)
    PDF   Embeded: √

   
 注意:此三项的设置必须确保iTextAsian.jar亚洲语言包已经包含在项目中,否则出现编译错误.
    若读者觉得对每一个对象设置比较麻烦,可通过iReport的”Format”?”Fonts”菜单进行统一设置,并设成报表的默认字体。如下图所示:
 
3可能出现的问题
   经过以上的设置,报表中文的显示应该没什么问题了,笔者在报表的开发过程中遇到几个问题,现总结如下:


 
 3.1 问题描述
   在WinXp中运行iReport1.2.8,设计报表时将数据字段的字体设置成中文字体,调好格式后编译并运行,并使用JRViewer进行预览一切正常(中文显示正常),但使用PDF、Excel预览出现如下错误:
  
 Could not load the following font :
   pdfFontName   : STSong-Light
   pdfEncoding   : UniGB-UCS2-H
   isPdfEmbedded : true
  
 产生原因:成成PDF的亚洲语言包没有包含到项目中
  
 解决办法: 将亚洲语言包iTextAsian.jar包含到项中,可通过过iReport的”Options”?”Classpath”将 iTextAsian.jar添加Classpath中或者直接将iTextAsian.jar复制到iReport安装目录下的lib中.若是Web项目则应该将iTextAsian.jar复制到此项目的WEB-INF\lib\中.


  
 3.2 问题描述
    在WinXp中运行iReport1.2.8,设计报表时将数据字段的字体设置成中文字体,调好格式后编译并运行,并使用JRViewer进行预览一切正常(中文显示正常),使用PDF、Excel预览时无任何错误,但中文无法显示(只显示空白).
   
 产生原因:报表显示对象的PDF字体属性设置不正确
   
 解决办法: 报表对象有关字体属性的设置如下:
   
 Font        name:         宋体 (中文字体)
    PDF font name:  STSong-Light
    PDF Encoding:   UniGB-UCS2-H(Chinese Siplified)
    PDF Embeded:  
true

 
   3.3问题描述
    生成PDF、Excel文件时,中文显示一切正常,但生成Html文件时显示乱码
 
产生原因
:主要是网页编码问题
   
 解决方法
 在JSP页中生成Html时,设置 <%@ page contentType="text/html;charset=GB2312" %> 
 在Servlet中生成Html时,response.setContentType("text/html;charset=GB2312");
    另外, 我们通过查看iReport生成的jrxml(<?xml version="1.0" encoding="UTF-8" ?>)文件可以发现, iReport
保存的汉字都是UTF-8编码。了解它的编码可以有助于我们统一编码方式。


 
  1. JasperReport 常见问题
    1. .jrxml vs .jasper
      • 如果在运行时载入.jrxml, 那么每次调用还得编译, 不如预先编译成.jasper.不过预先编译的jasper,必须用同样版本的JasperReport载入,而且灵活性差些. 不过对于大部分报表,还是预先编译成jasper方便
    2. 如果批量编译jrxml,用Ant很容易解决


    3. 如何使用图片?
      • 很容易,用Image控件就可以了. 在Image Express里面可以用String来表示图片的路径, 或者用InputStream, File对象.不过不管用File还是String对象, 都不得不用绝对路径, 这显然很不灵活. 解决办法是,穿入一个$P的参数,表示图片所在的目录,然后用$P和文件名拼接出完整的绝对路径. 更好的方法是用InputStream, 例如t his.getClass().getResourceAsStream("logo.jpg") ,这时只要把图片放在当前.jasper所在的目录就可以了,不必考虑什么参数,什么路径了

    4. 显示非数据库字段变量
      • 显示如运行日期等,可以直接在Text Field里面输入new java.util.Date(), 然后把Pattern设成如mm/dd/yyyy.

    5. 动态控制某些Field是否显示
      • 每个Static Text, Text Field甚至整个Band的属性里面都有Print When Expression, 比如设成new Boolean(!$P{isDisplay}.equalsIgnoreCase("yes")), 那么只有当参数display的值为yes的时候才显示

    6. 使用Sub Report, 如何使用相对路径
      • 见1.3, 和使用图片类似, 用InputStream或者传入参数Query里面如何使用参数
      • $P!{xxx} 或者 $P{xxx} 后者只能用于类似PreparedStatement参数绑定, 而前者可替换Sql的任意部分. 在需要动态排序的时候, 前者特别有用. 比如 select a,b,c from t order by $P!{orderClause}   不管用$P还是$P!, SQL最终是以PreparedStatement方式执行的, 不必太担心性能问题   注意:参数是不能嵌套的, 比如$P{a} =‘‘$P{b}‘‘   , $P{b}=‘‘value‘‘, 不要指望$P{a}能被替换成‘‘value‘‘

    7. 如何使用图表(Graph)
      • JasperReport本身没有图表功能, 只有显示Image的功能(见4.3). iReport里有个Graph向导, 其实质是通过jFreeChart生成Image. 更另外, 更直接的做法是放一个Image控件, Image Express Class设置成java.awt.Image, 在Image Expression里通过自定义的类返回java.awt.Image对象. 例如‘‘GraphProvider.getImage($P{REPORT_DATASOURCE},title, subtitle.....)‘‘.  GraphProvider是自己的类, public static Image getImage(JRDataSource, ....)

    8. 如果显示多个图表
      • 在一张报表上显示一个图表和显示多个图表是不同的. 假设Query是select name,price,qty from xxx, 第一张图显示name-price, 第二张图显示name-qty, 如果还是按3.8的方法, 第二张图根本显示不出来! 为什么  因为传入的是JRDataSource, 而JRDataSource仅仅是对ResultSet的简单封装, 在第一张图处理完后, 游标已经到了eof位置了, 在开始处理第二张图的时候,就必然抛出游标耗尽的异常! 
      • 怎么办?自己写个JRDataSourceAdapter, 把JRDataSource对象里面的值预先保存到一个Collection (相当于一个Offline的数据集), 然后把这个Collection传个getImage方法. 具体是, 建一个Variable  mydate, 类型是java.util.Map, Calculation Type- System, Initial Value Expression是JRDataSourceAdapter.JRDataSource2Map($P{REPORT_DATA_SOURCE},new String[]{"NAME","PRICE","QTY"},new Class[]{java.lang.String.class,java.lang.Double.class,java.lang.Double.class}), JRDataSource2Map是自己写的一个Adapter. 然后在Image的Expression里面换成如‘‘GraphProvider.getImage(mydata,title, other params...), 当然得修改getImage方法
  2. Export到Excel的问题
    1. 如何去掉报表头等
      • 直接把不需要的Band删除(把其高度设为0). 如果仅仅是export到Excel的时候不需要报表头, 而输出到PDF等仍然需要保留, 那么使用print when expression, 见4.4

    2. 如果让Excel看起来整齐
      • 不要有空白地方! 首先把所有的Field设成一样高, 对齐! 把所在Band的高度也设成和Field一样高, 让Field正好放入Band. 然后调整Field的宽度, 让每个Field都相邻,没有空隙. 最后,记得设置参数: exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);

    3. 如何保留GridLine
      • 首先, 设置参数exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE); 然后,把每个Field或者Static Text框的‘‘Transparent‘‘属性都勾上

    4. 如何使字段名只显示一次
      • 如果把字段名放在ColumnHead区域, 那么输出到Excel, 会每个Page都显示一遍. 在设计Report时候, 一般会设定Page大小. 然而对于Excel, 这个Page设定仍然存在,而且往往很讨厌, 因为在Excel里, 通常希望得到连续的数据, 然而Jasper仍然会‘‘自作多情‘‘进行分页. 比如说, 设计JasperReport的时候, 设定page size为Letter, Portrait, 那么输出到Excel的时候每隔大约30行(具体取决于Field的高度), page header, column header, column foot, page foot 会被重复一次, 而且还附带一个高度为0的Excel Row, 表示Page Break的地方. 把字段名放在title band里, 可以解决字段名重复的问题, 当然page header也不要显示了. 如果需要, 可以把title band的print when expression设成只有输出Excel的时候才显示

    5. 为什么Excel里面的数据是从第二行,第B列开始显示的 
      • 因为第一行和第A列分别是用来表示page top margin 和 page left margin的. 对于Excel来说, 纯粹多余. 解决方法是把page margin 设成0. 不过如果这个report还需要以PDF等显示, 那么设成0就不好看了. 最好能动态的改变page margin. 当然,这个改变只能在外部(调用Report的地方) 进行, 在设计Report的时候是无能为力的. 不幸的是, JasperReport类居然没有setMargin的方法,只有getter. 折中的方法只能是reflect了. 
      • 代码示意如下: 
      • //use reflect to set the private field of JRBaseReport
      • java.lang.reflect.Field margin = JRBaseReport.class.getDeclaredField("leftMargin");
      • margin.setAccessible(true);
      • margin.setInt(myRpt, 0);
      • margin = JRBaseReport.class.getDeclaredField("topMargin");
      • margin.setAccessible(true);
      • margin.setInt(myRpt, 0);
      • margin = JRBaseReport.class.getDeclaredField("bottomMargin");
      • margin.setAccessible(true);
      • margin.setInt(myRpt, 0);

    6. 如何去掉Excel中隐藏的行 
      • 如前说述, 由于page break的关系, Excel中每隔几十行,就有一个高度为0的row, 即使把page botom margin设为0, 把page footer去掉都没有办法. 唯一的解决办法是把page height设为很大. 同5.5一样, 不得不使用reflect:
        • java.lang.reflect.Field pageHeight = JRBaseReport.class.getDeclaredField("pageHeight");
        • pageHeight.setAccessible(true);
        • pageHeight.setInt(myRpt, Integer.MAX_VALUE);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jasperreport是一个广泛使用报表生成工具,它能够生成多种格式的报表,包括PDF。在导出PDF报表时,有时会遇到"could not load the following font"错误,这是由于JasperReport找不到所需的字体文件导致的。 解决这个问题的方法有以下几种: 1. 确保字体文件存在:首先,需要确认所使用的字体文件确实存在于系统中。可以通过查看字体文件所在的路径,或者在系统中搜索相应的字体文件来确认。 2. 添加字体文件到classpath:如果字体文件确实存在,但是JasperReport仍然找不到,可能是因为字体文件不在classpath中。在JasperReport的classpath中添加正确的字体文件路径,以便系统可以找到并加载它们。 3. 修改JasperReport配置文件:可以通过修改JasperReport的配置文件来解决字体加载问题。在jasperreports_extension.properties文件中添加以下配置: net.sf.jasperreports.extension.registry.factory.fonts=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory 这样可以告诉JasperReport使用默认的字体扩展注册工厂,并加载相应的字体。 4. 更换字体文件:如果以上方法都无法解决问题,可以尝试将字体文件替换为其他可用的字体文件。可以找到适合的字体文件,并将其放置在JasperReport的classpath中,然后重新导出报表,看是否解决问题。 总之,解决JasperReport PDF导出错误"could not load the following font"问题的关键是确保字体文件存在且能够被系统正确加载。如果以上方法仍然无法解决问题,可能需要进一步调查系统配置和字体文件是否存在异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值