本文只代表作者在一定阶段的认识与理解
一.写作前提
前面几篇中我讲了如何去实现一个RDLC报表、插入图片、参数传递及常用表达式的使用。这一节我们将focus on子报表的使用。假设有一天,你的老板和你说,公司需要做所有员工的出出差记录,这时子报表的应用是一个不错的选择。
关于怎样创建一个RDLC报表等相关内容,前查看我之前的文章,这里就不在阐述了。
二. 本文内容
1. RDLC报表模板的设计
2. Base的修改
3. 调用生成报表
4. 总结
5. 代码下载(下载)
三.RDLC报表模板设计
本篇要做的是一个含有子报表的报表,所以,最少我们需要两个报表模板,一个是Master.rdlc,另外一个是Sub.rdlc。Ok,下面我们就来啰嗦一下怎么设计模板文件吧。
1. 在VS(本人用的是2008的Version,自从小2003之后都支持.rdlc报表)中创建一个新的web application项目。
2. 新增两个新的报表文件,一个名叫master.rdlc,一个名叫sub.rdlc(在选择的时候要注意选择如下)。

3. 现在我们已经有报表模板文件了,再创建主报表和子报表所需要使用的数据类型(所需要的DataSet类型,具体可参阅[原创] RDLC 报表系列(一) 创建一个报表),这里并不多做解释了。
4. 打开 style="mso-bidi-font-weight:bold">master.rdlc文件,从工具箱中拖入一表格控件,设计你所需要的格式,选择所需要的数据源类型,然后在你需要使用子报表的地方从工具臬中插入一上SubReport控件,如下图所示。
5. 然后右击这个SubReport控件,在属性中选择这个子报表指向哪个文件,我们可以选择刚才创建的那个sub.rdlc文件。其次是们还需要为主报表和子报表之关建立关连关系,在属性的Parameters(参数)选择卡中新加我们需要传递给子报表的参数。
在我的报表中用了一个参数如下,当然你也可以根据自己的的需要创建多个你需要传递给子报表的参数。

