第十二章 BIRT报表的部署与配置(续) .

12.2 BIRT报表的打印和导出

birt报表在打印和导出的时候,如果出现中文字符,有可能会出现文字丢失空白,或者pdf缺少相应字体,或者直接乱码的问题,这个现象非常普遍和复杂。这是一个和环境密切相关的配置,由于中文字体涉及到很多的地方配置,主要包括五个方面,报表设计时候的字体配置,runtime的page css的配置,runtime的fontconfig的配置,linux环境的字体配置,adobe reader的字体库。故而很难达成一致的解决方案,不过本节试图给出一个推荐方案。

首先是在报表设计时,整个报表的字体要设置为宋体,主要包括表,行,单元格

当然这样去设置一个复杂的报表会很麻烦,我们可以采用css的方式,应用如下的css:

[css]  view plain copy
  1. <SPAN style="FONT-SIZE: 14px">.reportTitle{  
  2.     text-align:center;  
  3.     font-family:宋体;  
  4.     font-size:16px;  
  5.     padding-top:15pt;  
  6.     padding-bottom:17pt;  
  7.     font-weight:bold;}  
  8. .searchCondition{  
  9.     font-family:宋体;  
  10.     font-size:12px;  
  11.     font-weight:normal;  
  12.     margin-bottom:3pt;  
  13.     text-align:center;  
  14.     vertical-align:middle;}  
  15. .dataCell{  
  16.     border-color:#000000;  
  17.     border-style:solid;  
  18.     border-width:1px;  
  19.     padding-top:3px;  
  20.     padding-bottom:3px;  
  21.     text-align:center;  
  22.     font-family:宋体;  
  23.     font-size:10pt;  
  24.     vertical-align:middle;  
  25.     font-weight:normal;}  
  26. .columnName{  
  27.     border-color:#000000;  
  28.     border-style:solid;  
  29.     border-width:1px;  
  30.     background-color:#F2F2F2;  
  31.     padding-top:3px;  
  32.     padding-bottom:3px;  
  33.     text-align:center;  
  34.     font-family:宋体;  
  35.     font-size:10pt;  
  36.     vertical-align:middle;  
  37.     font-weight:bold;}</SPAN>  
[css]  view plain copy
  1. <span style="font-size:14px;">.reportTitle{  
  2.     text-align:center;  
  3.     font-family:宋体;  
  4.     font-size:16px;  
  5.     padding-top:15pt;  
  6.     padding-bottom:17pt;  
  7.     font-weight:bold;}  
  8. .searchCondition{  
  9.     font-family:宋体;  
  10.     font-size:12px;  
  11.     font-weight:normal;  
  12.     margin-bottom:3pt;  
  13.     text-align:center;  
  14.     vertical-align:middle;}  
  15. .dataCell{  
  16.     border-color:#000000;  
  17.     border-style:solid;  
  18.     border-width:1px;  
  19.     padding-top:3px;  
  20.     padding-bottom:3px;  
  21.     text-align:center;  
  22.     font-family:宋体;  
  23.     font-size:10pt;  
  24.     vertical-align:middle;  
  25.     font-weight:normal;}  
  26. .columnName{  
  27.     border-color:#000000;  
  28.     border-style:solid;  
  29.     border-width:1px;  
  30.     background-color:#F2F2F2;  
  31.     padding-top:3px;  
  32.     padding-bottom:3px;  
  33.     text-align:center;  
  34.     font-family:宋体;  
  35.     font-size:10pt;  
  36.     vertical-align:middle;  
  37.     font-weight:bold;}</span>  

reportTitle 是指的是报表标题的显示格式

searchCondition是指的是报表查询条件显示格式

(注:searchCondition 是放在表格中的一个Crid控件)

dataCell 是指的是查询数据的格式

columnName是指的是表格横标题显示的格式

一般这样问题就能解决了。但有些linux的环境缺失字体,则需要进行如下的一些配置。

如果runtime的版本低于3.7.0,也就是存在WebRoot\WEB-INF\report-engine\platform\plugins\路径

操作系统环境的配置为:

1、如果运行tomcatlinux帐号权限可以访问系统的fonts目录,则在linux下安装部分中文字体。
2、在linux建立一个目录,将此目录权限设为任意用户可读,将windows下的字体文件copy到该目录下,然后修改前边所说的fontsconfig.xml目录,增加一行 <path path="xxxxxxx" />,指向字体目录,即可解决问题。

服务器平台插件的配置如下:如果报表设置的字体不是宋体,而是Serif

(1) 需要在服务器端安装CSS样式中定义的字体。具体操作如下:

