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 表⽰不分页。
@PageCount int=0 output --总页数输出参数
)
as
begin
declare@RowCount int ;
--写业务,返回分页结果 , 分页结果放到表变量 @list 中
/*⽰例:
With Query_Rank as
(
select ROW_NUMBER() OVER (order by 1 )as RowNumber ,*
分页预览from T_ROOM
)
select Col1,col2, dbo.Func1(Col1) , dbo.Func2(col1,col2)
fromQuery_Rank
whereRowNumber between 100 and 150
*/
if(@PageSize>0 )
begin
--计算 @RowCount
set@PageCount=ceiling( @RowCount*1.0/@PageSize) ;
end
else
begin
set@PageCount=1
end
end
所需要的两个程序加⼯函数:
public static IEnumerable<T> ReportWrap<T>(this IEnumerable<T> Source, int CurrentPageIndex, int PageCount)
where T : IReportModel, new()
{
if (PageCount < 2)
{
foreach (var item in Source)
{
yield return item;
}
yield break;
}
Func<int, T> 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 <=1)
{
return Source;
}
Func<int, DataRow> CreateEmptyObj = (CurrentIndex) =>
{
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);
⾄此,分页就做好了.
发布评论