Crystal Reports 辅助类






4.62/5 (44投票s)
一个辅助类,用于简化在 .NET 应用程序中集成 Crystal Reports。
- .NET 2.0 源代码文件下载 - 10.9 KB
- .NET 2.0 演示项目下载 - 55.2 KB
- 帮助文件下载 - 70.8 KB
- .NET 1.1 源代码文件下载 - 8.81 KB
- .NET 1.1 演示项目下载 - 51.7 KB
引言
在 .NET 应用程序中集成 Crystal Reports 可能是一个真正的挑战。要成功地从应用程序内部运行报表,您需要了解许多内容。本文介绍的辅助类提供了许多在 .NET 应用程序中集成 Crystal Reports 时可能非常有用的方法。使用此辅助类,集成 Crystal Reports 将会更加轻松快捷。
该辅助类包含的方法可以帮助您:
- 将数据库连接或
DataSet
对象分配给报表 - 在 WinForms 应用程序中通过代码打印报表
- 在 WinForms 应用程序中通过代码将报表导出到磁盘
- 将报表导出到 ASP.NET 窗体。
- 从 ASP.NET 应用程序内部将报表下载到 Internet 客户端。
- 调整 Crystal Reports 查看器在 Windows Forms 应用程序中的显示方式。
- 为参数字段分配值。
您可以下载的演示解决方案演示了该类的许多功能。要使用它,您需要 SQL Server 2000 以及 Pubs 和 NorthWind 数据库。
背景
几年前,当我需要将 Crystal Reports 集成到 Windows GUI 应用程序时,我开始构建这个辅助类。我必须解决以下问题:
- 将
DataSet
对象分配给报表。 - 将数据库连接分配给报表。
- 将报表导出为 Adobe PDF 文件。
- 将 Crystal Reports 查看器集成到应用程序中。
该辅助类最初是为 .NET 1.1 应用程序设计的。Visual Studio 2003 附带了 Crystal Reports 9 的精简版,称为 Crystal for .NET。目前,Visual Studio 2005 附带了基于 Crystal Reports 10 的更新版本。
CrystalHelper 类处理的常见操作
为报表分配连接
大多数开发人员在集成 Crystal Reports 时面临的一个问题是让它在另一台系统上运行。这个问题是由 Crystal Reports 需要有效的数据库连接引起的。开发报表时,这通常是连接到您的开发数据库。但是,在部署报表时,您需要为报表中的每个表分配正确的数据库连接。以下代码显示了如何做到这一点:
ConnectionInfo connection = new ConnectionInfo();
connection.DatabaseName = "DatebaseName";
connection.ServerName = "ServerName";
connection.UserID = "UserId";
connection.Password = "Password";
// First we assign the connection to all tables in the main report
//
foreach (CrystalDecisions.CrystalReports.Engine.Table
table in _reportDocument.Database.Tables)
{
// Cache the logon info block
TableLogOnInfo logOnInfo = table.LogOnInfo;
// Set the connection
logOnInfo.ConnectionInfo = connection;
// Apply the connection to the table!
table.ApplyLogOnInfo(logOnInfo);
}
如果您有一个或多个子报表,那么事情会变得更加复杂。您需要对每个子报表执行上述操作。为此,您需要检查报表中的所有节,然后为每个子报表中的所有表重新分配连接信息。例如:
foreach (CrystalDecisions.CrystalReports.Engine.Section
section in _reportDocument.ReportDefinition.Sections)
{
// In each section we need to loop through all the reporting objects
foreach (CrystalDecisions.CrystalReports.Engine.ReportObject
reportObject in section.ReportObjects)
{
if (reportObject.Kind == ReportObjectKind.SubreportObject)
{
SubreportObject subReport = (SubreportObject)reportObject;
ReportDocument subDocument =
subReport.OpenSubreport(subReport.SubreportName);
foreach (CrystalDecisions.CrystalReports.Engine.Table
table in subDocument.Database.Tables)
{
// Cache the logon info block
TableLogOnInfo logOnInfo = table.LogOnInfo;
// Set the connection
logOnInfo.ConnectionInfo = connection;
// Apply the connection to the table!
table.ApplyLogOnInfo(logOnInfo);
}
}
}
}
上述两个代码段由 CrystalHelper
类中的 Open()
方法处理。
将 DataSet 分配给报表
当您想将 DataSet
分配给报表时,会发生类似的问题。DataSet
不仅必须分配给报表,还必须分配给所有子报表。执行此操作的代码如下所示:
// Now assign the dataset to all tables in the main report
//
_reportDocument.SetDataSource(dsReportData);
// Now loop through all the sections
// and its objects to do the same for the subreports
//
foreach (CrystalDecisions.CrystalReports.Engine.Section section
in _reportDocument.ReportDefinition.Sections)
{
// In each section we need to loop through all the reporting objects
foreach (CrystalDecisions.CrystalReports.Engine.ReportObject
reportObject in section.ReportObjects)
{
if (reportObject.Kind == ReportObjectKind.SubreportObject)
{
SubreportObject subReport = (SubreportObject)reportObject;
ReportDocument subDocument =
subReport.OpenSubreport(subReport.SubreportName);
subDocument.SetDataSource(dsReportData);
}
}
}
这段代码也是此 CrystalHelper
类中 Open()
方法的一部分。
使用代码集成报表
打印报表
第一个代码示例显示了当报表是嵌入式资源且数据存储在 DataSet
中时,如何打印报表。
private void PrintReport(SqlConnection connection)
{
using (DataSet ds = new TestData())
{
SqlHelper.FillDataset(connection,
CommandType.Text, "SELECT * FROM Customers", ds, new string [] {"Customers"});
using (CrystalHelper helper = new CrystalHelper(new TestReport()))
{
helper.DataSource = ds;
helper.Open();
helper.Print();
helper.Close();
}
}
}
如您所见,在此示例中,处理报表处的代码非常简单明了。Open()
方法将确保 DataSet
被分配给所有节。
当您在报表中使用嵌入式查询时,您将需要分配数据库连接,而不是像上面的示例那样分配 DataSet
。此时的代码将如下所示:
private void PrintReport()
{
using (LCrystalHelper helper = new LCrystalHelper(new TestReport()))
{
helper.DatabaseName = "DatabaseName";
helper.ServerName = "ServerName";
helper.UserId = "User";
helper.Password = "Password";
helper.Open();
helper.Print();
helper.Close();
}
}
同样,您会看到使用此辅助类集成 Crystal Reports 报表非常简单。在上面的示例中,我使用了具有有效用户 ID 和密码的完全限定连接。Visual Studio 2005 随附的 Crystal Reports 版本也支持集成安全性。为此,CrystalHelper
类还提供了一个名为 IntegratedSecurity
的属性。此属性默认为 false
,但将其设置为 true
将允许您使用集成安全性,如本示例所示:
private void PrintReport()
{
using (LCrystalHelper helper = new LCrystalHelper(new TestReport()))
{
helper.DatabaseName = "DatabaseName";
helper.ServerName = "ServerName";
helper.IntegratedSecurity = true;
helper.Open();
helper.Print();
helper.Close();
}
}
如果报表作为内容文件包含在您的解决方案中,而不是作为嵌入式资源,则可以替换此行:
using (CrystalHelper helper = new CrystalHelper(new TestReport()))
用这一行
using (CrystalHelper helper = new CrystalHelper(@"C:\ReportLocation\ReportFile.rpt"))
导出报表
报表可以导出为以下导出格式:
- Word (*.doc)
- Excel (*.xls)
- Rich text (*.rtf)
- Portable Doc Format (*.pdf)
该辅助类提供了四种执行导出操作的方法。前两种方法只是将文件导出到指定位置。这两种方法对于 WinForms 应用程序非常有用,或者当您需要在 ASP.NET 环境中将文件导出到服务器时。第一个方法接受文件名作为参数。导出类型通过检查给定的文件扩展名来确定。
helper.Export(@"C:\ExportLocation\MyFile.pdf");
第二种方法还允许您将导出格式指定为参数。
helper.Export(@"C:\ExportLocation\MyFile.pdf", CrystalExportFormat.PortableDocFormat);
当您在 ASP.NET 应用程序中使用这些方法时,您可能希望将文件导出到客户端。为此,该辅助类实现了两种需要您传递 HttpResponse
对象的方法。其中第一种方法会将导出的文件简单地写入响应。
helper.Export(Response, CrystalExportFormat.PortableDocFormat);
这将导致报表显示在客户端 Internet 浏览器中,前提是已安装支持导出格式的应用程序。第二种方法允许您指定导出是否要作为附件发送,在这种情况下,您可以为导出指定文件名。用户将看到一个对话框,可以在其中指定下载位置。
helper.Export(Response, CrystalExportFormat.PortableDocFormat,
true, "AnExportedDocument.pdf");
在 Crystal Reports 查看器控件中显示报表
显示报表的最后一个选项是使用 Crystal Reports 查看器控件。假设您的窗体(Windows 或 ASP.NET)上已有该控件,您可以执行以下操作:
private void PrintReport(SqlConnection connection)
{
using (DataSet ds = new TestData())
{
SqlHelper.FillDataset(connection,
CommandType.Text, "SELECT * FROM Customers",
ds, new string [] {"Customers"});
CrystalHelper helper = new CrystalHelper(@"C:\ReportLocation\ReportFile.rpt");
helper.DataSource = ds;
helper.Open();
crystalReportViewer1.ReportSource = _crystalHelper.ReportSource;
}
}
设置报表参数的值
要设置参数值,通常需要编写大约 6 行代码。并且,您需要知道何时执行此操作。通常,就在分配数据库连接之前。该辅助类还通过提供 SetParameter
方法来帮助您设置报表参数字段的值。该类将维护一个内部列表,其中包含您希望设置的所有参数,并在正确的时间应用这些值。以下示例显示了如何使用此方法:
using (CrystalHelper hlp = new CrystalHelper())
{
_crystalHelper.SetParameter("CategoryId", "Beverages");
_crystalHelper.ServerName = "localhost";
_crystalHelper.DatabaseName = "Pubs";
_crystalHelper.UserId = "UserId";
_crystalHelper.Password = "Password";
_crystalHelper.ReportSource = new TestReport();
_crystalHelper.Open();
_crystalHelper.Export("C:\\Test.pdf",
CrystalExportFormat.PortableDocFormat);
_crystalHelper.Close();
}
您可以在此处下载的演示解决方案 here 也演示了此功能。
调整 Crystal Reports 查看器控件
更改选项卡名称
当报表显示时,查看器将始终显示一个选项卡。当报表中有子报表或钻取功能时,这是一个非常有用的功能。唯一的问题是,选项卡的名称始终是“主报表”或子报表的名称。通过执行以下调用,可以轻松更改选项卡名称:
CrystalHelper.ReplaceReportName(crystalReportViewer1,
"MainReport", "My name for the report");
第一个参数是查看器控件。第二个参数始终是当前选项卡的名称。最后一个参数是选项卡的新名称。但是,您需要注意,更改选项卡名称有点棘手。首先,您只能确定第一个选项卡 (MainReport) 始终存在。其他选项卡仅在用户单击进入子报表或钻取部分时显示。您需要响应查看器引发的事件,以确保在显示新选项卡时调整选项卡名称。
隐藏选项卡
如果要隐藏选项卡,可以使用以下调用:
CrystalHelper.ViewerTabs(crystalReportViewer1, false);
当然,通过将 true
作为第二个参数调用相同的方法可以撤销此操作。
隐藏状态栏
报表查看器还显示一个状态栏。可以使用以下调用隐藏此状态栏:
CrystalHelper.ViewerStatusBar(crystalReportViewer1, false);
当然,通过将 true
作为第二个参数调用相同的方法可以撤销此操作。
有价值的资源
我用来构建这个辅助类的许多信息都在互联网上找到的。我发现以下资源对于您需要使用 Crystal Reports 做任何事情都非常有用:
我强烈建议任何想进一步了解 Crystal Reports 的人访问这些链接。我发现与 Crystal Reports 相关的问题的大部分答案都在上述某个地方。
历史
2007 年 8 月 3 日 |
|
2007 年 6 月 12 日 |
|
2007 年 3 月 8 日 |
修复了 Matthew Noonan 报告的错误。 |
2006 年 12 月 6 日 | 添加了该类和演示应用程序的 .NET 1.1 版本。 |
2006 年 8 月 8 日 | 包含更多示例和背景信息。 |
2006 年 8 月 3 日 | 包含了用于构建此类的资源的超链接。 |
2006 年 8 月 2 日 | 第一个版本发布在 CodeProject 上。 |