(A) 在birt工程路径WebRoot/WEB-INF/report-engine/platform/plugins/org.eclipse.birt.report.engine.fonts_2.3.0.v20080606)下存在4xml文件,分别是:fontsConfig.xml/ fontsConfig_linux.xml / fontsConfig_pdf.xml / fontsConfig_win32.xml。由于导出PDF时出现少字的情况,需要修改fontsConfig_pdf.xml配置文件

[html]  view plain copy
  1. <SPAN style="FONT-SIZE: 14px"><font-paths>  
  2. <path path="/usr/share/fonts/chinese/TrueType/simsun.ttc" />  
  3.  </font-paths></SPAN>  
[html]  view plain copy
  1. <span style="font-size:14px;"><font-paths>  
  2. <path path="/usr/share/fonts/chinese/TrueType/simsun.ttc" />  
  3.  </font-paths></span>  

(B) 在linux上安装宋体文件。步骤如下:

首先:将Windows下的宋体文件simsun.ttc,拷贝到/usr/share/fonts/chinese/TrueType/simsum

其 次 :编辑/etc/X11/fs/config 加入路径如下

[html]  view plain copy
  1. <SPAN style="FONT-SIZE: 14px">    catalogue = /usr/share/X11/fonts/misc:unscaled,  
  2.                 /usr/share/X11/fonts/75dpi:unscaled,  
  3.                 /usr/share/X11/fonts/100dpi:unscaled,  
  4.                 /usr/share/X11/fonts/Type1,  
  5.                 /usr/share/X11/fonts/TTF,  
  6.                 /usr/share/fonts/default/Type1,  
  7.                  ,  
  8.                 /usr/share/fonts/chinese/misc:unscaled,  
  9.                 /usr/share/fonts/chinese/misc,  
  10.                 /usr/share/fonts/chinese/TrueType/simsun,  
  11.                 /usr/share/fonts/chinese/TrueType</SPAN>  
[html]  view plain copy
  1. <span style="font-size:14px;">    catalogue = /usr/share/X11/fonts/misc:unscaled,  
  2.                 /usr/share/X11/fonts/75dpi:unscaled,  
  3.                 /usr/share/X11/fonts/100dpi:unscaled,  
  4.                 /usr/share/X11/fonts/Type1,  
  5.                 /usr/share/X11/fonts/TTF,  
  6.                 /usr/share/fonts/default/Type1,  
  7.                  ,  
  8.                 /usr/share/fonts/chinese/misc:unscaled,  
  9.                 /usr/share/fonts/chinese/misc,  
  10.                 /usr/share/fonts/chinese/TrueType/simsun,  
  11.                 /usr/share/fonts/chinese/TrueType</span>  


注:如果服务器中已经安装了CSS样式中的字体而且路径没有问题的话,则不需要配置上述操作。

回到3.7.0以后的版本,理论上只要按照如下的方式修改org.eclipse.birt.runtime_3.7.0.v20110615-1818.jar包中的fontsConfig_pdf.xml配置,也是能解决问题。

[html]  view plain copy
  1. <SPAN style="FONT-SIZE: 14px"><Code>  
  2. <font>  
  3. <font-aliases>  
  4. <mapping name="serif" font-family="SimSun" />  
  5. <mapping name="sans-serif" font-family="SimSun" />  
  6. <mapping name="monospace" font-family="SimSun" />  
  7. </font-aliases>  
  8. <font-encodings>  
  9. <encoding font-family="SimSun" encoding="utf-8" />  
  10. <encoding font-family="Times-Roman" encoding="Cp1252" />  
  11. <encoding font-family="Helvetica" encoding="Cp1252" />  
  12. <encoding font-family="Courier" encoding="Cp1252" />  
  13. <encoding font-family="Zapfdingbats" encoding="Cp1252" />  
  14. <encoding font-family="Symbol" encoding="Cp1252" />  
  15. <encoding font-family="STSong-Light" encoding="UniGB-UCS2-H" />  
  16. <encoding font-family="STSongStd-Light" encoding="UniGB-UCS2-H" />  
  17. <encoding font-family="MHei-Medium" encoding="UniCNS-UCS2-H" />  
  18. <encoding font-family="MSung-Light" encoding="UniCNS-UCS2-H" />  
  19. <encoding font-family="MSungStd-Light" encoding="UniCNS-UCS2-H" />  
  20. <encoding font-family="HeiseiMin-W3" encoding="UniJIS-UCS2-H" />  
  21. <encoding font-family="HeiseiKakuGo-W5" encoding="UniJIS-UCS2-H" />  
  22. <encoding font-family="KozMinPro-Regular" encoding="UniJIS-UCS2-H" />  
  23. <encoding font-family="HYGoThic-Medium" encoding="UniKS-UCS2-H" />  
  24. <encoding font-family="HYSMyeongJo-Medium" encoding="UniKS-UCS2-H" />  
  25. <encoding font-family="HYSMyeongJoStd" encoding="UniKS-UCS2-H" />  
  26. </font-encodings>  
  27. <composite-font name="all-fonts">  
  28. <font font-family="Times-Roman" catalog="Western" />  
  29. <font font-family="SimSun" catalog="Chinese" />  
  30. <font font-family="HeiseiKakuGo-W5" catalog="Japanese" />  
  31. <font font-family="HYGoThic-Medium" catalog="Korean" />  
  32. </composite-font>  
  33. </font>  
  34. </Code> </SPAN>  
