This is a migrated thread and some comments may be shown as answers.

Working with SubReports programmatically

6 Answers 1153 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Adam
Top achievements
Rank 1
Adam asked on 14 Apr 2013, 06:10 AM
Hi,

I'm using the ReportProcessor class in order to export reports in an HTML format progmmatically.  I have a couple of questions; I'm about at wit's end, here.

I have a report which contains a sub report.  Each of these reports is encapsulated in a TRDX file.  I create an instance of the main report (let's call it MainReport), which is of type Telerik.Reporting.Report.  I get a reference to MainReport's DataSource property, which is a SqlDataSource, and I set the ConnectionString property to a connection string in my app.config file.  I then instantiate an InstanceReportSource and set the ReportDocument property to my MainReport object.  At this point, I can render the main report via the ReportProcessor.RenderReport method.  All is well and good so far.

My problem is with the sub report.  What do I need to do to include it?  I've looked at the limited amount of documentation over and over but I simply cannot wrap my head around what I need to do.  Here's what almost works:

I create an instance of the sub report the same way I'm instantiating MainReport (we'll call it SubReport).  I then Find() the sub report item within MainReport's Items collection, and after grabbing that reference, I set its ReportSource property to my SubReport instance.

Here's the problem with that:  Apparently this way of doing things is obsolete.  I need to know how to do it correctly.  Also, I need SubReport.DataSource.ConnectionString to be the same as MainReport.DataSource.ConnectionString.  Additionally, there is a Crosstab item within the main report that apparently also needs a ConnectionString, even though the DataSource is the same as MainReport's DataSource.

Here's some code snippets:

//MainReport instantiation  (some code is hidden, but you should get the idea
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.IgnoreWhitespace = true;
ReportXmlSerializer serializer = new ReportXmlSerializer();
XmlReader primaryReportXmlReader = XmlReader.Create(reportDefinition.PrimaryReport.TemplateLocation, xmlReaderSettings);
_primaryReport = (Telerik.Reporting.Report)serializer.Deserialize(primaryReportXmlReader);
primaryReportXmlReader.Close();
             
SqlDataSource reportDataSource = (SqlDataSource)_primaryReport.DataSource;
reportDataSource.ConnectionString = reportDefinition.ConnectionString;
this._instanceReportSource.ReportDocument = _primaryReport;

//We're using a custom class to define a "report definition", which contains data about sub reports,
//so I'm looping through each sub report definition and instantiating it.
foreach (CPSReport cpsSubReport in reportDefinition.SubReports)
{
    XmlReader xmlReader = XmlReader.Create(cpsSubReport.TemplateLocation, xmlReaderSettings);
    Telerik.Reporting.Report subReportInstance = (Telerik.Reporting.Report)serializer.Deserialize(xmlReader);
    xmlReader.Close();
 
    SqlDataSource subReportDataSource = (SqlDataSource)subReportInstance.DataSource;
    subReportDataSource.ConnectionString = reportDefinition.ConnectionString;  //would be handy to automatically get from the main report
    //The following line is hardcoded for now because i've been experimenting.  The string "subReport1" would actually be defined in our custom report definition class.
    Telerik.Reporting.SubReport subReport = _primaryReport.Items.Find("subReport1", true).FirstOrDefault() as Telerik.Reporting.SubReport;
    subReport.ReportSource = subReportInstance;  //obsolete.  what's the right way to do this?
}

Also, as I mentioned, in the rendered report, I get an error about the Crosstab connection string:

An error has occurred while processing Table 'crosstab2': Unable to establish a connection to the database. Please, verify that your connection string is valid. In case you use a named connection string from the application configuration file, make sure the name is correct and the connection string settings are present in the configuration file of your application. ------------- InnerException ------------- Format of the initialization string does not conform to specification starting at index 0.

Please help?  :)

Thanks!

6 Answers, 1 is accepted

Sort by
0
Chavdar
Telerik team
answered on 18 Apr 2013, 09:15 AM
Hello,

The report source for the SubReport item should be again set via an InstanceReportSource as you do this for the main report. For example:

Telerik.Reporting.InstanceReportSource instanceReportSource = new Telerik.Reporting.InstanceReportSource();
instanceReportSource.ReportDocument = subReportInstance;
subReport.ReportSource = instanceReportSource;

The Report and the Crosstab item are different data items and as such they have different data sources. In your case you have to update the connection string for the CrossTab item as well.

Here is a sample code snippet which iterates through all data items in the report and updates their connection string:

