zoukankan      html  css  js  c++  java
  • 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);

    至此,分页就做好了.

    alarm   作者:NewSea     出处:http://newsea.cnblogs.com/    QQ,MSN:iamnewsea@hotmail.com

      如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。
  • 相关阅读:
    java 8 stream sql left join =》 jooq & Flink & Scala
    Maven error: lambda expressions are not supported in -source 1.7
    error C2039: 'SetWindowTextA' : is not a member of 'CString'
    循环队列(循环数组)中元素个数的计算
    数据结构之堆
    理解C语言声明的优先级规则
    内联汇编中的asm和__asm__
    程序启动时的堆栈
    局部变量与堆栈
    BCD码干什么用的?
  • 原文地址:https://www.cnblogs.com/newsea/p/2379250.html
Copyright © 2011-2022 走看看