I'm experiencing quite some difficulty getting a subreport to act on the master report's parameters. I'm using the lastest TelerikReporting version 3.0.9.311 (Q1 2009).
I have the following setup: 2 reports, one to act as master (named KeyFigures), one included as sub report (named ChartSubReport).
Both have parameters "CompanyID" defined as Integer with a default value set to 1 (via designer).
The subreport item is set to pass the master report parameter thus: [=Parameters.CompanyID] (also via designer).
I want to pass the companyID from Session to both master report and subreport.
I use NeedDataSource event for both reports to populate the data:
private void Chart_NeedDataSource(object sender, System.EventArgs e) |
{ |
string strCompanyID = this.ReportParameters["CompanyID"].Value.ToString(); |
// The above always gives the default parameter value in the sub report, but correct in the master report |
// ... |
} |
When execution of NeedDataSource events, the master report has the correct value passed from Session. The subreport however keeps the old default value regardless. I have tried to programatically set this value in different ways but no different result.
The Web report viewer is initialized on Page_Load event like this:
Sunscape.TKS.Reports.KeyFigures report = new Sunscape.TKS.Reports.KeyFigures(); |
report.ReportParameters["CompanyID"].Value = Session["intCompany_ID"]; |
Telerik.Reporting.SubReport subReport = report.Items.Find("chartSubReport", true)[0] as Telerik.Reporting.SubReport; |
subReport.Parameters[0].Value = Session["intCompany_ID"]; |
this.ReportViewer.Report = report; |
this shows I even try to programatically set the subreport's CompanyID, but it is not taken into account when NeedDataSource is fired for the SubReport. I know by forcing an exception to be thrown in both NeedDataSource handlers, that the master report's NeedDataSource event is fired first, and the subreport's second.
The above works for the master report which displays the correct data, but the sub report does not. It has the default parameter value of "1" regardless. Why is this?
I have browsed the forums and tried to follow any examples but none I have found address this exact problem. The best suggestion I have found is the above attempt by programmatically set the parameter before loading the report in the viewer.
Since it does not work this way, what is the correct way of forcing the sub report to get the value from the master report?
kind regards,
Ernst Sognnes
8 Answers, 1 is accepted
At runtime, when you read or change some properties of the report item you need to access the Processing instances of the reporting objects (instead of the Definition objects). Same thing is true for the parameters.
What is happening is that the SubReport item is populating the parameter values to the Processing instance of the subreport, and you are trying to read them from the definition.
Please find attached the zip file containing two (master and detail) reports with implemented interconnection between them.
Basically your approach is correct, you just need to change the code "reading" the subreport's parameter value.
You will find this help article really helpful in understanding the difference between definition/processing items and how to use them.
Let us know if you need further assistance.
All the best,
Milen
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
excellent :) just a tiny detail and it all works!
I forgot to mention that my SubReport just had a Chart as the only object and it was the Chart's NeedDataSource event that is used. It seemed I still need to do this in the Page_Load handler containing the web report viewer in order to also make the chart object receive the Session value properly:
// ... KeyFigures report = new KeyFigures(); |
report.ReportParameters["CompanyID"].Value = Session["intCompany_ID"]; |
Telerik.Reporting.SubReport subReport = report.Items.Find("chartSubReport", true)[0] as Telerik.Reporting.SubReport; |
subReport.Parameters[0].Value = Session["intCompany_ID"]; |
this.ReportViewer.Report = report; |
// ... |
And then in the subreport's chart object's NeedDataSource handler:
Telerik.Reporting.Processing.Chart chart = (Telerik.Reporting.Processing.Chart)sender; |
UInt32 uint32CompanyID = (System.UInt32)chart.Report.Parameters["CompanyID"]; |
// ... |
..and everything works perfectly :)
Thanks for your help!
-Ernst
private void DetailReport_NeedDataSource(object sender, EventArgs e)
{
// Here you need to read the parameter value from the Processing instance of the report,
// and that is the only thing you need to change.
Telerik.Reporting.Processing.Report report = (Telerik.Reporting.Processing.Report)sender;
Debug.Assert(5 == (
int)report.Parameters["CompanyID"]);
}
What does Debug.Assert do?
In Ernst's last post below some code is offered for setting the subreport parameter, but this is done from the report viewer. I tried doing something similar from my web page the calls the report, but this doesn't work. Any advice on passing a parameter from one's form to a subreport would really be appreciated, as I cannot seem to achieve what should be a relatively simple task.
I don't think you can render a Telerik Report without the ReportViewer. So in order to create a PDF from a Report, you need the ReportViewer, which have the necessary functions for this already implemented.
Debug.Assert is only used for debugging purposes to get a messagebox on the screen with whatever information you need to see at that point in the execution of the code. See http://msdn.microsoft.com/en-us/library/system.diagnostics.debug.assert.aspx
Passing a parameter to a SubReport within a Report depends on the parameters themselves and how they are set up. In my previous post I had a Chart subreport. This has to be handled accordingly in the subreport's NeedDataSource event handler.
Here's an example for a subreport's NeedDataSource event handler that's not a Chart:
private void Report_NeedDataSource(object sender, System.EventArgs e) |
{ |
Telerik.Reporting.Processing.Report report = (Telerik.Reporting.Processing.Report)sender; |
String strCompanyID = ((System.UInt32)report.Parameters["CompanyID"]).ToString(); |
string strSQL = "SELECT * FROM `some_table` t WHERE t.`intCompany_ID` = " + strCompanyID; |
MySqlDataAdapter mysqlDataAdapter = new MySqlDataAdapter(strSQL, this.strConnection); // Already defined MySQL Connection string |
DataSet dsData = new DataSet(); |
mysqlDataAdapter.Fill(dsData); |
(sender as Telerik.Reporting.Processing.Report).DataSource = dsData; |
} |
As you can see I'm using MySQL, and not MSSQL, but the approach is alsmost identical between the two.
-Ernst
@Ernst: Sure you can render a report without a viewer:
- http://www.telerik.com/support/kb/reporting/designing-reports/saving-a-report-into-pdf-format-programmatically.aspx
- http://www.telerik.com/support/kb/reporting/designing-reports/exporting-a-report-to-pdf-programmatically.aspx
Cheers
I have 2 parameters for my subReport - UserID and ItemID. The subReport is in the details section of my main report and I want to pass the parameter of UserID from the main report into the subReport and also pass the Fields.ItemID of the details section the subReport is in to the subReport.
I am using the NeedDataSource in the subReport to bind the subReport's DataSource to a DataSet.
I used:
Telerik.Reporting.Processing.Report report = (Telerik.Reporting.Processing.Report)sender;
...
(
int
)report.Parameters[
"UserID"
].Value
to get the UserID from the main report.... but when passing the Fields.ItemID into the subReport I am getting the default value (-1)
That works, thanks! We recently upgraded TR from Q2 2009 to Q3 2011 and ran into this issue with the new reports. What I don't understand, is why the way we were doing this in old reports still works. Here's a snippet of what I'm talking about:
void
omLabor_NeedDataSource(
object
sender, EventArgs e)
{
try
{
if
(
this
.dataSource ==
null
)
{
bool
clearingAccounts = Convert.ToBoolean(
this
.ReportParameters[
"clearing_accounts"
].Value);
string
glAcctCodeFilter = (clearingAccounts ==
false
?
" AND gl_acct_code NOT IN ('900','901','970') "
:
string
.Empty);
string
connectionString = ReportUtilities.ConnectionString;