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

"NullReferenceException" when trying to dynamically generate rows

1 Answer 30 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Barry
Top achievements
Rank 1
Barry asked on 18 Jul 2017, 06:42 PM

Hello,

I have been having a problem trying to generate a report programatically. I can generate columns just fine, but when it comes to trying to generate the rows, the ReportViewer gives me a NullReferenceException: "Object reference not set to an instance of an object." As I iterate through my list, I add a new row to the table body. Then, for every cell that needs to be made, I add a ChildGroup to the main Rowgroup. After I've finished iterating and generating everything, I finally add the parent RowGroup. From what I can tell, the way I add rows is close to the way it's done in the designer files. Here is the code in question:

 

private void table1_ItemDataBinding(object sender, EventArgs e)
{
    HtmlTextBox textboxGroup;
    var christieTable = new ChristieTable(ReportParameters["partNumber"].Value.ToString(),
                                          ReportParameters["lotNumber"].Value.ToString());
    var christieProps = typeof(ChristieTable).GetProperties();
 
    table1.ColumnGroups.Clear();
    table1.RowGroups.Clear();
    table1.Body.Columns.Clear();
    table1.Body.Rows.Clear();
    TableGroup rowsTableGroup = new TableGroup();
    List<ReportItemBase> reportItems = new List<ReportItemBase>();
 
    //start at -1 so we can account for the mold # column but retain the ability to index using i
    for (int columnIndex = -1; columnIndex < christieProps.Length - 1; columnIndex++)
    {
        var propValue = (columnIndex != -1) ? (List<Tuple<double, int>>) christieProps[columnIndex].GetValue(christieTable) : null;
        //make sure our column property is populated
        if (propValue != null && propValue.Count > 0)
        {
            var columnsPerStation = 1;
            var currentDip = propValue[0].Item2;
            foreach (var measurePair in propValue)
            {
                if (measurePair.Item2 != currentDip)
                {
                    columnsPerStation++;
                    currentDip = measurePair.Item2;
                }
            }
 
            var tableGroupColumn = new TableGroup();
            table1.ColumnGroups.Add(tableGroupColumn);
            //if tableGroupColumn isn't given a name, all cells will have the same value as cell 0,0
            tableGroupColumn.Name = columnIndex.ToString();
            table1.Body.Columns.Add(new TableBodyColumn(Unit.Inch(1)));
 
            for (int a = 0; a < columnsPerStation; a++)
            {
                textboxGroup = ReportHelper.GenStandardColumnHeader(christieTable.StationNames[columnIndex] + " - DIP NUMBER " + propValue[0].Item2);
                tableGroupColumn.ReportItem = textboxGroup;
                reportItems.Add(textboxGroup);
            }
 
            var value = (List<Tuple<double, int>>) christieProps[columnIndex].GetValue(christieTable, null);
            table1.Body.Rows.Add(new TableBodyRow(Unit.Inch(0.24998027086257935D)));
            for (int rowIndex = 0; rowIndex < 5; rowIndex++)
            {
                TableGroup newRowSubGroup = new TableGroup();
                newRowSubGroup.Name = "row" + (columnIndex + rowIndex + 1).ToString();
                rowsTableGroup.ChildGroups.Add(newRowSubGroup);
                HtmlTextBox newTextBoxTable = ReportHelper.GenTextBox(value[rowIndex].Item1.ToString());
                table1.Body.SetCellContent(rowIndex, columnIndex + 1, newTextBoxTable);
                reportItems.Add(newTextBoxTable);
            }
        }
        else if (propValue == null)
        {
            var tableGroupColumn = new TableGroup();
            table1.ColumnGroups.Add(tableGroupColumn);
            tableGroupColumn.Name = columnIndex.ToString();
            table1.Body.Columns.Add(new TableBodyColumn(Unit.Inch(1)));
 
            textboxGroup = ReportHelper.GenStandardColumnHeader("MOLD #");
            tableGroupColumn.ReportItem = textboxGroup;
            reportItems.Add(textboxGroup);
 
            HtmlTextBox textBoxTable = ReportHelper.GenTextBox("= RowNumber()");
            table1.Body.SetCellContent(0, columnIndex + 1, textBoxTable);
            reportItems.Add(textBoxTable);
        }
    }
    rowsTableGroup.Name = "rowsGroup";
    rowsTableGroup.Groupings.Add(new Grouping(null));
    table1.RowGroups.Add(rowsTableGroup);
 
    table1.Items.AddRange(reportItems.ToArray());
}

 

The GenStandardColumnHeader and GenTextBox methods simply return pre-formatted textboxes, their first parameter being the value of the textbox. The properties of the object ChristieTable that I am iterating through are DataMembers consisting of a list of pairs. Using the debugger, I found that the report processes fine, but throws the exception when trying to render. Despite the fact that rows get clearly added, I found in the debugger that the row count for the table at render time is 0. Any help would be appreciated, thanks.

1 Answer, 1 is accepted

Sort by
0
Stef
Telerik team
answered on 21 Jul 2017, 02:31 PM
Hi Barry,

The recommended approach is to create a sample report with test data via VS Report Designer and to reuse the code from the report's Designer.cs|vb file.

Example:
public DataTable GetData()
{
    dynamic table = new DataTable();
    table.Columns.Add("col1", typeof(int));
    table.Columns.Add("col2", typeof(int));
 
    table.Rows.Add(1, 3);
    table.Rows.Add(4, 6);
    table.Rows.Add(2, 5);
    table.Rows.Add(4, 7);
 
 
    return table;
}
 
