水晶報表的jsp實現(開發工具:bea weblogic workshop)
發表于:2007-07-01來源:作者:點擊數:
標簽:
最近為客戶 開發 一個mis系統,java技術,b/s結構.客戶要求系統的報表采用水晶報表. 怎樣在jsp中實現水晶報表呢?找遍了所有的資料,水晶報表的web實現倒是很多,但都講的是微軟的.net方案.jsp中如何實現水晶報表的動態顯示呢? 經過一段時間的痛苦摸索,現在把我的
最近為客戶
開發一個mis系統,java技術,b/s結構.客戶要求系統的報表采用水晶報表.
怎樣在jsp中實現水晶報表呢?找遍了所有的資料,水晶報表的web實現倒是很多,但都講的是微軟的.net方案.jsp中如何實現水晶報表的動態顯示呢?
經過一段時間的痛苦摸索,現在把我的方案介紹給大家,希望各位大哥批評指正
我的問題:
需要動態的顯示水晶報表,并且要根據我傳遞的一個參數(BH)的值動態的顯示數據.并且要可以把水晶報表導出為word,excel,pdf等格式
我的解決方案:
一:下載 crystal reports 10 for BEA weblogic workshop
二:安裝crystal reports 10 for BEA weblogic workshop;
三:如果安裝成功,則在C:\Program Files\Common Files\Crystal Decisions\2.5\bin目錄下,可以找到CRDB_JavaServer.ini文件.該文件很重要,里面的內容
關系到水晶報表如何訪問
數據庫.我的水晶報表采用jdbc的方式訪問
oracle數據庫,配置如下:
[Common]
PATH = C:\bea\jdk141_05\bin
CLASSPATH = C:\Projects\Drivers\jdbc\classes12.jar;
C:\Projects\Drivers\jdbc\msbase.jar;
C:\Projects\Drivers\jdbc\ms
sqlserver.jar;
C:\Projects\Drivers\jdbc\msutil.jar;
C:\Projects\Drivers\jdbc\common.jar;
C:\Projects\Drivers\jdbc\db2fs.jar;
C:\Projects\Drivers\jdbc\db2java.zip;
C:\Projects\Drivers\jdbc\db2j
clearcase/" target="_blank" >cc.jar;
C:\Projects\Drivers\jdbc\weblogic.jar;
D:/Progra~1/IBM/WebSph~1/Applic~1\v5.1.1\runtimes\base_v51\lib\naming.jar;
D:/Progra~1/IBM/WebSph~1/Applic~1\v5.1.1\runtimes\base_v51\lib\namingclient.jar;
D:/Progra~1/IBM/WebSph~1/Applic~1\v5.1.1\runtimes\base_v51\lib\namingserver.jar;
D:/Progra~1/IBM/WebSph~1/Applic~1\v5.1.1\runtimes\base_v51\lib\cmImpl.jar;
D:/Progra~1/IBM/WebSph~1/Applic~1\v5.1.1\runtimes\base_v51\lib\j2cImpl.jar;
C:/projects/drivers/jdbc/weblogic.jar;
C:\Program Files\Common Files\Crystal Decisions\2.5\bin\CRDBJavaServer.jar;
C:\bea\weblogic81\server\lib\ojdbc14.jar
IORFileLocation = ${TEMP}
JavaServerTimeout = 1800
JVMMaxHeap = 64000000
JVMMinHeap = 32000000
[CRDB_JDBC]
CacheRowSetSize = 100
JDBCURL = jdbc:oracle:thin:@192.168.1.99:1521:pwsc
JNDIURL =
JDBCUserName = testuser
JDBCDriverName = oracle.jdbc.driver.
OracleDriver
JNDIUserName = weblogic
JNDIConnectionFactory =
JNDIInitContext = /
GenericJDBCDriverBehavior = DB2
[CRDB_XML]
PREREADNBYTE = 5000
CacheRowSetSize = 100
XMLLOCALURL =
SCHEMALOCALURL =
XMLHTTPURL =
SCHEMAHTTPURL =
USETEMPFile = TRUE
以上是配置文件,需要說明的是:
1:由于我采用的是jdbc的方式訪問數據庫,所以CLASSPATH中一定要把C:\bea\weblogic81\server\lib\ojdbc14.jar加進去,它是jdbc的驅動
2:[CRDB_JDBC]中的:JDBCURL = jdbc:oracle:thin:@192.168.1.99:1521:pwsc 是我要訪問的數據庫名稱.JDBCUserName = testuser是設置用戶名,
JDBCDriverName = oracle.jdbc.driver.OracleDriver是jdbc驅動名稱
四:在水晶報表編輯器中編輯我要用的報表.由于我需要動態的給報表傳遞參數,所以我在報表中設置了一個參數字段,水晶報表根據這個參數字段,就可以顯示相應的
數據,參數字段命名為BH,在公式編輯器中編寫如下代碼:
IF {?BH}<>"" THEN
{GG_BPBJ.JLBH}={?BH}
ELSE
{GG_BPBJ.JLBH}="1" OR {GG_BPBJ.JLBH}<>"1"
以上代碼的意思是:如果bh參數不為空,則顯示{GG_BPBJ.JLBH}等于參數BH的記錄,否則顯示出所有的記錄
(大家可能覺得{GG_BPBJ.JLBH}="1" OR {GG_BPBJ.JLBH}<>"1"很可笑,是啊,我開始是寫成"true"了,在水晶報表編輯器中可以很好的運行,但方到web上顯示就有
問題,萬般無奈,只有如此了,:( )
五:在weblogic workshop中新建一個web項目,用右鍵選擇該項目文件夾,選擇"新建",選擇"crystal report",則在該web項目根目錄下自動新建了一個
crysta
lreportviewers10目錄,里面有顯示水晶報表需要的頁面元素系統自動添加了開發水晶報表需要的jar包,共有13個jar文件(位于WEB_INF\LIB目錄下),
并增加了一些水晶報表專用的標簽(在WEB_INF\SRC下)
六:需要特別注意的是:在WEB_INF下的web.xml文件也隨之改動,改動后的web.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//D
TD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<!-- The web.xml file is a configuration file used to control the behavior of WebLogic server.
In most cases, you will not need to modify this file. For more information on web.xml, please
consult the Web.xml Deployment Descriptor Elements chapter of the "Developing WebLogic Server
Applications" documentation on edocs.bea.com. -->
<web-app>
<display-name>Workshop Application</display-name>
<context-param>
<param-name>weblogic.httpd.inputCharset./*</param-name>
<param-value>GBK</param-value>
</context-param>
<context-param>
<param-name>crystal_image_uri</param-name>
<param-value>/webmis/crystalreportviewers10</param-value>
</context-param>
<filter>
<filter-name>PageFlowJspFilter</filter-name>
<filter-class>com.bea.wlw.netui.pageflow.PageFlowJspFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PageFlowJspFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<listener>
<listener-class>com.bea.wlw.runtime.core.servlet.WebappContextListener</listener-class>
</listener>
<!-- Standard Action Servlet Configuration (with de
bugging) -->
<servlet>
<servlet-name>messageServlet</servlet-name>
<servlet-class>com.infoearth.servlets.getTaskServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>com.bea.wlw.netui.pageflow.DynamicSubappActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/jpf-struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>config/-global</param-name>
<param-value>/WEB-INF/jpf-struts-config--global.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>drawImage</servlet-name>
<servlet-class>com.infoearth.drawimage.DrawImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>drawImage</servlet-name>
<url-pattern>drawImage</url-pattern>
</servlet-mapping>
<!-- Struts Action Servlet Mappings -->
<!-- Note that because Struts takes the *last* mapping here as the extension to add to
actions posted from forms, we must have *.do come after *.jpf. -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.jpf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>messageServlet</servlet-name>
<url-pattern>/messageServlet</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>doc</extension>
<mime-type>application/msword</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xls</extension>
<mime-type>application/msexcel</mime-type>
</mime-mapping>
<welcome-file-list>
<welcome-file>Login/loginController.jpf</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<!-- Define the NetUI tag library TLDs -->
<taglib>
<taglib-uri>netui-tags-html.tld</taglib-uri>
<taglib-location>/WEB-INF/netui-tags-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>netui-tags-databinding.tld</taglib-uri>
<taglib-location>/WEB-INF/netui-tags-databinding.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>netui-tags-template.tld</taglib-uri>
<taglib-location>/WEB-INF/netui-tags-template.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/crystal-tags-reportviewer.tld</taglib-uri>
<taglib-location>/WEB-INF/crystal-tags-reportviewer.tld</taglib-location>
</taglib>
</web-app>
其中:
<context-param>
<param-name>crystal_image_uri</param-name>
<param-value>/webmis/crystalreportviewers10</param-value>
</context-param>
很關鍵,它設置了水晶報表專用的crystalreportviewers10路徑(第五步中自動建的crystalreportviewers10目錄),如果設置錯誤,將來點擊水晶報表自帶的
導出和打印按鈕是就會報頁面錯誤,并且水晶報表自己的各種翻頁,導出等圖標也無法正常顯示.
七:把編輯好的水晶報表(后綴命為rpt)放在一個目錄下(我自己建了一個report目錄,專門存放報表文件)
八:可以寫程序了:
1.編寫ReportInit類.作用:用于傳遞參數BH.這個類很關鍵,負責把java的參數值傳遞到水晶報表文件.
2.在頁面流中增加showRpt操作:其實就是實例化一個ReportInit類.
3.編寫viewer.jsp文件用來動態顯示水晶報表.
后面有我的源代碼,請大家批評指正.
存在的問題:
1:水晶報表導出成pdf文件時有問題:漢字顯示為亂碼,不知何故?此問題困擾我幾個月了,沒法解決
2:無法把打印/導出頁面
漢化:在crystalreportviewers10\js目錄下有一系列strings命名的js文件,我猜測是用來國際化頁面的,可是我修改
strings_zh,js,strings_en.js,沒有什么效果.
3:在瀏覽器中顯示水晶報表后,關閉顯示頁面,該水晶報表依然和數據庫連接,(可由select * from v$session 查看oracle的連接數).如果在
viewer.jsp中加入斷開連接的語句:
viewer.dispose();
rptSource.dispose();
則只能顯示一頁報表.并且打印和導出不能工作.
以上問題困擾我很久,雖然并不影響使用,但心中還是不是很爽.希望高手指點.
源程序:
/*
* Create Date: 2004-8-14 11:06
* Create By: 李春雷
* purpose:設置水晶報表的查詢參數(目前支持7個參數的查詢,有用的參數為編號)
*/
package com.infoearth.report;
import com.crystaldecisions.report.web.viewer.*;
import com.crystaldecisions.sdk.occa.report.data.*;
import com.crystaldecisions.reports.reportengineinterface.JPEReportSourceFactory;
import com.crystaldecisions.sdk.occa.report.reportsource.IReportSourceFactory2;
import com.crystaldecisions.sdk.occa.report.reportsource.IReportSource;
public class ReportInit
{
private IReportSource rptSource;
private Fields fields;
public ReportInit(){
rptSource = null;
fields = null;
}
public IReportSource getRptsource(){
return rptSource;
}
public Fields getFields(){
return fields;
}
public boolean setReport(String fname,String rptID){
//獲得查詢條件
String FileName = fname + ".rpt";
String BH = rptID;
String path = "report/"+FileName; //報表文件路徑
try{
IReportSourceFactory2 rsf = new JPEReportSourceFactory();
java.util.Locale localetest = java.util.Locale.CHINA;
rptSource = (IReportSource)rsf.createReportSource(path,localetest);
fields = new Fields();
ParameterField pfield1 = new ParameterField(); //編號
ParameterField pfield2 = new ParameterField(); //單位
ParameterField pfield3 = new ParameterField(); //人
ParameterField pfield5 = new ParameterField(); //FIELD5
ParameterField pfield6 = new ParameterField(); //FIELD6
ParameterField pfield4_KSSJ = new ParameterField(); //開始時間
ParameterField pfield4_JSSJ = new ParameterField(); //結束時間
Values vals1 = new Values();
Values vals2 = new Values();
Values vals3 = new Values();
Values vals5 = new Values();
Values vals6 = new Values();
Values vals4_KSSJ = new Values();
Values vals4_JSSJ = new Values();
ParameterFieldDiscreteValue pfieldDV1 = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV2 = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV3 = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV5 = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV6 = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV4_KSSJ = new ParameterFieldDiscreteValue();
ParameterFieldDiscreteValue pfieldDV4_JSSJ = new ParameterFieldDiscreteValue();
//設置第一個參數:編號
pfield1.setReportName("");
pfield1.setName("BH");
pfieldDV1.setValue(BH);
pfieldDV1.setDescription("編號");
vals1.add(pfieldDV1);
pfield1.setCurrentValues(vals1);
//設置第二個參數:單位部門
pfield2.setReportName("");
pfield2.setName("DW");
pfieldDV2.setValue("");
pfieldDV2.setDescription("發單部門");
vals2.add(pfieldDV2);
pfield2.setCurrentValues(vals2);
//設置第三個參數:人
pfield3.setReportName("");
pfield3.setName("REN");
pfieldDV3.setValue("");
pfieldDV3.setDescription("申請人、下達人、操作人、負責人等");
vals3.add(pfieldDV3);
pfield3.setCurrentValues(vals3);
//設置第五個查詢字段
pfield5.setReportName("");
pfield5.setName("FIELD5");
pfieldDV5.setValue("");
pfieldDV5.setDescription("查詢字段5:任務來源線路名稱等");
vals5.add(pfieldDV5);
pfield5.setCurrentValues(vals5);
//設置第六個查詢字段
pfield6.setReportName("");
pfield6.setName("FIELD6");
pfieldDV6.setValue("");
pfieldDV6.setDescription("查詢字段6:更改原因、工作內容等");
vals6.add(pfieldDV6);
pfield6.setCurrentValues(vals6);
//設置開始時間
pfield4_KSSJ.setReportName("");
pfield4_KSSJ.setName("KSSJ");
pfieldDV4_KSSJ.setValue("");
pfieldDV4_KSSJ.setDescription("開始時間");
vals4_KSSJ.add(pfieldDV4_KSSJ);
pfield4_KSSJ.setCurrentValues(vals4_KSSJ);
//設置結束時間
pfield4_JSSJ.setReportName("");
pfield4_JSSJ.setName("JSSJ");
pfieldDV4_JSSJ.setValue("");
pfieldDV4_JSSJ.setDescription("結束時間");
vals4_JSSJ.add(pfieldDV4_JSSJ);
pfield4_JSSJ.setCurrentValues(vals4_JSSJ);
//參數字段和報表關聯
fields.add(pfield1);
fields.add(pfield2);
fields.add(pfield3);
fields.add(pfield5);
fields.add(pfield6);
fields.add(pfield4_KSSJ);
fields.add(pfield4_JSSJ);
return true;
}
catch(Exception e){
System.out.println("Class:ReportInit錯誤:"+e);
return false;
}
}
}
//在頁面流中增加如下操作:
/**
* @jpf:action
* @jpf:forward name="false" path="error.jsp"
* @jpf:forward name="success" path="viewer.jsp"
*/
protected Forward showRpt()
{
String rptid = this.getRequest().getParameter("rptID");
String rptBH = this.getRequest().getParameter("rptBH");
String rptName = dbCtrl.getRptCNName(rptid);
if ((rptName!=null) && (rptBH!=null)) {
ReportInit rpt = new ReportInit();
boolean result = rpt.setReport(rptName, rptBH);
if(result==true) {
Fields fields = rpt.getFields();
IReportSource rptSource = rpt.getRptsource();
this.getSession().setAttribute("fields", fields);
this.getSession().setAttribute("rptSource", rptSource);
return new Forward("success");
} else {
return new Forward("false");
}
}
return new Forward("false");
}
//viewer.jsp用來動態顯示水晶報表.viewer.jsp的內容如下:
<%@ page language="java" contentType="text/html;charset=utf-8"%>
<%@ page import= "com.crystaldecisions.report.web.viewer.*,
com.crystaldecisions.sdk.occa.report.data.*,
com.crystaldecisions.reports.reportengineinterface.JPEReportSourceFactory,
com.crystaldecisions.sdk.occa.report.reportsource.IReportSourceFactory2,
com.crystaldecisions.sdk.occa.report.reportsource.IReportSource"%>
<%@ taglib uri="netui-tags-html.tld" prefix="netui"%>
<%
//fields rptSource
//String name = (String)request.getAttribute("nametest");
//System.out.println("name="+name);
%>
<!-- ../crystalreportviewers10/css/default.css -->
<LINK rel="stylesheet" type="text/css" href="../crystalreportviewers10/css/default.css">
<%
IReportSource rptSource = (IReportSource)session.getAttribute("rptSource");
Fields fields = (Fields) session.getAttribute("fields");
ConnectionInfos connInfos = new ConnectionInfos();
IConnectionInfo connInfo1 = new ConnectionInfo();
connInfo1.setUserName("testuser");
connInfo1.setPassword("test");
connInfos.add(connInfo1);
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setReportSource(rptSource);
viewer.setDatabaseLogonInfos(connInfos);
viewer.setParameterFields(fields);
viewer.setEnableParameterPrompt(true);
viewer.setOwnPage(true);
viewer.setOwnForm(true);
viewer.setPrintMode(CrPrintMode.ACTIVEX);
viewer.setHasExportButton(true);
viewer.setHasPrintButton(true);
viewer.setHasLogo(false);
viewer.processHttpRequest(request, response,getServletConfig().getServletContext(), out);
viewer.refresh();
//viewer.dispose();
//rptSource.dispose();
%>
原文轉自:http://www.anti-gravitydesign.com