水晶报表

转载 2007年09月14日 11:05:00

 

绪论
       这篇文章,我们讨论j2ee应用程序结合水晶报表的经验,这个例子叫做“Task Workbench (TWB)”。这篇文章的目的是帮助大家评估在j2ee应用程序中使用水晶报表的优点和缺点。
       TWB(www.taskworkbench.com)是提供工程和每日运作的实时信息的工作管理工具。它是一个web应用程序,jsp作为表示层,EJBs处理商业逻辑,CMP实体bean作为持久层映射到一个oracle数据库。
       TWB帮助项目经理了解不同方法下项目花费时间和员工在每个项目上的消耗。当设计这个程序的时候,一个非常重要的需求就是提供给项目经理和项目管理人员一个高水平的项目成员和工程数据的视图。
图一: 显示一个员工的任务和每个任务花费的时间。
 
       最初,我们用jsp创建报表。但是这个方法被证实太耗费时间,特别是创建联合报表的时候。所以开始寻找一个java报表解决方案。我们的基本要求是这个方案能够快速配置,并且轻松生成和修改报表,还有要容易整合到j2ee程序中。
       我们选择水晶报表因为它完全满足我们的需求。它是一个成熟的、同类产品中处于领导地位的的工具。这是一个重要的考虑,因为我们希望我们的报表方案可以随着TWB一起成长。

实现
       水晶报表被整合进TWB中有两个关键目的:第一是实现花费最小代价增加新报表和维护现有报表。第二个目的是转换到更复杂报表方案时,可以通过简单配置实现。
       Crystal Java Reporting Component 有一个jsp标签库,提供创建基本报表的简单方法。我们决定使用自己的自定义jsp标签库,来使用Crystal Java Reporting Component显示报表。这个方法允许我们定制报表外观和报表参数,这样可以保持设计简单容易。
       jsp上唯一并且必须的java代码是一个为了得到一个显示在页面上的报表的实例而去访问工厂classjava方法。图二是一个可以请求报表的简单的jsp例子。Form传递必需的参数到view_report.jsp(图三)。
 
 

<%@ page import="com.ensemsys.twb.presentation.crystal.ReportParameter,
com.ensemsys.twb.presentation.crystal.ReportType"%>
<html>
<head>
<title>Report Viewer</title>
<link rel="stylesheet" href="style/main.css" type="text/css"/>
</head>
<body>
<h1>Simple Banked Hours Report</h1>
<p>Enter the date range for the report and click &quot;Submit&quot; to view
the report.</p>
<form method="post" action="view_report.jsp">
<input type="hidden" name="<%=ReportParameter.TYPE%>"
value="<%=ReportType.BANKED_TIME_SIMPLE%>"/>
<table>
<tr>
<td class="label">Start Date:</td>
<td>
<input type="text" name="<%=ReportParameter.START_DATE%>"
value="2003.06.30"/>
</td>
</tr>
<tr>
<td class="label">End Date:</td>
<td>
<input type="text" name="<%=ReportParameter.END_DATE%>"
value="2003.12.01"/>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<input type="submit" name="submitBtn" value="Submit"/>
</td>
</tr>
</table>
</form>
</body>
</html>

图二:simple_banked_time_report.jsp
 

<%@ page import="com.ensemsys.twb.presentation.crystal.ReportFactory,
com.ensemsys.twb.presentation.crystal.Report"%>
<%@ taglib uri="/simplereportviewer.tld" prefix="viewer" %>
<html>
<head>
<title>Report</title>
<link rel="stylesheet" href="style/main.css" type="text/css"/>
</head>
<body>
<%
// "CrystalEventTarget" is the report action name used by Crystal
final String REPORT_NAME = "CrystalEventTarget";
String reportName = (String) session.getAttribute( REPORT_NAME );
// refresh might have done via a report action
if ( reportName == null )
{
reportName = (String) request.getParameter( REPORT_NAME );
}
Report report = null;
if ( reportName == null )
{
report = ReportFactory.newInstance( request );
reportName = report.getName();
session.setAttribute( REPORT_NAME, reportName );
session.setAttribute( reportName, report );
}
else
{
report = (Report) session.getAttribute( reportName );
}
%>
<viewer:viewer report="<%=report%>" />
</body>
</html>
 

图三:view_report.jsp
 
报表工厂类创建一个报表实例,用request参数来确定报表类型。这种方法巧妙的把商业逻辑通过一个方法(method)装入单独报表。在ReportFactory子集中,工厂方法对于复合报表来说是一个最好的解决办法-ReportFactory能够代表子集创建一个报表。
 