foreach (Telerik.Reporting.DataItem dataItem in report.Items.Find(typeof(Telerik.Reporting.DataItem), true))
{
    Telerik.Reporting.SqlDataSource sqlDataSource = (Telerik.Reporting.SqlDataSource)dataItem.DataSource;
    sqlDataSource.ConnectionString = "...";
}

Still, the best approach is to use named connection strings and specify them through the config file of the application.

All the best,
Chavdar
the Telerik team

Have you tried the new visualization options in Telerik Reporting Q1 2013? You can get them from your account.

0
Adam
Top achievements
Rank 1
answered on 18 Apr 2013, 01:56 PM
Got it.  Thank you!!  I guess reading the other dozen examples just wasn't enough.. I needed one more to make it click!  Heh..
0
Michael Landy
Top achievements
Rank 1
answered on 09 May 2013, 10:06 PM
I have the same situation.  In my case I have a main report with 2 sub reports.  I am using the processing engine to generate a PDF file.  I am now getting a PDF file with both subreports displayed.  However, the data displayed on the subreports is incorrect.  It is as if the data is not being sent to the report instance as the report is generated.

The subreports share two parameters with the main report and a third parameter comes from the data in the main report.  I would have thought that my subreport would have been passed the data without my help.  It does not appear to be that way.

I am so close...what am I missing?
0
Adam
Top achievements
Rank 1
answered on 10 May 2013, 04:23 PM
Michael, I'm assuming the preview of your report in the designer is correct, in that the subreports are displaying the right data. Have you tried setting the shared parameters for each of your reports (the main report and the subreports)?
0
Michael Landy
Top achievements
Rank 1
answered on 10 May 2013, 04:34 PM
I figured out the issue.  The documentation is very poor surrounding the XML version of reports.  Here is what I have working and figured out from the various forums.

If you want to dynamically load reports that may contain subreports, you need to do the following:

1. Deserialize the main report
2. Search the main report for any SubReport items
3. For each SubReport, deserialize those reports
4. Copy the parameter settings for the subreport
5. Change the DB String of the subreport
6. Create an InstanceReportSource for the subreport
7. Set the main report subreport item to have a report source of the instance you just created
8. Reapply all of the report parameters saved off in step 4

Step 4 and 8 were missing.  After stepping through the code, I found that by attaching the subreport to the main report, the report parameters were being cleared.  So, by resetting them, everything began to work.
0
Steve
Top achievements
Rank 1
answered on 22 Jan 2014, 03:04 AM
I have some of the items figured out (I think) but cannot figure out how to do steps 7 and 8.

Here is what I have. Again, not sure it's correct.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            Dim crypto As Encryption.Crypto = New Encryption.Crypto("mystring")
            Dim conn As String = crypto.Decrypt(ConfigurationManager.ConnectionStrings("POS").ConnectionString)
 
            Dim report1 As Telerik.Reporting.Report = DeserializeReport(Server.MapPath("/Reports/Invoice.trdx"))
            TryCast(report1.DataSource, SqlDataSource).ConnectionString = conn
 
            Dim subreporta As Telerik.Reporting.SubReport = DirectCast(report1.Items.Find("subReport1", True)(0), SubReport)
            Dim instanceRS As Telerik.Reporting.UriReportSource = DirectCast(subreporta.ReportSource, UriReportSource)
            Dim uri As String = instanceRS.Uri
            Dim subparam As Telerik.Reporting.ParameterCollection = instanceRS.Parameters
 
            Dim subreport1 As Telerik.Reporting.Report = DeserializeReport(Server.MapPath("/Reports/" + uri))
            TryCast(subreport1.DataSource, SqlDataSource).ConnectionString = conn
 
            Dim irs As Telerik.Reporting.InstanceReportSource
 
            Dim srSource As Telerik.Reporting.InstanceReportSource
            srSource.ReportDocument = subreport1
    End if
End Sub
 
 Private Function DeserializeReport(ByVal ReportPath As String) As Telerik.Reporting.Report
        Dim settings As New XmlReaderSettings()
        settings.IgnoreWhitespace = True
        Using xmlReader__1 As XmlReader = XmlReader.Create(ReportPath, settings)
            Dim xmlSerializer As New Telerik.Reporting.XmlSerialization.ReportXmlSerializer()
            Return DirectCast(xmlSerializer.Deserialize(xmlReader__1), Telerik.Reporting.Report)
        End Using
 
    End Function

Anyone able to lend a hand on this, and correct any code that is wrong?

Thanks!
Tags
General Discussions
Asked by
Adam
Top achievements
Rank 1
Answers by
Chavdar
Telerik team
Adam
Top achievements
Rank 1
Michael Landy
Top achievements
Rank 1
Steve
Top achievements
Rank 1
Share this question
or