Tuesday 24 February 2015

Sub Report in RDLC Report viewer

In this article I am going explain about sub report control of RDLC and how can we use sub report in RDLC and report viewer by taking a real life example in an asp.net application.

I have taken an example of Orders and its Line items. Our report will something look like this:

 

In order to achieve above screenshot in a browser, you can follow the steps given below:

1)      Open Microsoft Visual Studio

2)      Select Asp.Net Empty Web Application.

3)      Add a new item (Report.aspx)

4)      Drag and Drop ReportViewer control and ScriptManager from the toolbox.

<form id="form1" runat="server">

    <div>

        <asp:ScriptManager ID="ScriptManager1" runat="server">

        </asp:ScriptManager>

        <rsweb:ReportViewer ID="rptViewer" runat="server" Width="100%" Height="600px" Font-Names="Verdana"

            Font-Size="8pt" InteractiveDeviceInfos="(Collection)" WaitMessageFont-Names="Verdana"

            WaitMessageFont-Size="14pt">

        </rsweb:ReportViewer>

    </div>

</form>

 

Add the following Object and Business class in order to specify the data for reportviewer:

1)      Order.cs

 

public class Order

    {

        public long OrderNo { get; set; }

        public DateTime OrderDate { get; set; }

        public string Customer { get; set; }

 

        public List<OrderLine> Lines { get; set; }

    }

 

2)      OrderLine.cs

public class OrderLine

    {

        public long OrderNo { get; set; }

        public int LineNo { get; set; }

        public string Product { get; set; }

        public float UnitPrice { get; set; }

        public int Quantity { get; set; }

        public float VAT { get; set; }

        public float Discount { get; set; }

        public float Total { get; set; }

    }

 

3)      BLL.cs

public class BLL

    {

        public static List<Order> GetOrders()

        {

            return new List<Order>

                        {

                            new Order { OrderNo = 1, OrderDate = DateTime.Now.AddYears(-3), Customer = "A", Lines = new List<OrderLine>

                                        {

                                            new OrderLine { LineNo = 1, Product = "A", UnitPrice = 200, Quantity = 4, VAT = 10, Discount = 2, Total = (200*4) + (200*4*10/100) - (200*4*2/100) },

                                            new OrderLine { LineNo = 2, Product = "B", UnitPrice = 250, Quantity = 4, VAT = 5, Discount = 1, Total = (250*4) + (250*5*10/100) - (250*4*1/100) },

                                        } },

                            new Order { OrderNo = 2, OrderDate = DateTime.Now.AddYears(-2), Customer = "B", Lines = new List<OrderLine>

                                        {

                                            new OrderLine { LineNo = 1, Product = "A", UnitPrice = 200, Quantity = 4, VAT = 10, Discount = 2, Total = (200*4) + (200*4*10/100) - (200*4*2/100) },

                                            new OrderLine { LineNo = 2, Product = "B", UnitPrice = 250, Quantity = 4, VAT = 5, Discount = 1, Total = (250*4) + (250*5*10/100) - (250*4*1/100) },

                                        } },

                            new Order { OrderNo = 3, OrderDate = DateTime.Now.AddYears(-1), Customer = "C", Lines = new List<OrderLine>

                                        {

                                            new OrderLine { LineNo = 1, Product = "A", UnitPrice = 200, Quantity = 4, VAT = 10, Discount = 2, Total = (200*4) + (200*4*10/100) - (200*4*2/100) },

                                            new OrderLine { LineNo = 2, Product = "B", UnitPrice = 250, Quantity = 4, VAT = 5, Discount = 1, Total = (250*4) + (250*5*10/100) - (250*4*1/100) },

                                        } },

                        };

        }

    }

 

Create a Report folder in the root directory of your application and add two report (.rdlc) files in the same folder Report.rdlc and Report1.rdlc

Also add a Dataset in Report folder and create these two DataTable in the same dataset.

1)      Order (OrderNo: Int64, OrderDate: DateTime, Customer: String)

2)      Line (OrderNo: Int64, LineNo: Int32, Product: String, UnitPrice: Double, Quantity: Int32, VAT: Double, Discount: Double, Total: Double)

Configure Report.rdlc