[html]  view plain copy
  1. <span style="font-size:14px;"><Code>  
  2. <font>  
  3. <font-aliases>  
  4. <mapping name="serif" font-family="SimSun" />  
  5. <mapping name="sans-serif" font-family="SimSun" />  
  6. <mapping name="monospace" font-family="SimSun" />  
  7. </font-aliases>  
  8. <font-encodings>  
  9. <encoding font-family="SimSun" encoding="utf-8" />  
  10. <encoding font-family="Times-Roman" encoding="Cp1252" />  
  11. <encoding font-family="Helvetica" encoding="Cp1252" />  
  12. <encoding font-family="Courier" encoding="Cp1252" />  
  13. <encoding font-family="Zapfdingbats" encoding="Cp1252" />  
  14. <encoding font-family="Symbol" encoding="Cp1252" />  
  15. <encoding font-family="STSong-Light" encoding="UniGB-UCS2-H" />  
  16. <encoding font-family="STSongStd-Light" encoding="UniGB-UCS2-H" />  
  17. <encoding font-family="MHei-Medium" encoding="UniCNS-UCS2-H" />  
  18. <encoding font-family="MSung-Light" encoding="UniCNS-UCS2-H" />  
  19. <encoding font-family="MSungStd-Light" encoding="UniCNS-UCS2-H" />  
  20. <encoding font-family="HeiseiMin-W3" encoding="UniJIS-UCS2-H" />  
  21. <encoding font-family="HeiseiKakuGo-W5" encoding="UniJIS-UCS2-H" />  
  22. <encoding font-family="KozMinPro-Regular" encoding="UniJIS-UCS2-H" />  
  23. <encoding font-family="HYGoThic-Medium" encoding="UniKS-UCS2-H" />  
  24. <encoding font-family="HYSMyeongJo-Medium" encoding="UniKS-UCS2-H" />  
  25. <encoding font-family="HYSMyeongJoStd" encoding="UniKS-UCS2-H" />  
  26. </font-encodings>  
  27. <composite-font name="all-fonts">  
  28. <font font-family="Times-Roman" catalog="Western" />  
  29. <font font-family="SimSun" catalog="Chinese" />  
  30. <font font-family="HeiseiKakuGo-W5" catalog="Japanese" />  
  31. <font font-family="HYGoThic-Medium" catalog="Korean" />  
  32. </composite-font>  
  33. </font>  
  34. </Code> </span>  

但实际上org.eclipse.birt.runtime_3.7.0.v20110615-1818.jar是经过数字指纹加密的,如果把fontsConfig_pdf.xml添加进去后,会导致字体包失效。这个时候weblogic会寻找自己类库中的别的字体包,如果weblogic的字体包比较完整,那么也能导出或者打印正常的pdf.

官方的文档是这样说明的:

BIRT从以下路径开始搜索字体,如果是WINDOWS的系统,如下路径
■ /windows/fonts for drives A through G
■ /WINNT/fonts for drives A through G
如果是linux的系统,则搜索以下路径
■ /usr/share/fonts/default/TrueType
■ /usr/share/fonts/truetype
如果pdf显示空白或者乱码,需要把相应的字体放置在以上的路径下.另一种方法是不必放在那儿,但要在系统中设置环境变量 BIRT_FONT_PATH.指向需要的字体。
 

至于打印时超出纸张边界,这个是需要在master page中进行设置

默认是A4 纸张:210mm*297mm 

A3 纸张:297mm*420mm 

根据报表实际长宽大小进行设置:在Master page 中的General中进行设置。

打印时出现pdf汉字丢失或者乱码时的另一个解决方案是用html格式打印,因为目前浏览器支持的字符集是相当全面的。

