我使用的開發IDE是eclipse3.2,伺服器是tomcat5.5
建立一個 Crystal reports web項目
在Target runtime選擇apache tomcat v5.5
下一步中crystal reports java reporting component、dynamic web module、java是預設選中的,這三個是必需的,你也可添加struts,後面的設定會要求你添加struts的類庫。在最後面預設加入樣本的資料庫和報表。
這樣一個Crystal Reports web項目就建立了(上面的步驟應該是地球人都可以完成吧)
在裡面有個CrystalReport1.rpt和CrystalReport_viewer.jsp
右鍵CrystalReport_viewer.jsp->運行方式->Run on Server,點擊完成。
你應該就可以看到一個空的水晶報表了吧(為什麼空的,當然啦,CrystalReport1.rpt本身是空的)
在看看sample reports檔案夾裡面,有4個樣本的.rpt報表檔案,右擊其中任何一個,選中Crystal Reports-》建立查看器JSP,就會建立一個*-viewer.jsp檔案。運行這個檔案,你應該可以看到一個水晶報表了吧。
我想這對大部分人應該都是沒有問題的,剩下的事情就是好好分析這個項目裡面所有的東東了
--------------------------------------------------------------------------------------------------------------------
上面什麼東西是在任何項目中實現都必須的呢?為此我特意建立一個新的tomcat項目,最好建一個簡單的jsp頁面測試下你的tomcat項目是否可以正常運行.
通過本人的實驗,在其他項目中JSP運行水晶報表的話,需要的類檔案跟配置.
1. 添加一個使用者庫如 CrystalReports Libraries,把下面的*.jar添加進去
commons-collections-3.1.jar,commons-configuration-1.2.jar,
commons-lang-2.1.jar,
commons-logging.jar,
Concurrent.jar,
CrystalCharting.jar
CrystalCommon.jar
CrystalContentModels.jar
CrystalDatabaseConnectors.jar
CrystalExporters.jar
CrystalExportingBase.jar
CrystalFormulas.jar
CrystalQueryEngine.jar
CrystalReportEngine.jar
CrystalReportingCommon.jar
derby.jar
icu4j.jar
jrcadapter.jar
jrcerom.jar
keycodeDecoder.jar
log4j.jar
MetafileRenderer.jar
msbase.jar
mssqlserver.jar
msutil.jar
rasapp.jar
rascore.jar
ReportPrinter.jar
rpoifs.jar
serialization.jar
URIUtil.jar
webreporting.jar
webreporting-jsf.jar
xercesImpl.jar
xml-apis.jar
Xtreme.jar
(總共36個jar,裡面有一些在其他的庫已經有的了,在項目中添加這個自訂庫就行了)
2. 把上個例子中的crystalreportviewers檔案夾放在WEB-INF檔案夾同一目錄下。這個就是你能看到水晶報表的基本架構,相當於.net裡面的水晶報表控制項了的原始碼了。
3. 把crystal-tags-reportviewer.tld放在WEB-INF下,主要標籤
4. web.xml 在<web-app>中間添加,主要是讀入crystalreportviewers
<context-param>
<param-name>crystal_image_uri</param-name>
<param-value>crystalreportviewers</param-value>
</context-param>
<context-param>
<param-name>crystal_image_use_relative</param-name>
<param-value>webapp</param-value>
</context-param>
5. 把CRConfig.xml放在src檔案夾下,水晶報表的設定檔,如果你有註冊,註冊碼也會在這檔案裡面
CRConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<CrystalReportEngine-configuration>
<reportlocation>../..</reportlocation>
<timeout>0</timeout>
<ExternalFunctionLibraryClassNames>
<classname/>
</ExternalFunctionLibraryClassNames>
</CrystalReportEngine-configuration>
配置逾時間隔
利用 CRConfig.xml 檔案,您可以配置確定何時丟棄不活動報表源的逾時間隔(以分鐘為單位)。這是必要的,因為不活動報表源仍然會消耗系統資源(如資料庫連接、伺服器記憶體以及臨時檔案使用的磁碟空間)。可以通過在 CRConfig.xml 檔案中設定 timeout 標記的值來指定逾時間隔。預設情況下,逾時間隔為 10 分鐘。通過將該值設定為 0,可以將 Java Reporting Component 配置為沒有逾時。
逾時間隔僅適用於不活動報表 -- 正在處理的報表不會因超出此值而逾時。每次成功完成一個報表源請求時,逾時定時器將會重設。如果在逾時間隔內沒有使用某個報表源,則會丟棄該報表源,並將其資源提供給其他進程使用。
6. 在jsp頁面插入這段代碼
<%@ taglib uri="/crystal-tags-reportviewer.tld" prefix="crviewer" %>
<crviewer:viewer reportSourceType="reportingComponent" viewerName="rcname-viewer" reportSourceVar="rcname" isOwnPage="true">
<crviewer:report reportName="rcname.rpt" />
</crviewer:viewer>
感覺像在用.net裡面的水晶報表控制項一樣,不只viewer,連partviewer也可以的.
在(一)中的配置保持不變,前一篇是用crviewer標籤來實現jsp顯示水晶報表的
這篇文章教你如何自己寫代碼來享受水晶報表的
report_source.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%//Crystal Java Reporting Component (JRC) imports.%>
<%-- jrcerom.jar--%>
<%@page import="com.crystaldecisions.reports.sdk.*" %>
<%-- rascore.jar--%>
<%@page import="com.crystaldecisions.sdk.occa.report.lib.*" %>
<%
//水晶報表的位置
final String REPORT_NAME = "view_report.rpt";
%>
<%
try ...{
//開啟報表
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);
//把報表源放進session,傳遞到報表顯示頁面
session.setAttribute("reportSource", reportClientDoc.getReportSource());
//轉到報表顯示頁面
response.sendRedirect("CrystalReportViewer.jsp");
}
catch(ReportSDKException ex) ...{
out.println(ex);
}
catch(Exception ex) ...{
out.println(ex);
}
%>
上面的可以封裝到javabean裡面
reportClientDoc.getDatabaseController().logon(USERNAME, PASSWORD);
設定資料庫的登陸使用者,如果瀏覽這個報表的使用者需要設定不同的許可權的話,那就需要設定上面這個了
CrystalReportViewer.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%//Crystal Report Viewer imports.%>
<%-- webreporting.jar--%>
<%@page import="com.crystaldecisions.report.web.viewer.*"%>
<%-- rascore.jar--%>
<%@page import="com.crystaldecisions.reports.sdk.*" %>
<%
//建立一個viewer對象執行個體,並設定
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setOwnPage(true);
viewer.setOwnForm(true);
viewer.setPrintMode(CrPrintMode.ACTIVEX);
//從session中取報表源
Object reportSource = session.getAttribute("reportSource");
viewer.setReportSource(reportSource);
//顯示水晶報表
viewer.processHttpRequest(request, response,this. getServletConfig().getServletContext(), null);
%>
第二種方法直接用一個頁面
CrystalReportViewer.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%//Crystal Java Reporting Component (JRC) imports.%>
<%-- jrcerom.jar--%>
<%@page import="com.crystaldecisions.reports.sdk.*" %>
<%-- rascore.jar--%>
<%@page import="com.crystaldecisions.sdk.occa.report.lib.*" %>
<%-- webreporting.jar--%>
<%@page import="com.crystaldecisions.report.web.viewer.*"%>
<%
//水晶報表的位置
final String REPORT_NAME = "view_report.rpt";
%>
<%
try ......{
//開啟報表
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);
//把報表源放進session,傳遞到報表顯示頁面
//session.setAttribute("reportSource", reportClientDoc.getReportSource());
//建立一個viewer對象執行個體,並設定
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setOwnPage(true);
viewer.setOwnForm(true);
viewer.setPrintMode(CrPrintMode.ACTIVEX);
//從session中取報表源
//Object reportSource = session.getAttribute("reportSource");
//viewer.setReportSource(reportSource);
viewer.setReportSource(reportClientDoc.getReportSource());
//顯示水晶報表
viewer.processHttpRequest(request, response,this. getServletConfig().getServletContext(), null);
//轉到報表顯示頁面
//response.sendRedirect("CrystalReportViewer.jsp");
}
catch(ReportSDKException ex) ......{
out.println(ex);
}
catch(Exception ex) ......{
out.println(ex);
}
%>
個人感覺第一種方法好,報表源跟顯示分開,安全,重用方便
在.net中,你可以很容易的用sql語句過濾報表資料,但在CR4E中沒這樣的功能設定,但可以通過編寫程式碼完成。
這裡是我做的簡單用sql語句過濾資料的例子。
項目還是用ǘ ├錈嫻膖omcat項目。
建一個實現這個功能的類
JRC_ResultSet_DataSource.java
package com.JRC.util;
import java.sql.*;
import javax.servlet.http.*;
import com.crystaldecisions.reports.sdk.*;
import com.crystaldecisions.sdk.occa.report.lib.*;
public class JRC_ResultSet_DataSource ...{
private String REPORT_NAME="";
public JRC_ResultSet_DataSource(String report_name)...{
this.REPORT_NAME=report_name;
}
/** *//**
* @return rEPORT_NAME
*/
public String getREPORT_NAME() ...{
return REPORT_NAME;
}
/** *//**
* @param report_name 要設定的 rEPORT_NAME
*/
public void setREPORT_NAME(String report_name) ...{
REPORT_NAME = report_name;
}
/** *//**
* 串連資料庫,通過sql查詢語句進行查詢,返回結果集
*/
private static ResultSet getResultSetFromQuery(String query, int scrollType)
throws SQLException, ClassNotFoundException ...{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
final String DBUSERNAME = "username";
final String DBPASSWORD = "password";
final String CONNECTION_URL = "jdbc:microsoft:sqlserver://localhost:1433;database=dname";
java.sql.Connection connection = DriverManager.getConnection(CONNECTION_URL, DBUSERNAME, DBPASSWORD);
Statement statement = connection.createStatement(scrollType, ResultSet.CONCUR_READ_ONLY);
return statement.executeQuery(query);
}
/** *//**
* 通過sql語句過濾報表資料,在.net就不用怎麼慘了
*/
public boolean isReportSourceInSession(String session_name,HttpSession session) throws ReportSDKException, SQLException, ClassNotFoundException...{
boolean flag=false;
try ...{
//開啟水晶報表
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);
//sql查詢語句,返回的欄位數必須跟報表裡面的一樣,不能多也不能少,並且欄位的類型要跟報表的一樣,其他不管是什麼資料都可以
//from 表這裡要填完整,如資料庫名.dbo.資料庫表,最好做個別名
String query = "select tt.test_1,tt.test_2,tt.test_3,tt.test_4 from dname.dbo.test tt";
ResultSet resultSet = this.getResultSetFromQuery(query,ResultSet.TYPE_SCROLL_INSENSITIVE);
String tableAlias = reportClientDoc.getDatabaseController().getDatabase().getTables().getTable(0).getAlias();
//把結果集放進報表裡,將會自動產生一個datasource
reportClientDoc.getDatabaseController().setDataSource(resultSet,tableAlias, "resultsetTable");
session.setAttribute(session_name, reportClientDoc.getReportSource());
flag=true;
return flag;
} catch (Exception e) ...{
// TODO: handle exception
e.printStackTrace();
return flag;
}
}
}
這裡要注意資料庫查詢結果集的欄位數目要跟報表裡面的欄位數目一樣,類型也要一樣,不然就會出錯。
sql語句中的表的名字要完整,如資料庫名.dbo.資料庫表,最好做個別名
顯示頁面
Result_viewer.jsp
<%@page import="com.JRC.util.JRC_ResultSet_DataSource" %>
<%--webreporting.jar --%>
<%@page import="com.crystaldecisions.report.web.viewer.*" %>
<%--jrcerom.jar --%>
<%@ page import="com.crystaldecisions.reports.sdk.*" %>
<%
JRC_ResultSet_DataSource jrcd=new JRC_ResultSet_DataSource("resultSet.rpt");
if(!jrcd.isReportSourceInSession("reportSource",session)
response.sendRedirect("error.html");
CrystalReportViewer crViewer=new CrystalReportViewer();
crViewer.setOwnPage(true);
crViewer.setOwnForm(true);
crViewer.setPrintMode(CrPrintMode.ACTIVEX);
Object reportSource=session.getAttribute("reportSource");
crViewer.setReportSource(reportSource);
crViewer.processHttpRequest(request,response,this.getServletConfig().getServletContext(),null);
%>
注意上面幾點應該就沒問題了
PS:Snippets視圖最下面有Crystal reports的一些實用程式碼片段
CR查看器標記、開啟並查詢報表、開啟報表、查看報表、查看報表並設定資料庫登入、將報表匯出為pdf、將報表匯出為rtf 等的程式碼片段,簡單易用
在eclipse中怎麼把POJO插入到水晶報表裡面呢?這就是第四篇的所要做的
首先,應該就是要建立一個實體類了。
我這裡用一個OrderItems.java做例子,代碼
package com.JRC.beans;
public class OrderItems ...{
public int id; //對應資料庫表的id
public int quantity; //產品數量,資料庫表所沒有的
public OrderItems(int id, int quantity) ...{
super();
this.id = id;
this.quantity = quantity;
}
/** *//**
* @return id
*/
public int getId() ...{
return id;
}
/** *//**
* @param id 要設定的 id
*/
public void setId(int id) ...{
this.id = id;
}
/** *//**
* @return quantity
*/
public int getQuantity() ...{
return quantity;
}
/** *//**
* @param quantity 要設定的 quantity
*/
public void setQuantity(int quantity) ...{
this.quantity = quantity;
}
}
如果你還沒建好報表,建立一個報表如Report.rpt,並開啟這個報表
在項目資源管理員中,點擊OrderItems.java前面的+ (發不了圖片),可以看到 “綠點 OrderItems”,就是這個了,右擊-》crystal reports-》添加到當前crystal報表。或者你可以直接把“綠點 OrderItems”拉到報表中
這樣OrderItems就在報表的資料中了,在報表資料中再添加一個資料庫表,如products(product_id,product_name,product_price,....,)
如果沒出什麼問題,那Report.rpt報表資料中有了OrderItems表和products表,左鍵按緊OrderItems表的id,把他拉到products表的products_id上,你可以發現他們中間有條線。
這樣OrderItems.id就跟products.products_id關聯起來了。中間的線預設屬性是等於,你也可以改成其他的。
右擊 Report.rpt-》Crystal Reports-》建立查看器JSP—》選擇查看器API代碼插入-》選中使用POJO填充報表、串連Crystal報表頁面查看器-》確定
一個新的Report-viewer.jsp頁面就出來了。不過現在很不能用,你要稍微改下裡面的一丁點東西才行。
注意:Report-viewer.jsp中用到JRCHelperSample類,這個在(一)中建立的CR項目中有,是非常非常好的工具類,沒事就把它拷到你的項目下吧,有很多地方要用到這個類。這個類在包com.businessobjects.samples裡面
String reportName = ""; //填上你的報表名字
List dataSet = new ArrayList();
dataSet.add(new OrderItems());
dataSet.add(new OrderItems());
dataSet.add(new OrderItems());
dataSet.add(new OrderItems());
dataSet.add(new OrderItems());
你可以用OrderItems的建構函式添加資料集,你可以用到很多方法來添加dataSet資料集的,只要添加的是準確有效OrderItems實體物件就行了
注意要把裡面的/* */這些去掉
啟動tomcat,運行Report-viewer.jsp吧