介绍:
这篇文章是前天看园子里给的一个链接,具体是谁的我忘记了,只记得http://www.codeproject.com/aspnet/ReportViewer.asp这个地址被贴了出来,然后说因为什么原因就没翻译完。我后来看了下正好对自己有用,因为公司里RS的东西有人在做,而楼下光电部门的BS需求也经常有,并且早就知道有这个东西只是一直没时间研究,正好找到这个文章,于是就好好的研究了一下午,先翻译一下,然后再补充点心得。
翻译的过程中尽量本地化了一下,不过保留了原文作者的意思。如果有翻译不贴切的地方请各位朋友批评指正。
在网上有很多关于SqlServer RS 的服务模式(Server Mode),而我在研究本地模式(Local Mode)确实用了很长的时间,尤其还是有参数调用的时候。
之所以要用本地模式而不是服务器模式,是因为服务模式的客户端每次请求一个报表的时候,服务器都要把数据组织成报表然后发送到客户端,虽然这样子安全些,但是巨型报表从服务器到浏览器的传输会降低其性能。
所以这个文章是描述如何组织报表并且用ASP.NET2.0的ReportViewer控件读取出来的,这里我们选用的就是本地模式,并且是使用带参数的存储过程。我所使用的是ASP.NET2.0,VisualStudio2005,还有SQLServer2005加Application Block。如果你没有Microsoft Application Block这个工具,那么就请把示例中通过SQL Helper调用存储过程的代码换成SQL Command的就可以了。
在这里我们选用Northwind数据库,我们的示例展现给用户的就是让用户从下拉列表里选择货品名称然后在报表里筛选出信息来。
第一步,创建带参数的存储过程
ALTER PROCEDURE ShowProductByCategory(@CategoryName nvarchar(15) )
AS
SELECT Categories.CategoryName, Products.ProductName,
Products.UnitPrice, Products.UnitsInStock
FROM Categories INNER JOIN Products ON
Categories.CategoryID = Products.CategoryID
WHERE CategoryName=@CategoryName
RETURN
第二步,使用DataSet设计器创建一个DataSet下的DataTable
在解决方案管理器界面里,右键App_Code这个文件佳,选择”Add New Item”。在弹出的对话框里选择”DataSet”,给它起个名,比如DataSetProducts.xsd,然后点击”Add”按钮。这时候TableAdapter配置工具会自动出现,如果没有出现或者误将其关闭了的话,在DataSet设计器的任何一个地方点击鼠标右键,选择Add,然后再选择TableAdapter这个工具就会再次出现。根据向导来建立DataTable,在出现的界面中分别选择”User existing stored procedures”作为命令类型然后指定”ShowProductByCategory”作为Select命令。
在第一步创建的存储过程在第二步里就变成了一个DataTable,而报表数据就是通过这个DataTable提供的。
图一:包含一个DataTable的DataSetProducts.xsd就是报表的数据源
第三步:创建一个报表文件
在解决发方案管理器下右键选择Add New Item,然后选择Report模板。在这个示例里是直接用默认的名Report.rdlc的。rdl的意思是报表定义语言,c的意思就是客户端(client)。也就是说,rdl是个服务器报表,而rdlc是本地报表。
在工具箱里把Table拖拽到报表设计窗体中,这个”表”有三个部分,头,内容和尾。一个Table就是一个显示数据的区域,一个区域显示的是被绑定到的DataSet下的那些数据元素。尽管一个报表是可以拥有很多的区域的,但是,每个区域只能显示一个DataSet里的内容。基于这点,我们可以用存储过程来联合多张表的数据到一个DataSet里来填充报表。
图二:工具栏里的专门做报表模板的控件
打开”网站数据源”窗口,找到”DataSetProducts”数据集,就是在第二步里创建的那个。展开直到看到叫”ShowProductByCategory”的这个DataTable。这个Table叫这个名字是因为我们之前在TableAdapter配置向导里选择了“Use existing stored procedure”这项,并且我们的存储过程的名字就叫ShowProductByCategory。
在网站数据源窗口中依次把ProductName,UnitPrice和UnitsInStock这三项分别拽到报表设计器里显示细节的那一行,也就是中间那行的第一列,第二列和第三列。而且你可以右键单击任何一个显示细节行中的字段,然后在属性栏里找到Format标签来为Unit Price和Unit In Stock来定义它们的显示格式。
图三,网站数据源窗体显示了在你程序里定义的DataSet以及它们所拥有的列
第四步:在ASP.NET2.0页里加入ReportViewer控件
首先把DropDownList控件拽到表单里,然后用选择数据源选项的方法把Categories里的CategoryName字段进行绑定。在其它场景中用户可以通过其它方法比如文本框的方式来输入参数然后传递到存储过程当中。
然后,把Report View控件拖拽到表单中,并且设置其Visible属性为False。还有需要注意的地方就是,ASP.NET2.0的Report Viewer提供Excel和PDF的导出方式,然而实际的过程中我发现,打印出来的报表和你设计时的样子总会有点误差。
图四,把这页设置成为StartUp页
下一步,调出Report Viewer的智能标签,选择刚才建立好的Report.rdlc文件。
图五,把报表定义文件联合到Report Viewer控件里。
第五步:写代码实现用户在下拉框选择不同的名称然后报表里显示不同的数据
这里不要忘记把Microsoft.Reporting.WebForms命名空间加入到你的code-behind(或code file)文件里。
1<PRE lang=cs id=pre1 style="MARGIN-TOP: 0px">using System;
2using System.Data;
3using System.Data.SqlClient;
4using System.Configuration;
5using System.Collections;
6using System.Web;
7using System.Web.Security;
8using System.Web.UI;
9using System.Web.UI.WebControls;
10using System.Web.UI.WebControls.WebParts;
11using System.Web.UI.HtmlControls;
12using Microsoft.ApplicationBlocks.Data;
13using Microsoft.Reporting.WebForms;
14
15public partial class ReportViewerLocalMode : System.Web.UI.Page
16{
17 public string thisConnectionString =
18 ConfigurationManager.ConnectionStrings[
19 "NorthwindConnectionString"].ConnectionString;
20
21 /**//*I used the following statement to show if you have multiple
22 input parameters, declare the parameter with the number
23 of parameters in your application, ex. New SqlParameter[4]; */
24
25 public SqlParameter[] SearchValue = new SqlParameter[1];
26
27 protected void RunReportButton_Click(object sender, EventArgs e)
28 {
29 //ReportViewer1.Visible is set to false in design mode
30 ReportViewer1.Visible = true;
31 SqlConnection thisConnection = new SqlConnection(thisConnectionString);
32 System.Data.DataSet thisDataSet = new System.Data.DataSet();
33 SearchValue[0] = new SqlParameter("@CategoryName",
34 DropDownList1.SelectedValue);
35
36 /**//* Put the stored procedure result into a dataset */
37 thisDataSet = SqlHelper.ExecuteDataset(thisConnection,
38 "ShowProductByCategory", SearchValue);
39
40 /**//*or thisDataSet = SqlHelper.ExecuteDataset(thisConnection,
41 "ShowProductByCategory", dropdownlist1.selectedvalue);
42 if you only have 1 input parameter */
43
44 /**//* Associate thisDataSet (now loaded with the stored
45 procedure result) with the ReportViewer datasource */
46 ReportDataSource datasource = new
47 ReportDataSource("DataSetProducts_ShowProductByCategory",
48 thisDataSet.Tables[0]);
49
50 ReportViewer1.LocalReport.DataSources.Clear();
51 ReportViewer1.LocalReport.DataSources.Add(datasource);
52 if (thisDataSet.Tables[0].Rows.Count == 0)
53 {
54 lblMessage.Text = "Sorry, no products under this category!";
55 }
56
57 ReportViewer1.LocalReport.Refresh();
58 }
59}</PRE>
第六步:运行报表
按F5键,单击”Run Report”按钮运行报表。
图六,运行报表
最后要确定ReportViewer被引入到网站中,并且要配置下web.config文件,它有可能是如下的格式:
<httpHandlers>
<add path="Reserved.ReportViewerWebControl.axd" verb="*"
type="Microsoft.Reporting.WebForms.HttpHandler,
Microsoft.ReportViewer.WebForms,
Version=8.0.0.0, Culture=neutral,
PublicKeyToken=?????????????"
validate="false" />
</httpHandlers>
当把有ReportViewer控件的网站项目部署到别的服务器的时候,你需要把C:Program FilesMicrosoft Visual Studio 8SDKv2.0BootStrapperPackagesReportViewerReportViewer.exe这个文件拷贝出来,然后在目标服务器运行一下。
翻译心得:似乎做过的翻译中这个是最简单的了,不过可能也是作者说的比较简介明了。
学习心得:作者阐述了两种ReportViewer能接受的报表方式并且做了简单的分析。不过在实际项目中用Server Mode的可能会更多些吧,Local Mode做一些不是规模太大或者太复杂的报表还是可以的。
公司里有专门做RS的我知道,据说做就要做一周,运行的时候看编写的质量,十分钟是正常的,而超过三十分钟的话就可能需要考虑改算法了。听起来好恐怖,呵呵,不过,如果能用到楼下光电部门的报表需求的话,我想要比以前GridView to Excel的方式更舒服一些。
如果这个能研究明白的话打算做一个专门的入门视频讲解来帮助更多的人了解这个控件。