6. 上面我们讲解完了主报表的设计,他制定了子报表以及子报表准获得的参数。现在打开Sub.rdlc文件,增加子报表所需要的数据源类型,并且创建参数,比如说我上面使用了一个isoOid,所以在子报表中一定有一个参数名称和这个是相同的,他用来接收从主报表传来的筛选数据条件,即用这个参数从子报表中选择符合本记录的所有子记录集。
7. 现在从工具箱中插入一个表格到你的子报表中(当然也可以不需要表格,根据需求定义的),然后右击属性选择所需要的数据源类型,并且根据从Master.rdlc传过来的参数进行筛选,可以在属性窗口的Filters(筛选)选项卡中加入筛选条件即可。
8. 至此我们讲完了报表设计部分,下面我们就去看看,C#中是如何实现的。
四.Base的修改
因为是要用到报表,所以我们需要对子报表的生成事件进行订阅,因此我们把CustomPageBase写成如下。
1
public
class
CustomPageBase : Page
2
{
3
List
<
ReportDataSource
>
subDataSource
=
new
List
<
ReportDataSource
>
();
4
public
void
GetReportMultipleDataSourceFile(List
<
ReportDataSource
>
reportDateSource,
string
TemplatePath, List
<
ReportParameter
>
parameterList,
string
FileType, List
<
string
>
subDataList)
5
{
6
string
reportFormat
=
FileType;
7
string
outputfile
=
"
Report.
"
;
//
报表名称
8
ReportViewer rview
=
new
ReportViewer();
9
rview.ProcessingMode
=
ProcessingMode.Local;
10
rview.LocalReport.ReportPath
=
Server.MapPath(TemplatePath);
11
rview.LocalReport.DataSources.Clear();
12
13
//
为主报表加数据源
14
foreach
(ReportDataSource re
in
reportDateSource)
15
{
16
if
(subDataList.Contains(re.Name))
17
{
18
subDataSource.Add(re);
19
continue
;
20
}
21
rview.LocalReport.DataSources.Add(re);
22
}
23
24
//
设置ReportViewer进行事件订阅
25
rview.LocalReport.SubreportProcessing
+=
26
new
SubreportProcessingEventHandler(SubreportProcessingEventHandler);
27
28
if
(parameterList.Count
>
0
)
29
rview.LocalReport.SetParameters(parameterList);
30
string
mimeType, encoding, extension, deviceInfo;
31
string
[] streamids;
32
Warning[] warnings;
33
deviceInfo
=
"
<DeviceInfo>
"
+
"
<SimplePageHeaders>True</SimplePageHeaders>
"
+
"
</DeviceInfo>
"
;
34
35
byte
[] bytes
=
rview.LocalReport.Render(reportFormat, deviceInfo,
out
mimeType,
out
encoding,
out
extension,
out
streamids,
out
warnings);
36
HttpContext.Current.Response.Buffer
=
true
;
37
HttpContext.Current.Response.Clear();
38
HttpContext.Current.Response.ContentType
=
mimeType;
39
HttpContext.Current.Response.AddHeader(
"
Content-Disposition
"
,
"
attachment; filename=
"
+
outputfile
+
extension
+
"
;
"
);
40
HttpContext.Current.Response.BinaryWrite(bytes);
41
HttpContext.Current.Response.End();
42
}
43
44
///
<summary>
45
///
为子报表加数据源
46
///
</summary>
47
///
<param name="sender"></param>
48
///
<param name="e"></param>
49
void
SubreportProcessingEventHandler(
object
sender, SubreportProcessingEventArgs e)
50
{
51
foreach
(var ReportDataSource
in
subDataSource)
52
{
53
e.DataSources.Add(ReportDataSource);
54
}
55
}
56
}
和这前的相关,GetReportMultipleDataSourceFile这个文件多提供一了一个新的参数subDataList他是用来指定哪些数据源是给子报表的。
五.调用生成报表
1
public
partial
class
_Default : CustomPageBase
2
{
3
protected
void
Page_Load(
object
sender, EventArgs e)
4
{
5
6
}
7
8
///
<summary>
9
///
Generate the report
10
///
</summary>
11
///
<param name="sender"></param>
12
///
<param name="e"></param>
13
protected
void
ButtonGenerate_Click(
object
sender, EventArgs e)
14
{
15
List
<
ReportDataSource
>
reportDataSource
=
new
List
<
ReportDataSource
>
();
16
List
<
string
>
subDataSource
=
new
List
<
string
>
();
17
ReportDataSet ds
=
new
ReportDataSet();
18
string
templatePath
=
string
.Empty;
19
20
SqlConnection conn
=
new
SqlConnection(ConfigurationManager.ConnectionStrings[
"
PQMSConnectionString
"
].ConnectionString);
21
SqlCommand comm
=
conn.CreateCommand();
22
comm.CommandText
=
"
select top 200 Oid, DrawingNumber, CWPNo, PaintCode, MasterRevision from ISO_DRAWING
"
;
23
SqlDataAdapter da
=
new
SqlDataAdapter(comm);
24
da.Fill(ds,
"
ISO_DRAWING
"
);
//
获得主表的内容(Get master table data)
25
26
comm.CommandText
=
"
SELECT S.Oid, S.ISOOid, S.SPOOLNo, S.Location, S.IssueNo, S.CP2 FROM SPOOL AS S INNER JOIN (SELECT TOP 200 OID FROM ISO_DRAWING) AS T ON S.ISOOID = T.OID
"
;
27
da
=
new
SqlDataAdapter(comm);
28
da.Fill(ds,
"
SPOOL
"
);
29
30
reportDataSource.Add(
new
ReportDataSource(
"
ReportDataSet_ISO_DRAWING
"
, ds.ISO_DRAWING));
31
reportDataSource.Add(
new
ReportDataSource(
"
ReportDataSet_SPOOL
"
, ds.SPOOL));
32
subDataSource.Add(
"
ReportDataSet_SPOOL
"
);
33
List
<
ReportParameter
>
parameterList
=
new
List
<
ReportParameter
>
();
34
35
templatePath
=
"
Master.rdlc
"
;
36
37
GetReportMultipleDataSourceFile(reportDataSource, templatePath, parameterList,
"
PDF
"
, subDataSource);
38
}
39
}
六.总结
通过上面的学习,我们了解如下内容:
1. Sub Report Design
2. Filter的应用