另外还有一种方式可以自定义导出的格式与方法,不过难度稍高,就是扩展"org.eclipse.birt.report.engine.dataExtraction"

用户完全可以基于已经实现的导出代码,实现自已的导出格式,如导出为XML格式,甚至可以保存到数据库。

下面我将给出一个大致的实现步骤:

1) eclipse下,新建plugin project
2) 修改plugin.xml,添加extenion point定义。举例如下:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension point="org.eclipse.birt.report.engine.dataExtraction">
<dataExtraction 
id = "org.eclipse.birt.report.engine.dataextraction.xml"
name = "XML"
format = "xml"
mimeType = "text/xml"
class = "org.eclipse.birt.report.engine.dataextraction.xml.DataExtractionImpl"/>
</extension>
</plugin>


注意,id, name, format,mimeType, class都是必须的。

3) 实现IDataExtractionExtension接口
该接口主要有三个方法:
public void initilize( IReportContext context, IDataExtractionOption option ) throws BirtException
public void output( IExtractionResults results ) throws BirtException
public void release( )

initialize方法会传入报表相关的IReportContext对象,如果需要获取报表相应的信息,可以通过该对象。

IDataExtractionOption对象是从BIRT viewer传入的一些参数。
如:
(Map) this.option.getOption( "birt.viewer.parameters" )--得到viewer相关的参数(包含用户在url上传入的自定义参数)
(Locale)this.option.getOption("birt.viewer.locale")--得到locale信息
(String[])this.option.getOption("birt.viewer.export.columns")--得到选中的columns

具体的实现逻辑可以在output方法里实现,应该非常容易理解。

下面给出output的方法的实现

