#RDLC #Report viewer #SSRS
▌Introduction
小弟日前完成了單張報表RDLC(以單號=XXX帶出)的情況下,使用者提出是否可同時列印多張報表(一次帶入多個單號)的需求;
因為這張報表很複雜,不太可能為了一次列印多張而重拉RDLC。
這時候比較聰明的作法就是利用「子報表」Sub-Report搭配「資料表」DataTable的方式,
重複使用既有已經設計好的報表來完成多張報表的需求。
▋Related articles
我們將延續以上文章的範例,實作利用子報表完成多張報表的功能。
▌Implement
以下是此範例將會新增的項目~
▋資料集:DataSetCityName
首先,我們必須設計一個DataSet來存放帶出多張報表的Key(參數值),例如本例的”城市名稱”, 將用來作為帶入子報表的資料庫查詢參數。
▋RDLC:CityCollection.rdlc (母報表)
在RDLC加入前一步驟的資料集。
另外我們在run time時,會將DataSetCityName裡面的Name值,注入到子報表作為參數做查詢。 所以這一張母報表需要加入子報表的資料來源。 (但是不需要子報表的資料集)
做法是先加入子報表的資料集,此時一併帶入資料來源,接著再移除子報表的資料集。
接著重頭戲來了,開始設計RDLC吧!!
先加入資料表DataTable,
我們只需資料表留一列,並加入資料集:DataSetCityName的[Name]。
接著插入一個”群組內-下方”的資料列,並加入SubReport。
插入子報表…
設定子報表要使用哪一張既有的RDLC,本例的子報表是 : City
在子報表控制項加入一個參數,其值指向DataSetCityName的[Name]。
到這邊已經完成了母報表RDLC的設計, 重點在於
l 帶入多個城市名稱給母報表RDLC
l 指派每個城市名稱給子報表RDLC作為查詢參數
▋RDLC:City.rdlc (子報表)
子報表只有一個地方需要修改,由於子報表的查詢參數是由母報表帶入,所以需要加入一個報表參數: CityName
▋ASPX:帶入資料到母報表及子報表的ReportViewer
ASPX請自行加入ReportViewer及ScriptManager控制項。
l Page_Load
以下Sample code是在Page_Load時,利用Url parameter帶入母報表所需的多個城市名稱,再存入DataSet帶入到母報表的RDLC。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var qStr =
Request.QueryString["cityNames"].ToString();
char[] separators = new char[] { ',' };
string[] cityNames =
qStr.Split(separators);
try
{
rptViewer.LocalReport.SetBasePermissionsForSandboxAppDomain(new PermissionSet(PermissionState.Unrestricted));
rptViewer.ShowPrintButton = true;
rptViewer.ProcessingMode = ProcessingMode.Local;
rptViewer.LocalReport.EnableExternalImages = true;
rptViewer.LocalReport.ReportPath = Server.MapPath("~/Reports/Rdlc/CityCollection.rdlc");
rptViewer.LocalReport.DataSources.Clear();
#region MainReport
DataSetCityName ds = getDataSet(cityNames.ToList());
ReportDataSource datasource = new ReportDataSource("DataSetCityName", ds.Tables[0]);
rptViewer.LocalReport.DataSources.Add(datasource);
#endregion
#region SubReport
rptViewer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SetSubDataSource);
#endregion
rptViewer.LocalReport.Refresh();
}
}
}
private DataSetCityName getDataSet(List<string> cityNames)
{
var dataset = new DataSetCityName();
var dataTable =
dataset.Tables[0];
foreach (var cn in cityNames)
{
var dr = dataTable.NewRow();
dr["Name"] = cn;
dataTable.Rows.Add(dr);
}
return dataset;
}
|
至於子報表的資料要如何帶入? 設定rptViewer.LocalReport.SubreportProcessing 這個delegate eventhandler來另行處理。
底下是負責SubreportProcessing的event,可以看到帶出子報表的方式其實很熟悉,
l
取得查詢的參數值(city)
l
呼叫Store Procedure
l
將資料放入DataSet
l
DataSet放入子報表RDLC的DataSource
public void SetSubDataSource(object sender, SubreportProcessingEventArgs e)
{
var city =
e.Parameters["CityName"].Values.First();
DataSetCity dsCity =
getCityData(city);
ReportDataSource datasource = new ReportDataSource("DataSetCity", dsCity.Tables[0]);
e.DataSources.Add(datasource);
}
private DataSetCity getCityData(string cityName)
{
var rtnVal = new DataSetCity();
var connString = ConfigurationManager.ConnectionStrings["JbDbContext"].ConnectionString;
var sqlConn = new SqlConnection(connString);
SqlCommand cmdReport = new SqlCommand("usp_getCitys", sqlConn);
SqlDataAdapter daReport = new SqlDataAdapter(cmdReport);
using (cmdReport)
{
SqlParameter questionIdPrm = new SqlParameter("@CityName", cityName);
cmdReport.CommandType = CommandType.StoredProcedure;
cmdReport.Parameters.Add(questionIdPrm);
daReport.Fill(rtnVal, "DataTableCity");
}
return rtnVal;
}
|
▋執行結果
原本單筆的報表(City.rdlc)
多筆的報表(CityCollection.rdlc)
▌Reference
沒有留言:
張貼留言