知方号

知方号

ReportViewer,RDLC 报表开发之分页

前段时间开发报表,采用了 ReportViewer + RDLC , 开发整理如下.

分页思路

MS 的DataGrid ,GridView,和 ReportViewer 分页机制差不多,都需要绑定全部数据,MS控件自动处理分页。 只是ReportViewer 是按页面布局分页的,而不是按数据条数。绑定全部数据的方式会无谓的增加服务器压力,尤其是数据计算和表关联多的情况下。为了减轻服务器压力,我们采用数据分页,数据传到应用服务器端后,再加工一下(插入空数据),做也可分页数据源。

如果数据库有 100 条数据,每页10条数据,那存储过程返回10条数据后,还需要再插入90条数据。当数据大的时候,插入的数据也很多。有没有插入数据再少一点的办法呢?

当然是有了,没有就不写了。。先提两个概念:维度和指标.

维度: 是指公司,项目,区域等要分析的对象.

指标: 是指针对维度进行计算的结果

1. 先对维度进行分页. 

2.针对分页结果,有针对性的进行指标计算 ,可以把每个计算列,做成函数,方便调用,同时,也方便维护和测试。

实现方案

方案是把页码做成分组,这样再插入的时候,就只插入 Celling( 90 ÷ 10 ) 条的空分组数据即可。 插入的数据少了 n 倍。

存存过程示例代码:

CREATE proc [dbo].[R_ANALYSIS] ( @Query varchar(50)= ', --查询条件 @PageIndex int = 1 , --从1开始 @PageSize int = 50 , --每页条数,传入 0 ) begin --计算 @RowCount set @PageCount = ceiling( @RowCount *1.0 / @PageSize) ;

end else begin set @PageCount = 1 end

end

所需要的两个程序加工函数:

public static IEnumerable ReportWrap(this IEnumerable Source, int CurrentPageIndex, int PageCount) where T : IReportModel, new() { if (PageCount < 2) { foreach (var item in Source) { yield return item; } yield break; }

Func CreateEmptyObj = (CurrentIndex) => { T retVal = new T();

retVal.SysPageIndex = CurrentIndex;

return retVal; };

for (int i = 0; i < CurrentPageIndex; i++) { yield return CreateEmptyObj(i + 1); }

foreach (var item in Source) { item.SysPageIndex = CurrentPageIndex + 1; yield return item; }

for (int i = CurrentPageIndex + 1; i < PageCount; i++) { yield return CreateEmptyObj(i + 1); } }

public static DataTable ReportWrap(this DataTable Source, int CurrentPageIndex, int PageCount){ if (PageCount { DataRow retVal = Source.NewRow();

retVal["SysPageIndex"] = CurrentIndex;

return retVal; };

for (int i = 0; i < CurrentPageIndex; i++) { Source.Rows.InsertAt(CreateEmptyObj(i + 1), 0); }

for (int i = CurrentPageIndex + 1; i < PageCount; i++) { Source.Rows.Add(CreateEmptyObj(i + 1)); }

return Source;}

程序调用函数代码,很简单:

DataTable dt = db.Exec_SP_DataTable("sp_Report_ModuleVisitStatisView", pars);pageCount = Convert.ToInt32(pars[6].Value);dt.ReportWrap(pageIndex -1 , pageCount);

之后,再把 DataTable 转成 实体列表。方便RDLC数据绑定。

另注:

上面的 IReportModel , 是一个只包含 SysPageIndex 属性的接口. 它约束了报表返回的Model 必须继承自 IReportModel 且必须拥有 无参构造函数.

1. 无参构造函数的作用是 初始化空对象. 比如: 字符串类型的,要设置为 string.Empty . 数值类型要设置为 0.

2.接口是约束Model 必须具有 SysPageIndex 属性用于页码值.

 

报表RDLC 的设置:

绑定数据源,添加父组,选 SysPageIndex。在该列的属性上设置: Hidden = True , Width = 0cm。即隐藏该列。后端绑定代码:

ReportDataSource data = new ReportDataSource("LogSource", MyBiz.GetLogReportData("query", pageIndex, pageSize, out pageCount));

this.ReportViewer1.LocalReport.LoadReportDefinition(new FileStream(Server.MapPath("~/Admin/Report/Log.rdlc")));this.ReportViewer1.LocalReport.DataSources.Clear();this.ReportViewer1.LocalReport.DataSources.Add(data);

至此,分页就做好了.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。