1)      Now add an Order DataTable in Report.rdlc file and also drag and drop Table control from Toolbox and set the columns of DataTable in Table columns.

2)      Remove the header row from the table control.

3)      Add a parameter Total of type float in the Parameters folder.

4)      Drag and Drop Textbox control and set the Total parameter in the textbox.

5)      Right click on Table row and select Insert Row à select Inside Group – Below.

6)      Select all the columns of added row and right click and choose Merge Cells option.

7)      Now Drag and Drop Subreport control from toolbox in this row.

8)      Set the properties of Subreport.  

a.       ReportName: Report1

b.       Name: LineInfo

c.        Hidden: True

d.       ToggleItem: OrderNo

9)      Right Click on Subreport and add a parameter (OrderNo) to display the OrderNo wise LineInfo.

 

I also highlighted the configured part in the above screenshot for your reference. Please make sure all the steps should be properly configured.

 

Configure Report1.rdlc

1)      Now add a Line DataTable in Report1.rdlc file and also drag and drop Table control from Toolbox and set the columns of DataTable in Table columns.

2)      Select Row of the Table  à Select Details from Row Groups give at the bottom of the page àChoose Add Total option à Choose After.

3)      Remove all sum columns except Sum(Total) and merge all the cells in this row.

Our configuration part is completed now. Now we will move towards our server side code where we dynamically set the data in reportviewer control and its subreport.

Open Report.aspx.cs and add the following two functions:

1)      Page_Load

protected void Page_Load(object sender, EventArgs e)

        {

            if (!Page.IsPostBack)

            {

                string path = Path.Combine(Server.MapPath("~/Report"), "Report.rdlc");

                rptViewer.LocalReport.ReportPath = path;

 

                var cm = BLL.GetOrders();

 

                ReportParameter [] param = new ReportParameter[1];

                param[0] = new ReportParameter("Total", cm.Sum(m => m.Lines.Sum(x => x.Total)).ToString(), true);

 

                rptViewer.LocalReport.SetParameters(param);

 

                rptViewer.LocalReport.DataSources.Clear();

                ReportDataSource rd = new ReportDataSource("MyDataset", cm);

                rptViewer.LocalReport.DataSources.Add(rd);

                rptViewer.LocalReport.Refresh();

 

                rptViewer.LocalReport.SubreportProcessing +=

                    new Microsoft.Reporting.WebForms.SubreportProcessingEventHandler(LocalReport_SubreportProcessing);

            }

        }

 

 

2)      LocalReport_SubreportProcessing

 

void LocalReport_SubreportProcessing(

            object sender,

            Microsoft.Reporting.WebForms.SubreportProcessingEventArgs e)

        {

            // get empID from the parameters

            int iOrderNo = Convert.ToInt32(e.Parameters[0].Values[0]);

 

            // remove all previously attached Datasources, since we want to attach a

            // new one

            e.DataSources.Clear();

 

            // Retrieve employeeFamily list based on EmpID

            var lines = BLL.GetOrders().Single(m => m.OrderNo == iOrderNo).Lines;

 

            // add retrieved dataset or you can call it list to data source

            e.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource()

            {

                Name = "LineDS",

                Value = lines

            });

        }

 

 

Now all we set to see the output in browser window. Run an application and browse Report.aspx. I hope the output should be fine and we can the list orders and line items y expanding the rows.

 

Thanks for reading this article. I think this will helps a lot. You can ask any question and can also provide feedback for this article by using the comment box given below.

In order to see reportviewer basic you can visit this article Using ReportViewer in WinForms C#

 

4 comments:

VJ said...

How to avoid the space between the elements in the main report.

cjw said...

Remember to add your parameter on your subreport as well

Unknown said...

Hi i just followed the same steps which u have mentioned in the post and i am getting Error: Subreport could not be shown.
and LocalReport_SubreportProcessing in not getting executed


I know the issue is with the parameter to subreport becasue once i remove parameter for subreport. LocalReport_SubreportProcessing is getting executed

So can u please suggest what can be done.. Thanks in Advance

Sajjad Abdullah said...

I have created sub report successfully. It is working fine. However, I want to add an "Expand All" / "Collapse All" function to the main report. When the user clicks on the "Expand All" button, all the records of the main report should be expanded and so on.
Can you please help me in this regard????