package com.ensemsys.twb.presentation.crystal;
import com.crystaldecisions.sdk.occa.report.data.Fields;
import com.crystaldecisions.sdk.occa.report.data.ParameterField;
import com.crystaldecisions.sdk.occa.report.data.ParameterFieldDiscreteValue;
import com.crystaldecisions.sdk.occa.report.data.Values;
import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import java.sql.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* Provides methods for creating an instance of a Report
* from the parameters in the request.
*/
public class ReportFactory
{
public static final DateFormat FORMAT =
new SimpleDateFormat( "yyyy.MM.dd" );
 
public static Report newInstance( ServletRequest request )throws JspException
{
String reportType = getParameter( request, ReportParameter.TYPE );
Report report = null;
// For brevity, only the simple report type is shown here
if ( reportType.equals( ReportType.BANKED_TIME_SIMPLE ) )
{
report = newSimpleBankedTimeReport( request );
}else
{
throw new InvalidReportTypeException( reportType );
}
return report;
}
 

图四:ReportFactory.java 基于form提交的参数创建一个实例
 

private static Report newSimpleBankedTimeReport( ServletRequest request )
throws JspException
{
Date startDate = getDateParameter( request, ReportParameter.START_DATE );
Date endDate = getDateParameter( request, ReportParameter.END_DATE );
Fields fields = new Fields();
ParameterField prevYearField = newDateField( "Prev Fiscal Year", startDate);
ParameterField reportDateField = newDateField( "Report Date", endDate );
fields.add( prevYearField );
fields.add( reportDateField );
return new Report( "protected/reports/bhr_simple_demo.rpt",
ReportType.BANKED_TIME_SIMPLE, fields );
}
 
public static ParameterField newDateField( String name, Date date )
{
ParameterField field = new ParameterField();
Values vals = new Values();
ParameterFieldDiscreteValue value = new ParameterFieldDiscreteValue();
field.setName( name );
value.setValue( date );
field.setReportName( "" );
value.setDescription( "" );
vals.add( value );
field.setCurrentValues( vals );
return field;
}
 
public static Date newDate( String s )
throws InvalidDateStringException
{
java.sql.Date date = null;
try{
date = new java.sql.Date( FORMAT.parse( s ).getTime() );
}
catch ( ParseException e )
{
throw new InvalidDateStringException( e );
}
return date;
}
 
protected static void assertHasParameter( ServletRequest request,
String name)
{
String parameter = request.getParameter( name );
if ( parameter == null || parameter.equals( "" ) )
{
throw new NoSuchParameterException( name );
}
}
 

图四:ReportFactory.java
 

protected static Date getDateParameter( ServletRequest request, String name )
throws JspException
{
String parameter = getParameter( request, name );
Date date = null;
try{
date = newDate( parameter );
}
catch ( InvalidDateStringException e )
{
throw new JspException( e );
}
return date;
}
 
protected static String getParameter( ServletRequest request, String name )
{
assertHasParameter( request, name );
return request.getParameter( name );
}
}
 

图四:ReportFactory.java
 
 
       SimpleReportViewerTag.java 呈现报表,这个类使用水晶报表的API来完成画出报表的工作。这个类非常简单――它创建一个CrystalReportViewer实例,设置数据库连接信息和报表需要的参数,最后显示报表。对应的TLDsimplereportviewer.tld,在图六列出。
 

package com.ensemsys.twb.presentation.crystal;
import com.crystaldecisions.report.web.viewer.CrystalReportViewer;
import
com.crystaldecisions.reports.reportengineinterface.JPEReportSourceFactory;
import com.crystaldecisions.sdk.occa.report.data.ConnectionInfo;
import com.crystaldecisions.sdk.occa.report.data.ConnectionInfos;
import com.crystaldecisions.sdk.occa.report.data.Fields;
import com.crystaldecisions.sdk.occa.report.data.IConnectionInfo;
import com.crystaldecisions.sdk.occa.report.lib.ReportSDKExceptionBase;
import com.crystaldecisions.sdk.occa.report.reportsource.IReportSource;
import com.crystaldecisions.sdk.occa.report.reportsource.IReportSourceFactory2;
import com.ensemsys.twb.ApplicationProperties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.util.Locale;
 

图五:SimpleReportViewerTag.java 被执行来显示一个报表。
                                                            