[java]  view plain copy
  1. public void output( IExtractionResults results )  
  2. throws BirtException{  
  3. String[ ] columnNames = (String[ ]) selectedColumnNames;  
  4. try {  
  5. outDocument = createNewDocument ( );  
  6. catch (Exception e) {  
  7. e.printStackTrace();  
  8. }  
  9. //create root element of output XML document   
  10. Element rootElement = outDocument.createElement( "Report" );  
  11. rootElement.appendChild( outDocument.createComment("Extract report data in XML format" ));  
  12. outDocument.appendChild( rootElement );  
  13. Element pRow = outDocument.createElement( "Properties" );  
  14. rootElement.appendChild( outDocument.createComment("Lists the report properties, such as name, locale,  
  15. encoding, user parameters" ));  
  16. rootElement.appendChild( pRow );  
  17. Element nodeReportName = outDocument.createElement( "ReportName" );  
  18. nodeReportName.appendChild(outDocument.createTextNode( reportName ));  
  19. pRow.appendChild( nodeReportName );  
  20. Element nodeLocale =outDocument.createElement( "Locale" );  
  21. nodeLocale.appendChild(outDocument.createTextNode(locale.getDisplayLanguage( ) ));  
  22. pRow.appendChild( nodeLocale );  
  23. Element nodeEncoding =outDocument.createElement( "Encoding" );  
  24. nodeEncoding.appendChild( outDocument.createTextNode( encoding ));  
  25. pRow.appendChild( nodeEncoding );  
  26. Element nodeParameters = outDocument.createElement( "Parameters" );  
  27. nodeParameters.appendChild(outDocument.createTextNode( userParameters ));  
  28. pRow.appendChild(nodeParameters);  
  29. try {  
  30. // if selected columns are null or empty,   
  31. returns all columns  
  32. if ( columnNames == null || columnNames.length <= 0 ){  
  33. int count =results.getResultMetaData( ).getColumnCount( );  
  34. columnNames = new String[ count ];  
  35. for ( int i = 0; i < count; i++ ){  
  36. String colName =results.getResultMetaData( ).getColumnName(i);  
  37. columnNames[i] = colName;  
  38. }  
  39. }  
  40. IDataIterator iData = null;  
  41. if ( results != null ){  
  42. iData = results.nextResultIterator( );  
  43. if ( iData != null && columnNames.length > 0 ){  
  44. String[ ] values =new String[ columnNames.length ];  
  45. while ( iData.next( ) ){  
  46. Element row =outDocument.createElement( "Row" );  
  47. rootElement.appendChild( row );  
  48. for (int i = 0; i < columnNames.length;i++){  
  49. String columnName =results.getResultMetaData( ).getColumnName( i );  
  50. values[i] = getStringValue(iData.getValue( columnNames[i] ),isLocaleNeutral, locale );  
  51. Element node =outDocument.createElement(columnName);  
  52. node.appendChild(outDocument.createTextNode(values[ i ] ));  
  53. row.appendChild( node );  
  54. }  
  55. }  
  56. }  
  57. }  
  58. if ( encoding != null && encoding.trim( ).length( ) > 0 ){  
  59. outputStream.write(serialize( outDocument ).getBytes(encoding.trim( )));  
  60. }  
  61. else{  
  62. outputStream.write( serialize( outDocument ).getBytes( ));  
  63. }  
  64. }  
  65. catch ( Exception e ){  
  66. }  
  67. }  
[java]  view plain copy
  1. public void output( IExtractionResults results )  
  2. throws BirtException{  
  3. String[ ] columnNames = (String[ ]) selectedColumnNames;  
  4. try {  
  5. outDocument = createNewDocument ( );  
  6. catch (Exception e) {  
  7. e.printStackTrace();  
  8. }  
  9. //create root element of output XML document  
  10. Element rootElement = outDocument.createElement( "Report" );  
  11. rootElement.appendChild( outDocument.createComment("Extract report data in XML format" ));  
  12. outDocument.appendChild( rootElement );  
  13. Element pRow = outDocument.createElement( "Properties" );  
  14. rootElement.appendChild( outDocument.createComment("Lists the report properties, such as name, locale,  
  15. encoding, user parameters" ));  
  16. rootElement.appendChild( pRow );  
  17. Element nodeReportName = outDocument.createElement( "ReportName" );  
  18. nodeReportName.appendChild(outDocument.createTextNode( reportName ));  
  19. pRow.appendChild( nodeReportName );  
  20. Element nodeLocale =outDocument.createElement( "Locale" );  
  21. nodeLocale.appendChild(outDocument.createTextNode(locale.getDisplayLanguage( ) ));  
  22. pRow.appendChild( nodeLocale );  
  23. Element nodeEncoding =outDocument.createElement( "Encoding" );  
  24. nodeEncoding.appendChild( outDocument.createTextNode( encoding ));  
  25. pRow.appendChild( nodeEncoding );  
  26. Element nodeParameters = outDocument.createElement( "Parameters" );  
  27. nodeParameters.appendChild(outDocument.createTextNode( userParameters ));  
  28. pRow.appendChild(nodeParameters);  
  29. try {  
  30. // if selected columns are null or empty,  
  31. returns all columns  
  32. if ( columnNames == null || columnNames.length <= 0 ){  
  33. int count =results.getResultMetaData( ).getColumnCount( );  
  34. columnNames = new String[ count ];  
  35. for ( int i = 0; i < count; i++ ){  
  36. String colName =results.getResultMetaData( ).getColumnName(i);  
  37. columnNames[i] = colName;  
  38. }  
  39. }  
  40. IDataIterator iData = null;  
  41. if ( results != null ){  
  42. iData = results.nextResultIterator( );  
  43. if ( iData != null && columnNames.length > 0 ){  
  44. String[ ] values =new String[ columnNames.length ];  
  45. while ( iData.next( ) ){  
  46. Element row =outDocument.createElement( "Row" );  
  47. rootElement.appendChild( row );  
  48. for (int i = 0; i < columnNames.length;i++){  
  49. String columnName =results.getResultMetaData( ).getColumnName( i );  
  50. values[i] = getStringValue(iData.getValue( columnNames[i] ),isLocaleNeutral, locale );  
  51. Element node =outDocument.createElement(columnName);  
  52. node.appendChild(outDocument.createTextNode(values[ i ] ));  
  53. row.appendChild( node );  
  54. }  
  55. }  
  56. }  
  57. }  
  58. if ( encoding != null && encoding.trim( ).length( ) > 0 ){  
  59. outputStream.write(serialize( outDocument ).getBytes(encoding.trim( )));  
  60. }  
  61. else{  
  62. outputStream.write( serialize( outDocument ).getBytes( ));  
  63. }  
  64. }  
  65. catch ( Exception e ){  
  66. }  
  67. }  

4) 最后一步当然是发布了,非常简单,如果是3.7.0以前的版本,则打包成plugin,然后放到WEB-INF/platform/plugins下就可以了,注意BIRT已经有了一个org.eclipse.birt.report.engine.dataextraction.csv.jarplugin,和它放一起就行了,3.7.0以后的版本直接放在WEB-INF/lib下即可

5)打开页面,在export dialog里就会看到多了一个XML的导出选项了。

具体怎么实现导出成XML格式,还要实现其它接口的方法,在后面的BIRT报表的扩展中会详细的说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值