开源 RDL 引擎






4.77/5 (11投票s)
一个用于将报表呈现到 WinForms 或 ASP.NET 的开源 RDL 引擎
引言
Sawiki RDL 报表引擎用于将 RDL 报表呈现到 ASP.NET 或 Winforms 查看器。它还可以将呈现的报表导出为 XLS、PDF 或 CSV 格式文件。
RDL 引擎读取在 Microsoft Visual Studio 中创建的 RDL 文件,连接到引用的数据库,收集参数信息并呈现生成的报表。它目前支持所有 RDL 功能,但 3D 图表、列、递归层次结构、文档地图和固定页眉除外。它包括完整的 VB.NET 支持,包括导入外部库。
这是一个轻量级的高速报表渲染器,并包括一个 RDL 编译器,以进一步提高报表项目的性能。对于希望将 Microsoft Reporting Services 报表部署到网站而无需支付 SQL Server 许可证的人员,或在 WinForms 应用程序中部署报表的人员,它非常有用。
背景
启动此项目的目的是为了将 RDL 报表包含到网站中,而无需为 Web 服务器向 Microsoft 支付 SQL Server 许可证。而且,我不喜欢 Microsoft ASP.NET 报表查看器的工作方式。我花了一些时间在开源项目 RDL Project 3 上,但对部分 VB 解释器和复杂的渲染算法不满意。
该引擎使用 VBCodeProvider
类(来自 Microsoft.VisualBasics
命名空间)将任何包含的源代码和表达式编译成程序集。程序集中的每个函数都被放入一个委托列表中,这些委托可以在报表处理期间按索引调用。唯一不能直接编译的表达式是包含聚合函数(如 Sum
、Avg
等)的表达式。对于这些,RDL 报表中的 VB 源代码使用正则表达式进行修改,以将任何聚合函数调用包装到一个迭代器中。
渲染到中间模型,然后渲染到最终形式。中间模型由 GenericRender
类表示,该类由 Report.Run
方法返回。GenericRender
表示一个简单的盒子模型,可以很容易地转换为最终渲染类之一。这些包括 RenderToHtml
、RenderPagesToHtml
、RenderToText
、RenderToCsv
、RenderToXls
和 RenderPagesToPdf
。WinForms 查看器直接与 GenericRender
类一起工作。 GenericRender
类的简单盒子模型允许简单地渲染成各种最终形式,这可以从 RenderToText
类总共不到 100 行代码看出来。
Using the Code
RDL 引擎包含四个元素
RDLEngine
- 基本库,包含 RDL 解释器和渲染引擎。这需要在任何报表项目中包含。RDLAsp
- ASP.NET 库,包括报表查看器控件、参数控件、打印功能和导出功能。RDLViewer
- WinForms 库,包括报表查看器、参数控件、参数对话框、打印和导出功能RDLCompile
- RDL 编译器,用于将 RDL 报表编译成 .NET 程序集。
要读取 RDL 报表,设置一些参数并将呈现的报表写入 PDF 和 XLS,请使用以下内容
// Create a new Report object and load an RDL report definition
Rdl.Engine.Report rpt = new Rdl.Engine.Report();
FileStream fs = new FileStream("Product Line Sales.rdl", FileMode.Open);
rpt.Load(fs, ".");
fs.Close();
// Set parameters
rpt.ReportParameters["Category"].Value = 1;
rpt.ReportParameters["StartDate"].Value = DateTime.Now;
rpt.ReportParameters["EndDate"].Value = DateTime.Now.AddMonths(-1);
// Render the report
Rdl.Render.GenericRender render = rpt.Run();
// Export to XLS and write to a file
Rdl.Render.RenderToXls xlsExport = new Rdl.Render.RenderToXls();
string xls = xlsExport.Render(render, false);
StreamWriter sw = File.CreateText("Product Line Sales.xls");
sw.Write(xls);
sw.Close();
// Export to PDF and write to a file
PageRender pr = new Rdl.Render.PageRender();
pr.Render(render);
Rdl.Render.RenderPagesToPdf pdfExport = new Rdl.Render.RenderPagesToPdf();
string pdf = pdfExport.Render(render, pr);
sw = File.CreateText("Product Line Sales.pdf");
sw.Write(pdf);
sw.Close();
以下 ASP.NET 页面包括一个 ReportViewer
控件和一个参数控件。当按下 Button6
时,参数控件将加载“产品线销售额”报表。参数控件包括一个查看按钮,按下该按钮时会触发 ViewReport
事件,在该事件中,报表被呈现并加载到 ReportViewer
控件中。
<%@ Page Language="C#" MasterPageFile="~/Sawiki.master"
AutoEventWireup="true" CodeFile="Samples.aspx.cs"
Inherits="_Samples" Title="Sawiki Software Samples" %>
<%@ Register TagPrefix="uc" Assembly="RdlAsp"
Namespace="RdlAsp" %>
<%@ Register Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<%@ Register Assembly="System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI" TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="
ContentPlaceHolder1" Runat="Server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<asp:Button ID="Button6" runat="server"
OnClick="ProductLineSales_Click" Text="Product Line Sales" />
<table>
<tr>
<td>
<uc:Parameters ID="ReportParameters"
runat="server" OnViewReport="
ReportParameters_ViewReport" />
</td>
</tr>
<tr>
<td>
<uc:ReportViewer ID="ReportViewer" runat="server" />
</td>
</tr>
</table>
</div>
</asp:Content>
附带代码
protected void ReportParameters_ViewReport
(object sender, RdlAsp.ViewReportEventArgs e)
{
// When the ParameterEntry control posts this event
// render the passed report and load the ReportViewer with it
Rdl.Engine.Report rpt = e.Report;
Rdl.Render.GenericRender render = rpt.Run();
ReportViewer.SetReport(render);
}
protected void ProductLineSales_Click(object sender, EventArgs e)
{
// Load the report
Rdl.Engine.Report rpt = new Rdl.Engine.Report();
string path = Request.MapPath("SampleReports\\Product Line Sales.rdl");
FileStream fs = new FileStream(path, FileMode.Open);
rpt.Load(fs, System.IO.Path.GetDirectoryName(path));
// Put the report into the Parameters control
ReportParameters.SetReport(rpt);
ReportViewer.SetReport(null);
}
在以下 WinForms 示例中,假设您有一个包含参数控件、一个 ReportViewer
控件和一个名为 btnEmployeeSalesSummary
的按钮的窗体。当按下该按钮时,将加载“员工销售额摘要”报表并将其放入参数控件中。当按下“参数”查看按钮时,将引发 ViewReport
事件,在该事件中,报表被呈现并放入 ReportViewer
控件中。在此示例中,注册了 InitializeDataSet
事件,如果程序员希望用自定义数据表替换 RDL 报表中定义的数据表,则可以使用该事件。
private void Form1_Load(object sender, EventArgs e)
{
parametersEntry1.ViewReport +=
new EventHandler<RdlViewer.ParametersEntry.ViewReportEventArgs>(ViewReport);
}
static void rpt_InitializeDataSet(object sender,
Rdl.Runtime.InitializeDataSetEventArgs args)
{
switch(args.DataSetName)
{
case "SalesEmps":
// You could replace the default data with a
// custom data table for any of the named datasets here.
//e.dt = {your custom datatable}
break;
default:
break;
}
}
private void ViewReport(object sender, RdlViewer.ParametersEntry.ViewReportEventArgs args)
{
// When the ParameterEntry control posts this event
// render the passed report and load the ReportViewer with it
Rdl.Render.GenericRender render = args.Report.Run();
reportViewer1.SetReport(render);
}
private void btnEmployeeSalesSummary_Click(object sender, EventArgs e)
{
// Load the report and put it into the ParameterEntry control
Rdl.Engine.Report rpt = new Rdl.Engine.Report();
rpt.Load(new FileStream(@"Employee Sales Summary.rdl",
FileMode.Open, FileAccess.Read, FileShare.Read),
@".");
rpt.InitializeDataSet += rpt_InitializeDataSet;
parametersEntry1.SetReport(rpt);
}
参考文献
SawikiSoft RDL 引擎项目的所在地。 您可以在此站点上找到可查看的示例报表和当前的源代码。
历史
- 2010 年 12 月 17 日:初始版本