我使用的开发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吧