Search code examples
c#telerik-reporting

How to have a subreport with a table that has a dynamic amount of columns in Telerik reporting


I have a Report that is made with Telerik reporting. This report displays information for all given weekdays in a month (e.g. All Mondays in July 2017) in a table. The columns of the table are the days, the rows are the data associated with the dates.

The amount of times a certain day falls inside a month varies, so I need to have the ability to define the amount of columns the table needs to have based on the requested data. How would I do this?

Here a mock of how it should be displayed:

enter image description here


Solution

  • Considering the reportnames are MainReport and SubReport:

    In the MainReport add the following code:

    public static ReportSource SetReportSourceForSubreport(object data)
    {
        var report = new SubReport(data);
        var repSource = new InstanceReportSource
        {
            ReportDocument = report
        };
    
        return repSource;
    }
    

    Now add a subreport to the main report via the Visual Studio Report Designer and set the ReportSource to = MyNameSpace.MainReport.SetReportSourceForSubreport(Fields.Data). Make sure that Data is available in the datasource of the main report.

    In your SubReport you will now need a constructor that accepts the data. First call the InitializeComponent() method, and then generate your table by code, adding the amount of columns and rows needed.

    public SubReport(object data)
    {
        InitializeComponent();
    
        // Create and add table to report body
        var table = CreateTable(data);
        this.detail.Items.Add(table);
    }
    

    On how the generate a table by code, read the following page and associated articles for a detailed explanation. https://docs.telerik.com/reporting/table-understanding-cells-rows-columns

    A small example on how to generate a table with code:

    private Table CreateTable(Dictionary<string, IEnumerable<string>> data)
    {
        ////
        // New table instance
        ////
        _requiredColumns = data.Count + 1;
        Table table = new Table()
        {
            Name = "tableDay",
            Docking = DockingStyle.Fill,
            Location = new PointU(Unit.Cm(0D), Unit.Cm(0D)),
            Size = new SizeU(Unit.Cm(17D), Unit.Cm(5D)),
            RowHeadersPrintOnEveryPage = true
        };
    
        table.Bindings.Add(new Telerik.Reporting.Binding("DataSource", "= Fields.Rows"));
    
        for (int i = 0; i < _requiredColumns; i++)
        {
            table.Body.Columns.Add(new TableBodyColumn(Unit.Cm(_columnWidth)));
        }
    
        ////
        // Add headers
        ////
        table.ColumnGroups.Add(new TableGroup
        {
            Name = "columnLeftMost",
            ReportItem = new TextBox { Name = "textBoxHours", Value = "Hours" }
        });
    
        foreach (var item in data)
        {
            table.ColumnGroups.Add(new TableGroup
            {
                Name = "column" + item.Key,
                ReportItem = new TextBox { Name = "textBoxTitleDay" + item.Key, Value = item.Key }
            });
        }
    
        ////
        // Add data rows
        ////
    
        var tableGroup28 = new TableGroup() { Name = "tableGroup280" };
        tableGroup28.Groupings.Add(new Telerik.Reporting.Grouping(null));
        table.RowGroups.Add(tableGroup28);
    
        table.Body.Rows.Add(new TableBodyRow(Unit.Cm(ROWHEIGHT)));
    
        List<ReportItemBase> list = new List<ReportItemBase>();
    
        for (int i = 0; i < _requiredColumns; i++)
        {
            var tb = new TextBox
            {
                Name = "textBox" + i,
                Value = i == 0 ? "= Fields.DayTimeFriendly" : "= Fields.RowValues"
            };
    
            list.Add(tb);
            table.Body.SetCellContent(0, i, tb);
        }
    
        table.Items.AddRange(list.ToArray());
    
        return table;
    }