SharePoint 的 Crystal Reports WebPart
一篇关于构建 SharePoint WebPart 以动态显示 Crystal Reports 的文章。
引言
这是一个 SharePoint WebPart,它将允许站点管理员在 SharePoint 网页中动态添加 Crystal Reports,无需任何编程。该 Web Part 使用 C# 和 .NET Framework 3.5 编写(应兼容 .NET Framework 2.0)。
背景
我最近被一位客户要求编写一个 Web Part,允许他们为生产控制团队动态生成和显示 Crystal Reports。关键在于报表必须从最新的、不断变化的数据中生成;过夜生成并存储在文档库中的报表是不可接受的。通过硬编码 Crystal Report 定义文件的物理位置,我为相对有限数量的报表实现了这一点,但现在似乎可以做一个更通用的版本,允许站点管理员将报表定义文件上传并存储在 SharePoint 文档库中,然后放置在页面上,这将是一个有用的实用程序。
必备组件
您需要 Windows 2003 Server(或更高版本)配合 Windows SharePoint Services 3.0、安装了 Crystal Reports 插件的 Visual Studio 2008,以及 Windows SharePoint Services 3.0 Tools: Visual Studio Extensions (WSSVSE),这将为您提供 Visual Studio SharePoint 模板。WSSVSE 可从 Microsoft 下载。
假设您对 SharePoint Web Part 开发有基本了解。
设置 Crystal Reports 文档库
在 SharePoint 中,为 Crystal Reports 定义文件(*.rpt)添加一个文档库。默认情况下,它称为“Crystal Reports RPT Files”。您可以根据自己的需求更改此名称,但之后您需要在源代码中更改库名称。将一个或多个 RPT 文件上传到文档库。RPT 文件必须配置为直接访问目标数据库;代码可以重写为访问本地数据集,但目前不支持。
代码
创建 SharePoint Web Part
在 Visual Studio 中,单击“文件”->“新建”->“项目”,然后选择“SharePoint”,再选择“Web Part”。为项目指定一个合适的名称和位置,然后单击“确定”。
在“解决方案资源管理器”中,右键单击“引用”,然后添加对 Crystal Reports 库的引用。您需要以下引用:
打开 Web Part 的 *.aspx.cs 源代码文件,并添加上述的 `using` 语句。
using CrystalDecisions.Shared;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Web;
我们需要设置一个属性来保存 Web Part 将使用的报表文件名。这会通过 `public string ReportSource` 中的 `get`/`set` 方法进行序列化。
public class CustomCrystalReportWP : System.Web.UI.WebControls.WebParts.WebPart
{
// for the name of the .rpt file in the document library
String strReportName = "";
// an editor part control to display a list of reports
ReportSourcePart edPart = new ReportSourcePart();
public CustomCrystalReportWP()
{
}
// to serialise the name of the report
[Personalizable(PersonalizationScope.Shared, false)] // Storage.
public string ReportSource
{
get
{
return strReportName;
}
set
{
strReportName = value;
}
}
在 `CreateChildControls` 中,添加一个 `CrystalReportViewer` 和一个 Crystal Reports 文档。在 SharePoint 文档库中查找 *.rpt 文件,因为 Crystal Reports 只会打开物理文件中的 *.rpt 文件,将其写入临时文件,然后将临时文件的位置设置为 CR 文档的位置。
protected override void CreateChildControls()
{
// add a Crystal Reports Viewer control
CrystalDecisions.Web.CrystalReportViewer crystalReportViewer1 =
new CrystalDecisions.Web.CrystalReportViewer();
// and a Crystal Reports report document
ReportDocument crdoc = new ReportDocument();
this.SetPersonalizationDirty();
base.CreateChildControls();
if (strReportName.Length > 0)
{
// if we have a report selected get the .rpt file
SPWeb thisSite;
thisSite = SPControl.GetContextWeb(Context);
SPFolder folder = thisSite.GetFolder("Crystal Reports rpt Files");
if (folder.Exists)
{
// get collection of Crystal Reports rpt files in the document library
SPFileCollection files = folder.Files;
// open the rpt file and get the contents
SPFile srcfile = files[strReportName];
byte[] content = srcfile.OpenBinary();
// make a temporary folder
DirectoryInfo dir2 = new DirectoryInfo("~/temp");
if (!dir2.Exists)
dir2.Create();
if (File.Exists("~/temp/temp.rpt"))
{
File.Delete("~/temp/temp.rpt");
}
// write the report definition to a temporary file
BinaryWriter bw =
new BinaryWriter(File.Open("~/temp/temp.rpt", FileMode.Create));
bw.Write(content);
bw.Close();
// set up the crystal report
crdoc.Load("~/temp/temp.rpt");
// and the Crystal report Viewer
crystalReportViewer1.ReportSource = crdoc;
crystalReportViewer1.ReuseParameterValuesOnRefresh = false;
crystalReportViewer1.HasRefreshButton = true;
this.Controls.Add(crystalReportViewer1);
// clean up
File.Delete("~/temp/temp.rpt");
}
}
}
设置工具窗格(在编辑 Web Part 时显示),以便可以选择报表。这基本上是 SharePoint Web Part 的样板代码;选定的文件名会保存在基 Web Part 中。
// Display a custom editor in the tool pane,
// this gets displayed when you edit the web part settings.
public override EditorPartCollection CreateEditorParts()
{
ArrayList arEditorParts = new ArrayList();
edPart.ID = this.ID + "RptSrcEditorPart";
arEditorParts.Add(edPart);
return new EditorPartCollection(arEditorParts);
}
// Create a custom EditorPart to edit the WebPart.
class ReportSourcePart : EditorPart
{
DropDownList rptslist = new DropDownList();
// Get settings from web part.
public override void SyncChanges()
{
CustomCrystalReportWP part = (CustomCrystalReportWP)this.WebPartToEdit;
}
// Apply new settings to web part.
public override bool ApplyChanges()
{
CustomCrystalReportWP part = (CustomCrystalReportWP)this.WebPartToEdit;
part.strReportName = rptslist.SelectedValue;
return true;
}
获取 SharePoint 文档库中保存的 *.rpt 文件列表,并将它们添加到编辑器部分中的下拉列表中。
// Render the control.
protected override void CreateChildControls()
{
// Set the title to display in the properties pane
this.Title = "Crystal Reports List";
// add elements to dropdown
SPWeb thisSite;
thisSite = SPControl.GetContextWeb(Context);
SPFolder folder = thisSite.GetFolder("Crystal Reports rpt Files");
SPFileCollection files = folder.Files;
foreach (SPFile file in files)
{
rptslist.Items.Add(file.Name);
}
Controls.Add(rptslist);
this.ChildControlsCreated = true;
base.CreateChildControls();
}
}
}
现在您可以构建 Web Part 并尝试将其添加到 SharePoint Web Part 页面。在 Visual Studio 2008 中,回退、创建和部署解决方案步骤已自动化,因此您可以直接单击“调试”按钮,您的站点应该会打开,然后您可以通过将其添加到 Web Part 页面来尝试 Web Part。但是,存在两个明显的问题。工具栏上没有图标,任何图形(图表、统计图)都无法显示。您只看到一个带有红色叉号的框。
要解决这些问题:
- 工具栏图标需要在根网站上安装一些文件才能在 SharePoint 网站文件中可用。从以下位置复制:
- 解决图形显示问题更为复杂。
将文件粘贴到:
在网上搜索发现,该问题与 Crystal Reports 的动态图像 HttpHandler (CrystalImageHandler.aspx) 调用顺序混乱有关,导致其输出从未显示。我发现最令人满意的解决方案是基于一位细心的开发人员的提示,Crystal Reports 在“c:\windows\temps\cr_tmp_image__**yourSite**”中写入一个临时文件,通过在 SharePoint 网站的根文件夹中提供一个自定义的 `CrystalImageHandler.aspx` 文件及其代码隐藏文件,使用 `Response.Transmitfile` 将临时文件发送回客户端,从而解决了调用顺序混乱的问题。
复制我已包含在源代码文件中的 `CrystalImageHandler.aspx` 和 `CrystalImageHandler.aspx.cs` 这两个文件,并将它们粘贴到您的网站根文件夹中,例如:
c:Inetpub\wwwroot\wss\VirtualDirectories\80
当页面加载以显示您的图形图像时,它会被动态编译,您可以在 Visual Studio 中调试它,但前提是它能成功编译。您不会在 Visual Studio 中看到任何编译错误,您需要查看“管理工具”/“事件查看器”/“应用程序”并查找错误或警告,这应该可以帮助您解决任何问题。
这是 `CrystalImageHandler.ascx` 文件。
上面的 `Register Assembly
` 实例是处理对 Crystal Reports DLL 引用的必需项。要复制上面的代码,您需要下载源代码文件。
C# 文件构建临时文件名并将其发送回客户端。
public partial class CrystalImageHandler : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// get the Crystal Reports temporary file name
String strtempImagePath = Request.QueryString["dynamicimage"];
if (strtempImagePath != null)
{
// send the temporary image file
SPWeb thissite = SPControl.GetContextWeb(Context);
String strsitename = thissite.Site.HostName;
int iport = thissite.Site.Port;
String strport = Convert.ToString(iport);
Response.TransmitFile(@"C:\WINDOWS\Temp\cr_tmp_image__" +
strsitename + strport + "\\" + strtempImagePath);
}
}
}
Using the Code
您可以通过复制源代码或安装 `CRWPCompiledInstall.zip` 下载中的 WSP 文件来将 WebPart 安装到您的站点。安装已编译 Web Parts 的最简单方法是使用 `stsadm` 命令行实用程序,该实用程序默认位于:`C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe`。
从命令提示符,根据文件路径进行适当调整,运行:
stsadm -o addsolution -filename CustomCRWPInstall.wsp
您还需要将 `CrystalImageHandler.ascx` 和 `CrystalImageHandler.ascx.cs` 这两个文件复制到您的网站根文件夹(参见上面默认路径)。
关注点
集成 SharePoint 和 Crystal Reports 等复杂应用程序可能是一项令人沮丧且耗时的工作。有时您可能很幸运,事情会顺利进行(就像应该的那样),但通常不会,如果网上找不到简单的解决方案,您将面临一系列漫长的试错实验来找到答案,或者进行长期的学习和研究以至少成为您正在使用的技术的部分专家,但您常常会发现自己根本没有时间。
历史
- 版本 1 - 2009 年 9 月 24 日。