ReportViewer with nested tables

Sometimes you may need a report that can not be done easily with standard grouping in a table.  Say you want to a repeatable data region that is repeated by an outer group, but contains two other tables an maybe an image.  I can’t think of a good way to do that with standard row grouping using a tablix.  However, the List control makes this easy.  In short, here is what is needed.  A List control that contains all other elements and is grouped by some value.  The List gets repeated for each unique group value.  Put two Tables in the List and toss in any other controls you need such as Textboxes or Images.

Here is the controls layed out in Visual Studio report designer:

image

 

We get our data from the database using anything such as Linq or other.  However, we "flatten" it because reports do not understand nested data.

We can make developing the report simplier by skipping the DB step and making our own objects like:

public class Offers
{
    public string OfferID { get; set; }
    public string Offerer { get; set; }
    public bool IsProgram { get; set; }
    public string ProgramName { get; set; }
    public int ProgramHours { get; set; }
    public bool IsPrereq { get; set; }
    public string PrereqName { get; set; }
    public int PrereqCode { get; set; }
    public byte[] Image { get; set; } 

    public static List<Offers> GetData()
    {
        byte[] im = File.ReadAllBytes(@"C:\Users\William\Pictures\MarkTwain.jpg");
        byte[] im2 = File.ReadAllBytes(@"c:\users\william\pictures\captain_john_smith.jpg"); 

        // Offer1
        Offers of1 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="admission", ProgramHours=1};
        of1.Image = im2;
        Offers of2 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="actual crisis", ProgramHours=10};
        of2.Image = im2;
        Offers of3 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="discussion", ProgramHours=5};
        of3.Image = im2;
        Offers of4 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="final notes", ProgramHours=2};
        of4.Image = im2; 

        Offers of5 = new Offers(){ OfferID="03453", Offerer="John Smith", IsPrereq=true, PrereqName="Macro econ II", PrereqCode=3463};
        of5.Image = im2;
        Offers of6 = new Offers(){ OfferID="03453", Offerer="John Smith", IsPrereq=true, PrereqName="Finance", PrereqCode=34634};
        of6.Image = im2;
        List<Offers> offers = new List<Offers>() {of1, of2, of3, of4, of5, of6}; 

        // Offer2
        of1 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="admission2", ProgramHours=2};
        of1.Image = im;
        of2 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="actual crisis2", ProgramHours=3};
        of2.Image = im;
        of3 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="discussion2", ProgramHours=4};
        of3.Image = im;
        of4 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="final notes2", ProgramHours=7};
        of4.Image = im; 

        of5 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsPrereq=true, PrereqName="Macro econ II2", PrereqCode=3466};
        of5.Image = im;
        of6 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsPrereq=true, PrereqName="Finance2", PrereqCode=34638};
        of6.Image = im;
        List<Offers> offers2 = new List<Offers>(){of1, of2, of3, of4, of5, of6};
        offers.AddRange(offers2);
        return offers;
    }
}

 

Now in the Report load event of your report Form do something like:

private void Offers_Load(object sender, EventArgs e)
{
    var list = Offers.GetData();
    this.OffersBindingSource.DataSource = list;
    this.reportViewer1.LocalReport.EnableExternalImages = true;
    this.reportViewer1.RefreshReport();
}

 

Now you have a report that has grouped "regions" and inside each region can contain other lists and/or other elements related to the group.

Output:

image

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

7 Responses to ReportViewer with nested tables

  1. Luca says:

    You saved my life 🙂

  2. Unknown says:

    hithanks for the gr8 post. i cant figure out what this "OffersBindingSource" is <%@ Page Language="VB" CodeFile="try.aspx.vb" Inherits="Reports_try" %><%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %><html><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <rsweb:ReportViewer ID="ReportViewer1" runat="server"> <LocalReport ReportPath="Report1.rdlc"> <DataSources> <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="MainBaseDataSet_viwPersons" /> </DataSources> </LocalReport> </rsweb:ReportViewer> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetData" TypeName="MainBaseDataSetTableAdapters.viwPersonsTableAdapter"></asp:ObjectDataSource> </div> </form></body></html>i cannot find any datasource object, except for the datasources collection of the report. is that what u mean? cant seem to set it via codei have a linq object that im trying to hook up to a report. coud be microsft or crystal. both seem very powerful, just wanna get started with this. thanks

Comments are closed.