它确实有效,但它肯定是挑剔的。
我建议的第一件事是将您的报告开发为 .rdl。以这种方式测试报告要容易得多。您还可以将子报表参数设置和测试为 rdl,确保子报表的每个参数也定义为父报表的参数。一旦您获得报告(包括子报告)以这种方式工作,您可以将 .rdl 重命名为 rdlc 并将 rdlc 文件添加到您的 ReportViewer 项目中。无需进一步更改。使用 rdl 数据源的名称作为代码中的数据源名称,以向 SubreportProcessing 事件处理程序中的报表提供数据。
您不会为传递的参数赋值。子报表将按原样使用它们。(听起来您缺少的步骤是将参数添加到父报表以及上面提到的子报表。)您可以评估参数并将它们用作查询参数以获取您将添加的数据源。您必须考虑数据源,就像它在子报表的未发现维度上一样。在事件处理程序中调试时,您将不得不四处寻找以了解我的意思。您的应用程序中的某些值将很容易获得,而您在其他地方轻松使用的其他值将引发 object not found 异常。例如,我在应用程序主窗体上创建的类的实例中创建数据集。我在整个应用程序中使用数据集。在 SubreportProcessing 事件处理程序中,我不能使用公共数据集,所以我必须为报告创建一个我需要的表的新实例并填充它。在主报告中,我将能够访问公共数据集。还有其他类似的限制。只需要涉水而过。
这是来自工作中的 VB.NET ReportViewer 应用程序的 SubreportProcessing 事件处理程序。显示获取子报表数据源的几种不同方法。subreport1 从应用程序业务对象构建单行数据表,subreport2 提供报表所需的数据,不带参数,subreport3 是 subreport2,但会评估传递给子报表的参数之一,以便在创建 ReportDataSource 的查询所需的日期值中使用。
Public Sub SubreportProcessingEventHandler(ByVal sender As Object, _
ByVal e As SubreportProcessingEventArgs)
Select Case e.ReportPath
Case "subreport1"
Dim tbl As DataTable = New DataTable("TableName")
Dim Status As DataColumn = New DataColumn
Status.DataType = System.Type.GetType("System.String")
Status.ColumnName = "Status"
tbl.Columns.Add(Status)
Dim Account As DataColumn = New DataColumn
Account.DataType = System.Type.GetType("System.String")
Account.ColumnName = "Account"
tbl.Columns.Add(Account)
Dim rw As DataRow = tbl.NewRow()
rw("Status") = core.GetStatus
rw("Account") = core.Account
tbl.Rows.Add(rw)
e.DataSources.Add(New ReportDataSource("ReportDatasourceName", tbl))
Case "subreport2"
core.DAL.cnStr = My.Settings.cnStr
core.DAL.LoadSchedule()
e.DataSources.Add(New ReportDataSource("ScheduledTasks", _
My.Forms.Mother.DAL.dsSQLCfg.tSchedule))
Case "subreport3"
core.DAL.cnStr = My.Settings.cnStr
Dim dt As DataTable = core.DAL.GetNodesForDateRange(DateAdd("d", _
-1 * CInt(e.Parameters("NumberOfDays").Values(0)), _
Today), _
Now)
e.DataSources.Add(New ReportDataSource("Summary", dt))
End Select
End Sub