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);

至此,分頁就做好了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM