.NET开发报表总结
VS.NET开发中最常用的两种报表开发方式:水晶报表(Crystal Report)和RDLC(Report Definition Language Client-side processing)报表。
RDLC相对于水晶报表,具有以下优势:
1) 微软自己开发的报表组件,无须注册,直接使用,真正实现RDLC报表与.NET的无缝集成。
2) 简单易用的控件,方便用户报表设计,无须开发人员额外画线条布局,提高报表开发效率。
3) 高度可编程性,在项目甚至不需要一个报表文件,完全可通过代码实现报表生成、预览以及打印等一系列操作。
4) 支持DrillThrough数据钻取功能(类似Excel中的透视表功能)。
5) 支持导出Excel,PDF以及Word文件格式,真正实现所见即所得。
一、添加报表数据源
- 首先一个报表需要有一个数据源,一个项目里可能有许多报表来自不同的数据源,所以在vs里添加一个命名为TestReportDataSet.xsd的数据集文件,把同一个项目中所有报表的数据源都放在同一个数据集里进行设计,以便查找和修改。
- 添加数据源有三种方式,如图所示:
三种添加方式大同小异,项目中采用的是第一种方式,可通过使用命令和存储过程添加我们报表中所需要用到的字段,最终添加效果如图:
在报表里经常会有使用到二维码图片以及公司Logo,,所以可在这个数据源中添加一列取名为ImageCode,设置其数据类型为Syste.Byte[],如下图所示:
- 添加报表数据源除上述2所描述,也可动态绑定数据源,比如DataTable或者List。
二、页面代码实现
1.前台主要代码:
<div style="width: 100%;" id="divReport"> <table style="vertical-align: bottom; border-width: 0px; margin-top: 0px; margin-bottom: 0px; width: 100%; height: 100%; padding: 0px,0px,0px,0px;" cellspacing="0" cellpadding="0"> <tr> <td style="height: 100%; vertical-align: top;"> <rsweb:ReportViewer ID="ReportViewerMES" runat="server" Font-Names="Verdana" Font-Size="8pt" BackColor="White" InteractiveDeviceInfos="(集合)" WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt" Width="100%" Height="100%" ShowPageNavigationControls="true" ShowFindControls="false" ShowRefreshButton="false" ShowBackButton="false" ShowToolBar="true"> <LocalReport ReportPath="MES\Reports\MOWIPReport.rdlc"> <DataSources> <rsweb:ReportDataSource DataSourceId="ReportDataSourceMoWipQty" Name="MoWipRecord" /> </DataSources> </LocalReport> </rsweb:ReportViewer> <asp:SqlDataSource ID="ReportDataSourceMoWipQty" runat="server"></asp:SqlDataSource> </td> </tr> </table> </div>
这里需要注意两点:ReportPath需要与我们报表文件对应以及ReportDataSource中的Name命名需要与我们后续添加的报表文件中的数据集名称保持一致。
2.后台主要代码:
添加报表中需要使用到的一些参数
private void PageInitializtion() { List<ReportParameter> Paras = new List<ReportParameter>(); //单头参数 Paras.Add(new ReportParameter("ProjecName", WebUtility.GetResource("MES_ProjectMaster_ProjectName"))); Paras.Add(new ReportParameter("ProductName", WebUtility.GetResource("MES_ProductInformation_ProductName"))); Paras.Add(new ReportParameter("MOLotCode", WebUtility.GetResource("MES_MO_Lot"))); this.ReportViewerMES.LocalReport.SetParameters(Paras); this.RefreshReport(); }
绑定数据源到报表文件
方式一:
private void RefreshReport() { //报表数据查询 Image image; DataTable DT = new DataTable(); StringBuilder SB = new StringBuilder(); SB.Append("SELECT A.TRDeliverID,A.TRDeliverCode,‘[‘+A.DWorkStationCode+‘]‘+A.DWorkStationName AS DWorkStationName,"); SB.Append("‘[‘+A.DWorkCenterCode+‘]‘+A.DWorkCenterName AS DWorkCenterName,‘[‘+A.RWorkStationCode+‘]‘+A.RWorkStationName AS RWorkStationName,"); SB.Append("‘[‘+A.RWorkCenterCode+‘]‘+A.RWorkCenterName AS RWorkCenterName,B.MOID,B.MOCode,C.CustomerPO,C.Remark,B.MOLotCode,B.SendQty, "); SB.Append("C.ProjectName,C.ProductCode,C.ProductName,C.UOMName,B.CreateDate,A.Deliverer+‘ ‘+D.CHINESENAME+‘ ‘+CONVERT(varchar(100), A.DeliverDate, 23) AS Deliver, "); SB.Append("A.Receiver+‘ ‘+E.CHINESENAME+‘ ‘+CONVERT(varchar(100), A.ReceiverDate, 23) AS Receiver "); SB.Append("FROM MES_TR_DeliverHead A "); SB.Append("LEFT JOIN MES_TR_DeliverDetail B ON B.TRDeliverID=A.TRDeliverID "); SB.Append("LEFT JOIN MES_MO C ON C.MOID=B.MOID "); SB.Append("LEFT JOIN SYS_USER D ON D.USERID=A.Deliverer "); SB.Append("LEFT JOIN SYS_USER E ON E.USERID=A.Receiver "); SB.Append("WHERE A.CompanyID=‘" + this.CompanyID + "‘ "); SB.Append("AND A.TRDeliverID=‘" + this.RecordNavigationEdit.CurrentRecordID + "‘ "); DT = DBHelper.FillDataSet(SB.ToString(), CommandType.Text, null).Tables[0]; DT.Columns.Add("imageCode", Type.GetType("System.Byte[]"));//添加新列 BarCode barCode = new BarCode(); foreach (DataRow row in DT.Rows) { byte[] imgBytes = barCode.GetBarcode(200, 1000, TYPE.CODE128, row["TRDeliverCode"].ToString(), out image); row["imageCode"] = imgBytes; } var pageSettings = this.ReportViewerTRDeliver.GetPageSettings(); if (DT.Rows.Count > 1) { pageSettings.PaperSize.Width = 461; pageSettings.PaperSize.Height = 480 + 45 * (DT.Rows.Count - 1); } this.ReportViewerTRDeliver.SetPageSettings(pageSettings); ReportDataSource rds = new ReportDataSource("TRDeliver", DT); this.ReportViewerTRDeliver.LocalReport.DataSources.Clear(); this.ReportViewerTRDeliver.LocalReport.DataSources.Add(rds); this.ReportViewerTRDeliver.LocalReport.Refresh(); }
方式二:
private void RefreshReport() { this.ReportDataSourceMoWipQty.SelectCommand += "SELECT ProjectName,ProductName,WorkStationName,WorkCenterName,MOLotCode,MOCode,Sequence,TypeQty,Qty "; this.ReportDataSourceMoWipQty.SelectCommand += "FROM "; this.ReportDataSourceMoWipQty.SelectCommand += "( "; this.ReportDataSourceMoWipQty.SelectCommand += "SELECT ProjectName,ProductName,A.WorkStationName,WorkCenterName,MOLotCode,MOCode,B.Sequence,"; this.ReportDataSourceMoWipQty.SelectCommand += "WProductQty,WSendQty,WQCQty,WJudgeQty,WReworkQty,WScrapQty,OutsideProcessQty "; this.ReportDataSourceMoWipQty.SelectCommand += "FROM MES_MO_WIP A "; this.ReportDataSourceMoWipQty.SelectCommand += "LEFT JOIN MES_MD_WorkStation B ON B.WorkStationCode=A.WorkStationCode AND B.DepartmentID=A.DepartmentID "; this.ReportDataSourceMoWipQty.SelectCommand += "WHERE TROutputID=‘‘ "; this.ReportDataSourceMoWipQty.SelectCommand += ")T "; this.ReportDataSourceMoWipQty.SelectCommand += "UNPIVOT "; this.ReportDataSourceMoWipQty.SelectCommand += "( "; this.ReportDataSourceMoWipQty.SelectCommand += "Qty FOR TypeQty IN (WProductQty,WSendQty,WQCQty,WJudgeQty,WReworkQty,WScrapQty,OutsideProcessQty ) "; this.ReportDataSourceMoWipQty.SelectCommand += ")P "; this.ReportDataSourceMoWipQty.SelectCommand += "WHERE Qty>0 "; if (!string.IsNullOrEmpty(this.Request.QueryString["WIPType"])) { string[] types = this.Request.QueryString["WIPType"].Split(new char[] { ‘,‘ }); string wipType = string.Empty; foreach (string type in types) { wipType+= "‘" + type + "‘,"; } wipType = wipType.Substring(0, wipType.LastIndexOf(‘,‘)); this.ReportDataSourceMoWipQty.SelectCommand += "AND TypeQty IN ("+wipType+") "; } this.ReportViewerMES.LocalReport.Refresh(); }
一般情况下我们采用第二种方式进行报表数据源绑定,如若有动态列添加的则采用第一种方式。
三、设计报表文件
1.在VS中添加RDLC报表文件,然后在报表数据窗口中选择数据源以及对应的数据集,特别注意名称命名必须与页面上的Name保持一致,否则可能会出现找不到数据源错误,如下图所示:
2.设计报表。在RDLC报表中基本可以满足用户的所有展现要求,可插入文本,矩阵,图表,子报表以及图像等一系列呈现方式。
- 在报表设计页面单击鼠标右键可设置一些报表属性,主要用于报表打印设置,如下图所示:
也可以在后台用代码根据设置一些属性来设置打印的样式,具体代码如下图所示:
- 报表向下钻取功能。先看效果图:
下面我们具体分析下上图报表是如何呈现出来的。首先我们看下我们的报表设计结构图:
在报表中有个非常重要的属性:组属性。我们可以根据设置组属性动态的显示行列数据。显然,组属性分为行组和列组,如图所示:
组属性都有些什么属性可以进行设置呢,如下图所示:
常规:设置组名称和分组方式。可以添加多个分组方式,类似SQL中的分组,根据项目实际需要对数据进行分组得到我们需要的结果。
分页符:设置报表分页符呈现样式。
排序:设置行列数据根据某数据字段进行排序,默认按字母A~Z进行排序。
可见性:这个是设置报表向下钻取非常重要的一个属性。
可以控制某数据字段在报表最初运行时的显示或隐藏,如上图所示。
筛选器:可以根据设置某些表达式条件来筛选一些符合条件的组值:
至于变量和高级在项目中未实际运用过,不再赘述。
还有一个问题就是如何控制某一列字段的数据在报表最初运行时是折叠(+)还是展开(-),在上述设置中只能设置全部折叠或全部展开。如何灵活控制某字段的切换状态?
有时候我们很容易忽略一个点就是在所有上述报表属性设置其实都可以在视图—属性中进行所有设置:
在该面板中可以设置某个文本框的属性,同时可以根据某些条件控制该文本框的初始状态,如上所示,不再赘述。
RDLC报表还有一个最大的特点就是自动汇总(SUM)。用户可以根据某些条件灵活控制:
以上记述,为以后工作方便仅此而已。