public Telerik.Reporting.Report GenerateReport()
{
 
    //create a blank report
    Telerik.Reporting.Report report = new Telerik.Reporting.Report();
    report.Name = "Report1";
    report.PageSettings.Margins = new Telerik.Reporting.Drawing.MarginsU(Telerik.Reporting.Drawing.Unit.Inch(1.0), Telerik.Reporting.Drawing.Unit.Inch(1.0), Telerik.Reporting.Drawing.Unit.Inch(1.0), Telerik.Reporting.Drawing.Unit.Inch(1.0));
    report.PageSettings.PaperKind = System.Drawing.Printing.PaperKind.Letter;
    report.Width = Telerik.Reporting.Drawing.Unit.Inch(6.0);
 
    //create a detail section and add it to the report instance's Items collection
    Telerik.Reporting.DetailSection detailSection = new Telerik.Reporting.DetailSection();
    detailSection.Height = Telerik.Reporting.Drawing.Unit.Inch(1);
 
    detailSection.Name = "DetailSection";
    report.Items.AddRange(new Telerik.Reporting.ReportItemBase[] { detailSection });
 
    //create a blank Table item
    Telerik.Reporting.Table table1 = new Telerik.Reporting.Table();
    table1.Location = new Telerik.Reporting.Drawing.PointU(Telerik.Reporting.Drawing.Unit.Inch(0.0), Telerik.Reporting.Drawing.Unit.Inch(0.0));
    table1.Name = "Table1";
    table1.Size = new Telerik.Reporting.Drawing.SizeU(Telerik.Reporting.Drawing.Unit.Inch(4), Telerik.Reporting.Drawing.Unit.Inch(1));
 
 
    //get the data for the table
    dynamic data = GetData();
    table1.DataSource = data;
 
    //create a dynamic row group
    Telerik.Reporting.TableGroup DetailRowGroup = new Telerik.Reporting.TableGroup();
    DetailRowGroup.Groupings.Add(new Telerik.Reporting.Grouping(null));
    DetailRowGroup.Name = "DetailRowGroup";
    table1.RowGroups.Add(DetailRowGroup);
    //add a row container
    table1.Body.Rows.Add(new Telerik.Reporting.TableBodyRow(Telerik.Reporting.Drawing.Unit.Inch(0.5)));
 
 
    //add columns
    for (int i = 0; i <= data.Columns.Count - 1; i++)
    {
        //add a column container
        table1.Body.Columns.Add(new Telerik.Reporting.TableBodyColumn(Telerik.Reporting.Drawing.Unit.Inch(2)));
        //add a static column group per data field
        Telerik.Reporting.TableGroup columnGroup = new Telerik.Reporting.TableGroup();
        table1.ColumnGroups.Add(columnGroup);
 
        //header textbox
        Telerik.Reporting.TextBox headerTextBox = new Telerik.Reporting.TextBox();
        headerTextBox.Name = "headerTextBox" + i.ToString();
        headerTextBox.Size = new Telerik.Reporting.Drawing.SizeU(Telerik.Reporting.Drawing.Unit.Inch(2), Telerik.Reporting.Drawing.Unit.Inch(0.5));
        headerTextBox.Value = data.Columns[i].ColumnName;
        headerTextBox.Style.BackgroundColor = Color.Yellow;
        headerTextBox.Style.BorderStyle.Default = Telerik.Reporting.Drawing.BorderType.Solid;
      //  headerTextBox.Style.BorderWidth.Default = Telerik.Reporting.Drawing.Unit.Pixel(1);
        columnGroup.ReportItem = headerTextBox;
 
        //field that will be displayed
        Telerik.Reporting.TextBox detailRowTextBox = new Telerik.Reporting.TextBox();
        detailRowTextBox.Name = "detailRowTextBox" + i.ToString();
        detailRowTextBox.Size = new Telerik.Reporting.Drawing.SizeU(Telerik.Reporting.Drawing.Unit.Inch(2), Telerik.Reporting.Drawing.Unit.Inch(0.5));
        detailRowTextBox.Value = "= Fields.[" + data.Columns[i].ColumnName + "]";
        table1.Body.SetCellContent(0, i, detailRowTextBox);
 
        //add the nested items in the Table.Items collection
        table1.Items.AddRange(new Telerik.Reporting.ReportItemBase[] {
    headerTextBox,
    detailRowTextBox
});
 
    }
 
    //add total group - static group out of the detail row group
    table1.Body.Rows.Add(new Telerik.Reporting.TableBodyRow(Telerik.Reporting.Drawing.Unit.Inch(0.5)));
    Telerik.Reporting.TableGroup totalRowGroup = new Telerik.Reporting.TableGroup();
    totalRowGroup.Name = "totalRowGroup";
    table1.RowGroups.Add(totalRowGroup);
    for (int i = 0; i <= data.Columns.Count - 1; i++)
    {
        Telerik.Reporting.TextBox totalRowTextBox = new Telerik.Reporting.TextBox();
        totalRowTextBox.Name = "detailRowTextBox" + i.ToString();
        totalRowTextBox.Size = new Telerik.Reporting.Drawing.SizeU(Telerik.Reporting.Drawing.Unit.Inch(2), Telerik.Reporting.Drawing.Unit.Inch(0.5));
        totalRowTextBox.Value = "='Total:'+ Sum(Fields.[" + data.Columns[i].ColumnName + "])";
 
        totalRowTextBox.Style.BackgroundColor = Color.Azure;
        table1.Body.SetCellContent(1, i, totalRowTextBox);
    }
 
 
    //add the table in the detail section's Items collection
    detailSection.Items.AddRange(new Telerik.Reporting.ReportItemBase[] { table1 });
 
 
    return report;
}


You can serialize the final code into a TRDX file to verify the generated structure via Standalone Report Designer. And to determine what should be edited in code.


I hope this helps.

Regards,
Stef
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
General Discussions
Asked by
Barry
Top achievements
Rank 1
Answers by
Stef
Telerik team
Share this question
or