/**
* Displays a Crystal report.
*/
public class SimpleReportViewerTag extends TagSupport
{
private Report report;
 
public Report getReport()
{
return report;
}
public void setReport( Report report )
{
this.report = report;
}
 
public int doEndTag() throws JspException
{
CrystalReportViewer viewer = newViewer( report );
try{
IReportSourceFactory2 rptSrcFactory = new JPEReportSourceFactory();
IReportSource reportSource =
(IReportSource) rptSrcFactory.createReportSource(
report.getReportFileName(), getLocale() );
viewer.setReportSource( reportSource );
viewer.setDatabaseLogonInfos( newDBConnectionInfos() );
viewer.setEnableLogonPrompt( false );
Fields fields = report.getFields();
if ( fields != null )
{
viewer.setParameterFields( fields );
viewer.setEnableParameterPrompt( false );
}
viewer.processHttpRequest(
(HttpServletRequest) pageContext.getRequest(),
(HttpServletResponse) pageContext.getResponse(),
pageContext.getServletConfig().getServletContext(),
pageContext.getOut() );
}
catch ( ReportSDKExceptionBase e )
{
throw new JspException( e );
}
finally
{
if ( viewer != null )
{
viewer.dispose();
}
}
return EVAL_PAGE;
}
 

图五:SimpleReportViewerTag.java
 
 

private Locale getLocale()
{
// generally you want to change this method
// to return the specific locale that your J2EE
// application is using
return pageContext.getRequest().getLocale();
}
private static ConnectionInfos newDBConnectionInfos()
{
ConnectionInfos infos = new ConnectionInfos();
IConnectionInfo con = new ConnectionInfo();
con.setUserName( ApplicationProperties.getJDBCUser() );
con.setPassword( ApplicationProperties.getJDBCPassword() );
infos.add( con );
return infos;
}
 
private static CrystalReportViewer newViewer( Report report )
{
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setName( report.getName() );
// set the viewer formatting and behaviour options
//viewer.setSeparatePages( false );
//viewer.setBestFitPage( true );
// ... and so on
return viewer;
}
}
 

图五:SimpleReportViewerTag.java
 
 

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Crystal Viewer Tag Library</short-name>
<description>Display a Crystal Report with paramters</description>
<tag>
<name>viewer</name>
<tagclass>
com.ensemsys.twb.presentation.crystal.SimpleReportViewerTag
</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>report</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
 

图六:simplereportviewer.tld 
 
       应为TWB仅仅允许管理者查看报表,TWB现有的接口控制系统控制对报表的访问。将来,TWB可以要求更精细的访问控制-例如,用户可以在有限的条件下查看特定项目的报表。在这个案例中,为了到达这种访问标准,我们使用水晶报表的安全特性。
 
 

相关文章推荐

Winform基础水晶报表-Pull模式

一、添加数据源1.         选择菜单数据,添加数据源,出现数据源配置向导,选择数据库,设置连接,选择表,完成。2.         ...

水晶报表(Crystal Report)通过Visual Studio 2010的WPF实现

1,前言。      本文中采用的工具介绍: VS2010旗舰版,CrystalReport版本为13.0 。实现的方式是做一个简单demo,让初学者能够初步了解水晶报表的使用。     ...

如何部署包含水晶报表的程序(参考)

1、原理: 发布使用水晶报表的项目需要包含三种组件:报表(*.rpt)、模块(*.msm)、运行库(*.msm),这些模块文件是在 C:\Program Files\Common Files\Mer...
  • leek
  • leek
  • 2012-02-24 09:15
  • 255

水晶报表之主从多表数据源批量预览及打印开发设计

第一步:创建强类型数据集,添加数据表,一般情况下,设置各个字段类型为字符串,对于图片字段,数据类型为System.Byte[],指定各个数据表之间的关系。如果父表为SickInfo,子表为ChemPr...

水晶报表:交叉表页内自动“换行”

转自:http://topic.csdn.net/u/20090422/00/6ad57982-d44c-44a8-8089-e19107b0c86c.html 使用交叉表时,会遇到这种情况:列非常多...

水晶报表编写高效记录选定公式的策略 -Crystal Reports

http://webloger.blog.hexun.com/7245706_d.html 水晶报表编写高效记录选定公式的策略 -Crystal Reports 注意:    本节假定您熟悉“选择...
  • os005
  • os005
  • 2012-08-11 15:10
  • 1350

【水晶报表内功心法】--推拉之间(转载)

水晶报表教程,强烈推荐CSDN上babyt(阿泰)的帖子(以下内容皆转帖自此贴以及其子连接): http://topic.csdn.net/u/20090713/18/6e14bf28-1979-4...

.net中水晶报表使用

本次示例目的只是让刚接触水晶报表的朋友掌握其应用,因此示例以简单,简洁,清晰为主,没有连接后台数据库。 Visual studio 2008新建asp.net网站CrystalReportsDe...

水晶报表内功心法

索引 .【水晶报表内功心法】--序言 .【水晶报表内功心法】--推拉之间 .【水晶报表内功心法】--PULL模式样板招式 .【水晶报表内功心法】--PUSH模式样板招式 ...

水晶报表中让行高自适应高度(即根据内容的来适应高度)

1、在水晶报表打印中,有些内容可能占两行、三行、四行内容,但有些内容仅占一行内容,如果固定行高,会造成纸张的很大的浪费,如下图所示 2、如上图所示,零件型号、名称、规格三列超出一行内容,怎么让内...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)