How to Create a Report that Displays Hierarchical Nested Data
Environment
Product | Progress® Telerik® Reporting |
Description
The requirement is to represent hierarchical data with an unknown number of hierarchical levels in a report recursively. The data consists of nested collections. For example here is a sample JSON data:
[{
"Name":"Grand Parent 1",
"List":[{
"Name":"Parent 1-1",
"List":[{
"Name":"Child 1-1-1"},{
"Name":"Child 1-1-2"},...]
},...]
},{
"Name":"Grand Parent 2",
"List":[{
"Name":"Parent 2-1",
"List":[{
"Name":"Child 2-1-1"},...]
},
{
"Name":"Parent 2-2",
"List":[{
"Name":"Child 2-2-1"},{
"Name":"Child 2-2-2",
"List":[{
"Name":"Grand Child 2-2-2-1"},...]
},...]
},...]
},...]
Solution 1
We use one report that references itself through a SubReport item. The DataSource of each subreport is set to the collection field (the field "List" in the above JSON) from the parent Report DataSource. This way, the report structure will be reproduced hierarchically based on the data, and the bottom of the recursion will be hit when the collection fields are no longer available. The solution is demonstrted in the HierarchyFromNestedCollections.trdp demo report. Next I have outlined the main points when designing the report. The report has a DataSource assigned as a property - the JsonDataSource with hierarchical nested data collection, and a DataSource assigned with Bindings through the following Expression:
Property path | Expression
DataSource | = ReportItem.Parent is Null ? ReportItem.DataSource : ReportItem.Parent.DataObject.List
This way, if the Report doesn't have a parent, like the root report of the hierarchy representation, the default DataSource will be the JsonDataSource assigned as a property, otherwise, the List field of the parent report will become the corresponding data source for each child report in the hierarchy representation. The SubReport item has a ReportSource set both directly as a property, and with the following Binding:
Property path | Expression
ReportSource.Uri | = Fields("List") is Null ? Null : "HierarchyFromNestedCollections.trdp"
The above expression modifies the ReportSource so that when there is no more field "List" in the parent report DataSource a next level subreport is not generated, which will be the bottom of the recursion. The direct setting of the ReportSource property is needed in order to create the ReportSource object before modifying its Uri property with the Binding. Otherwise, the ReportSource object will be Null, which will result in an exception in the above Binding.
Solution 2
Another approach is suggested in the How do I displaying recursive data? Forum thread. The updated example can be downloaded from our GitHub repository: HierarchicalDataRepresentation.zip.