diff --git a/docs-builder.yml b/docs-builder.yml index 07f201d7a..bd9c7b76c 100644 --- a/docs-builder.yml +++ b/docs-builder.yml @@ -134,13 +134,16 @@ meta: ## User Guide section: wrd-user-guide/components: - position: 1 + position: 3 title: "Components" wrd-user-guide/components/subreport-item: - position: 1 + position: 2 title: "SubReport" - wrd-user-guide/customizing-report-items: + wrd-user-guide/data-scope: position: 2 + title: "Data Scope" + wrd-user-guide/customizing-report-items: + position: 5 title: "Customizing Report Items" ## Report Items section: diff --git a/wrd-user-guide/app-tour.md b/wrd-user-guide/app-tour.md index 24fc04b25..1a76e0ed0 100644 --- a/wrd-user-guide/app-tour.md +++ b/wrd-user-guide/app-tour.md @@ -6,7 +6,7 @@ slug: user-guide/app-tour tags: web, report, design, tool, create, report, web, structure published: True reportingArea: WRDHTML5, WRDBlazorWrapper -position: 5 +position: 1 --- # App Tour of the Web Report Designer diff --git a/wrd-user-guide/data-scope/data-binding-context.md b/wrd-user-guide/data-scope/data-binding-context.md new file mode 100644 index 000000000..ce9ef4bf0 --- /dev/null +++ b/wrd-user-guide/data-scope/data-binding-context.md @@ -0,0 +1,111 @@ +--- +title: Data Scope +page_title: Data Scope - Web Report Designer User Guide +description: "Learn how data scopes work in Telerik Reporting, how they are inherited, and how parent–child data item relationships affect them." +slug: data-scope +tags: report, bind, context, data, scope +published: True +tag: new +reportingArea: WRDHTML5, WRDBlazorWrapper +position: 0 +--- + +# Data Scope + +When you build a report in the Telerik Web Report Designer, every item (like a table, chart, or text box) needs to know which data it can see and display. This is called **data scope** (also known as data context). What data an item can see and display is defined by the item's type and its place in the report hierarchy. + +## Item Types + +Telerik Reporting provides two main categories of report items: + +* Data items—Each data item supports its own data binding, grouping, and layout capabilities, enabling flexible data organization and visualization. Common data items include Report, Table, Crosstab, List, and Graph. For example, the Table item displays data in rows and columns, while the Graph item visualizes aggregated data using various chart types. + +* Non-data items—Non-data items can display text, expressions, images, or identifiers and can be placed within data items or directly in report sections. These include items such as TextBox, PictureBox, Barcode, and others. + +## Data Scope Levels + +Think of data scope levels like a set of nested containers—each one holds a specific set of data than the one around it, and each data scope sits on a different level: + +* Report scope—The top-level report has its own data source and parameters. The report item (for example, “Report1”) defines the top-level data scope that includes all rows returned by its data source (after filtering and sorting). Everything inside the report, but outside nested data items, uses that scope by default. Expressions at this level can use: + * `=Fields.*` (if the report has a data source) + * `=Parameters.*` + * Aggregates (for example, `=Sum(Fields.Amount)`) + +* Data item scope (for example, Table, List, Crosstab, Graph)—Each data item can define its own data source and groups (Row/Column groups). Inside the item, `=Fields.*` refers to the current row/group data scope of that item. Since Telerik Reporting uses hierarchical data scopes and each data item (Table, List, Group, etc.) creates its own scope, you can use the `Parent` keyword when you're inside a nested data item and need access to values from an outer scope (for example, `=ReportItem.Parent.DataObject.OrderID`). + +* Group scope—Groups create nested (inner) scopes—Report groups, table/column/row groups, crosstab groups, and detail sections partition the data into smaller sets. Expressions inside a group are evaluated only against that group’s rows. The innermost “detail” is typically a single record. In group headers/footers and detail cells, `=Fields.*` resolves in the group’s data scope. + +* SubReport scope—A SubReport in Telerik Reporting does not inherit its data scope automatically from its parent report or parent data item. A SubReport always has its own data source, defined entirely by its ReportSource. This means that a SubReport is an isolated report that you load inside a parent report, and you control its data by passing parameters or by assigning it an explicit data source. + +### Passing Data to a SubReport + +The Available Options for passing data to a SubReport are: + +* Own DataSource—When the SubReport refers to a separate report (.trdp file) that has its own data source and you pass parameters and let the SubReport query its own data. This is the most common method. A similar approach is demonstrated in [Creating Master-Detail Reports]({%slug web-report-designer-user-guide-creating-master-detail-report%}) where the master report contains a table with Categories data. The SubReport displays Products records filtered by the respective CategoryID. + +* Setting the SubReport Data Source from the Parent Report—The SubReport item exposes a DataSource property that allows the parent report to supply data directly to the inner report. When this property is set on the SubReport item, the provided data source is used during report processing instead of the data source defined in the SubReport’s report definition. + +* Passing Data from the Parent—You can also use a DataObject as a data source for nested data items, meaning the child item’s entire data source can derive from the parent. A common scenario is when a parent data row contains a JSON column with child items. A similar approach is demonstrated in [Creating Nested Hierarchy with SubReports]({%slug wrd-user-guide-create-nested-hierarchy-with-subreport%}). + +## Data Scope in Expressions + +The data scope directly affects how expressions behave. The same expression can produce different results depending on where it is placed in the report: + +* **Field access** and **simple expressions** (like `=Fields.Amount`) run in the default scope, so inside a detail row it refers to the current record; inside a group footer it refers to the current group instance. + +* **Aggregates** (like `=Sum(Fields.Amount)`) calculate over the current data scope by default. That is why the same `=Sum(Fields.Amount)` expression returns a group subtotal when placed in a group footer, but returns the grand total when placed in the report footer. + +The Reporting engine provides the [Exec]({%slug telerikreporting/designing-reports/connecting-to-data/expressions/expressions-reference/functions/data-functions%}) aggregate function to perform calculations outside the current data or item scope. Unlike typical aggregate functions such as Sum, Avg, or Count, which operate only on the current data scope, Exec allows you to reference another parent’s scope. +This makes Exec extremely useful when you need to display aggregated values in headers, footers, textboxes, or other parts of the report where normal aggregates are not allowed. + +```Expression +=Exec("ReportItemName", AggregateExpression) +``` + +|Parameter|Description| +|----|----| +|`ReportItemName`|The name of the parent (one or more levels up the hierarchy) data item (for example, a table, group, or list) that defines the scope.| +|`AggregateExpression`|A valid aggregate function (for example, Sum(Fields.Price), Avg(Fields.Quantity)).| + +The following example shows how to display Total Sales in a TextBox placed in the header: + +```Expression +=Exec("Report1", Sum(Fields.Price * Fields.Quantity)) +``` + +* **Report1** defines the data scope. +* **Exec** evaluates the Sum expression as if it were inside the report. +* You get the correct total even though you are in the header. + +>note If you don’t specify a data scope in an expression, the **default data scope** is always the data scope of the closest enclosing data item or group. + +## Data Scope Inheritance + +By default, a non-data item (like TextBox) automatically uses the data scope of its parent. That's why you do not need to connect every item to a data source manually—the Web Report Designer passes data downward through the report's items and data scope levels for you. + +Every report starts with a top-level data source. Items placed directly in the report use that data. Items nested inside other items (for example, a text box inside a table cell) inherit the data scope of the item they are placed in. This lets you reuse the parent's data without creating a new data source for each child item. + +Inherited Data Scope + +>note The data scope is inherited only downward, not sideways. Two report items placed next to each other (siblings) do not access each other's data. Each item only inherits from its own parent. + +## Independent Data Scope + +When a data item has its own data source, it creates an independent data scope. Its children inherit that scope, not the parent report's data scope. This means the item's data is completely unaffected by the parent's filtering or grouping, making it easy to reuse tables, graphs, and SubReports across different parent reports. + +Two common patterns for using an independent data scope are: + +* Master-Detail (Parent-Child)—A parent Table uses **DataSource A**. Inside the detail row, a child Table, List, or Graph sets its own **DataSource B**, filtered by a key from the parent row. To pass the parent row's value to the child data source, use `=ReportItem.DataObject.CustomerId` or `=Fields.CustomerId` as a data source parameter. The child item then shows only the rows that match the current parent row. + +* SubReport—A SubReport is self-contained by design. You pass a parameter from the parent (for example, an `OrderId`) and the SubReport uses its own data source filtered by that parameter. This pattern is ideal when the same SubReport is reused across multiple parent reports. + +>note See the [Creating Master-Detail Reports]({%slug web-report-designer-user-guide-creating-master-detail-report%}) tutorial. + +Independent Data Scope + +## See Also + +* [Using ReportItem.DataObject]({%slug telerikreporting/designing-reports/connecting-to-data/data-items/how-to-use-the-reportitem.dataobject-property-in-expressions%}) +* [Data scope related functions]({%slug telerikreporting/designing-reports/connecting-to-data/expressions/expressions-reference/functions/data-functions%}) +* [Data Scope in Expressions]({%slug data-scope-in-expressions%}) +* [Data Scope in Filters]({%slug data-scope-in-filters%}) diff --git a/wrd-user-guide/data-scope/data-scope-in-expressions.md b/wrd-user-guide/data-scope/data-scope-in-expressions.md new file mode 100644 index 000000000..ffcbb995b --- /dev/null +++ b/wrd-user-guide/data-scope/data-scope-in-expressions.md @@ -0,0 +1,88 @@ +--- +title: Data Scope in Expressions (Tutorial) +page_title: Data Scope in Expressions - Web Report Designer User Guide +description: "Learn how data scope inheritance affects expressions and aggregates in Telerik Reporting by building a sample report with groups and subtotals." +slug: data-scope-in-expressions +tags: report, bind, context, data, scope, expression +published: True +tag: new +reportingArea: WRDHTML5, WRDBlazorWrapper +position: 1 +--- + +# Data Scope in Expressions (Tutorial) + +By following the steps below, you can build a sample report that will help you understand how the data scope inheritance works when using expressions. + +1. Create a new report in the Web Report Designer. + +1. Add a CSV Data Source to the report with the following data: + + ````CSV + Product,Category,Amount + Laptop,Electronics,1200 + Phone,Electronics,800 + Tablet,Electronics,400 + Headphones,Accessories,150 + Monitor,Electronics,300 + ```` + + If you explicitly set the DataSource property of your report, it defines a report-level data scope, containing all rows. It defines the outermost scope. However, for this example, leave the Report.DataSource empty. + +1. Add a Table: from the Components pane, drag a Table onto the design surface and bind it to your data source. A Table is a data item, so it switches scope to its own data source (data item-level scope). Everything inside its detail section is evaluated per row. + +1. Add fields to columns: + * Column 1: + ```` + =Fields.Product + ```` + + * Column 2: + ```` + =Fields.Category + ```` + + * Column 3: + ```` + =Fields.Amount + ```` + + At this point `Fields.Amount` in a detail row represents the value from the current record and the default scope is the Table row (innermost detail scope). + + Bound Table + +1. Preview the report. + + Preview Table Without Groups + +1. Add a Row Group by **Category** using the [Table Context Menu]({%slug telerikreporting/designing-reports/report-designer-tools/web-report-designer/tools/table-context-menu%}). + + Table Context Menu + Table Add Group + +1. Save the group. This creates a new group-level scope (subset of rows that share the same Category). Here, the default scope is the current group instance, so all fields refer to that group’s records. + + Table Group Scope + +1. Preview the report and see the products grouped by category: + + Preview Table Grops + +1. Add a Group Subtotal: In the Group Footer, select the TextBox under the **Amount** column and set the Value to `=Sum(Fields.Amount)`: + + Group Footer Sum + + `Sum()` automatically aggregates over the group scope, not the entire dataset. This is because the nearest ancestor defining a data scope is the group. For **Accessories**, *Subtotal Amount is 150* and for **Electronics**, the *Subtotal Amount is 2700*: + + Preview Group Footer Sum + +1. Add a Group Grand Total: In the Table Group, select the TextBox above the **Amount** column and set the Value again to `=Sum(Fields.Amount)`. This is the same expression as the one set in the group's footer. However, the result is different due to the larger data scope. + + Add Group Grand Total Sum + Preview Group Grand Total Sum + +## See Also + +* [Using ReportItem.DataObject]({%slug telerikreporting/designing-reports/connecting-to-data/data-items/how-to-use-the-reportitem.dataobject-property-in-expressions%}) +* [Data scope related functions]({%slug telerikreporting/designing-reports/connecting-to-data/expressions/expressions-reference/functions/data-functions%}) +* [Data Scope in Filters]({%slug data-scope-in-filters%}) diff --git a/wrd-user-guide/data-scope/data-scope-in-filters.md b/wrd-user-guide/data-scope/data-scope-in-filters.md new file mode 100644 index 000000000..8a9e01de1 --- /dev/null +++ b/wrd-user-guide/data-scope/data-scope-in-filters.md @@ -0,0 +1,77 @@ +--- +title: Data Scope in Filters (Tutorial) +page_title: Data Scope in Filters - Web Report Designer User Guide +description: "Learn how applying filters at the report, data-item, and group levels affects data scope and aggregate values in Telerik Reporting." +slug: data-scope-in-filters +tags: report, bind, context, data, scope, filter +published: True +tag: new +reportingArea: WRDHTML5, WRDBlazorWrapper +position: 2 +--- + +# Data Scope in Filters (Tutorial) + +You can filter data at multiple levels in your report. Each data level controls which records are available to the next level down. Parent scopes (like Tables) inherit all data unless you filter them. Child scopes (like Groups) inherit parent data (filtered or not) and can apply additional filters to the inherited data. + +This article builds on the example demonstrated in [Data Scope in Expressions]({%slug data-scope-in-expressions%}), which demonstrates how expressions in group-level scopes default to operating over the subset of records belonging to the group. Aggregates placed outside the group (like table header/footer) compute over all records that the Table receives. That is why for the *Grand total we calculated 2850*, for **Accessories**, *Subtotal Amount is 150* and for **Electronics**, the *Subtotal Amount is 2700*. + +Preview Grand Total + +Filters applied at a certain data level change the visible data records. Whichever records remain after filtering form the current data scope. All aggregates (Sum, Avg, Count, etc.) operate only on that scope. + +Report-level filtering affects only the report data and the data it passes to its children. Data-item-level filters affect only the data item (and its child items), not the whole report. + +## Filtering the Table + +Filter the table to show only the products belonging to the "Electronics" category: + +1. Select the table in the Explorer pane and add a filter: + + ```` + Fields.Category = "Electronics" + ```` + + Table Filter + +1. Preview the report. Both, the Grand Total (table data scope) and the Subtotal (groups data scope) values, are affected by the applied filter. Filters, applied to the parent data source, affect what records are available in the nested data items that inherit that data scope. + + Preview Table Filter + + +## Filtering the Group + +Filter the groups now to show products with a greater amount than 500: + +1. Select the detail table group in the Explorer pane and add a filter: + + ```` + Fields.Amount >= 500 + ```` + + Detail Group Filter + +1. Preview the report. Now, you can see only products whose amount is greater than 500. The Grand Total remains 2700 because it **uses the table's data scope** which is filtered by showing only Electronics. The Subtotal also remains 2700 because the Category group's scope still contains all Electronics rows (1200 + 800 + 400 + 300). Filtering the detail group level (Amount > 500) does not change the data scope for group-level aggregates, so the subtotal in the group footer continues to include all records in the group, regardless of the detail filter. Group aggregates (such as Sum, Count, etc.) are evaluated over the group’s data records as defined by the group expression, not by the filtered detail rows. Filtering at the detail group level only affects which detail rows are displayed, but does not alter the underlying data set used for group-level calculations. + + >important It is possible to add a filter at the category group level, but a Category Group filter does **not** remove individual detail rows. It only determines if the entire category group should appear or not. So, if a group contains at least one record with amount greater than 500, it will remain visible. + + Preview Detail + + To achieve subtotals that reflect only the filtered records, you can adjust your report design to use a filtered data source for the group itself. An alternative approach is to use a conditional subtotal in the CategoryGroup footer which is demonstrated in the following step. + +1. Apply a conditional sum to the group's footer—use an aggregate expression that sums only the values meeting your condition. The recommended approach is to use the Sum aggregate with an IIF (immediate if) statement: + + ```` + =Sum(IIf(Fields.Amount > 500, Fields.Amount, 0)) + ```` + + Now, the Subtotal shows the expected value 2000: + + Conditional Sum + + +## See Also + +* [Using ReportItem.DataObject]({%slug telerikreporting/designing-reports/connecting-to-data/data-items/how-to-use-the-reportitem.dataobject-property-in-expressions%}) +* [Data scope related functions]({%slug telerikreporting/designing-reports/connecting-to-data/expressions/expressions-reference/functions/data-functions%}) +* [Data Scope in Expressions]({%slug data-scope-in-expressions%}) diff --git a/wrd-user-guide/data-scope/images/add-group-grand-total-sum.png b/wrd-user-guide/data-scope/images/add-group-grand-total-sum.png new file mode 100644 index 000000000..44212c78a Binary files /dev/null and b/wrd-user-guide/data-scope/images/add-group-grand-total-sum.png differ diff --git a/wrd-user-guide/data-scope/images/bound-table.png b/wrd-user-guide/data-scope/images/bound-table.png new file mode 100644 index 000000000..19f573fc3 Binary files /dev/null and b/wrd-user-guide/data-scope/images/bound-table.png differ diff --git a/wrd-user-guide/data-scope/images/conditional-sum.png b/wrd-user-guide/data-scope/images/conditional-sum.png new file mode 100644 index 000000000..831a2072d Binary files /dev/null and b/wrd-user-guide/data-scope/images/conditional-sum.png differ diff --git a/wrd-user-guide/data-scope/images/filter-detail-group.png b/wrd-user-guide/data-scope/images/filter-detail-group.png new file mode 100644 index 000000000..4a5986bfb Binary files /dev/null and b/wrd-user-guide/data-scope/images/filter-detail-group.png differ diff --git a/wrd-user-guide/data-scope/images/filter-table.png b/wrd-user-guide/data-scope/images/filter-table.png new file mode 100644 index 000000000..e8b96d465 Binary files /dev/null and b/wrd-user-guide/data-scope/images/filter-table.png differ diff --git a/wrd-user-guide/data-scope/images/group-footer-sum.png b/wrd-user-guide/data-scope/images/group-footer-sum.png new file mode 100644 index 000000000..41c36af31 Binary files /dev/null and b/wrd-user-guide/data-scope/images/group-footer-sum.png differ diff --git a/wrd-user-guide/data-scope/images/inherited-data-context.png b/wrd-user-guide/data-scope/images/inherited-data-context.png new file mode 100644 index 000000000..637daccb7 Binary files /dev/null and b/wrd-user-guide/data-scope/images/inherited-data-context.png differ diff --git a/wrd-user-guide/data-scope/images/own-data-context.png b/wrd-user-guide/data-scope/images/own-data-context.png new file mode 100644 index 000000000..6ebd14467 Binary files /dev/null and b/wrd-user-guide/data-scope/images/own-data-context.png differ diff --git a/wrd-user-guide/data-scope/images/preview-add-group-grand-total-sum.png b/wrd-user-guide/data-scope/images/preview-add-group-grand-total-sum.png new file mode 100644 index 000000000..555346c50 Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-add-group-grand-total-sum.png differ diff --git a/wrd-user-guide/data-scope/images/preview-detail-group-filter.png b/wrd-user-guide/data-scope/images/preview-detail-group-filter.png new file mode 100644 index 000000000..5b38d88a3 Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-detail-group-filter.png differ diff --git a/wrd-user-guide/data-scope/images/preview-group-footer-sum.png b/wrd-user-guide/data-scope/images/preview-group-footer-sum.png new file mode 100644 index 000000000..dfe984724 Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-group-footer-sum.png differ diff --git a/wrd-user-guide/data-scope/images/preview-table-filter.png b/wrd-user-guide/data-scope/images/preview-table-filter.png new file mode 100644 index 000000000..ed1cc0b69 Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-table-filter.png differ diff --git a/wrd-user-guide/data-scope/images/preview-table-groups.png b/wrd-user-guide/data-scope/images/preview-table-groups.png new file mode 100644 index 000000000..921617719 Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-table-groups.png differ diff --git a/wrd-user-guide/data-scope/images/preview-table-without-groups.png b/wrd-user-guide/data-scope/images/preview-table-without-groups.png new file mode 100644 index 000000000..74afbf3eb Binary files /dev/null and b/wrd-user-guide/data-scope/images/preview-table-without-groups.png differ diff --git a/wrd-user-guide/data-scope/images/table-add-group.png b/wrd-user-guide/data-scope/images/table-add-group.png new file mode 100644 index 000000000..e908cf6b3 Binary files /dev/null and b/wrd-user-guide/data-scope/images/table-add-group.png differ diff --git a/wrd-user-guide/data-scope/images/table-context-menu.png b/wrd-user-guide/data-scope/images/table-context-menu.png new file mode 100644 index 000000000..d48bf3e04 Binary files /dev/null and b/wrd-user-guide/data-scope/images/table-context-menu.png differ diff --git a/wrd-user-guide/data-scope/images/table-group-scope.png b/wrd-user-guide/data-scope/images/table-group-scope.png new file mode 100644 index 000000000..71f425853 Binary files /dev/null and b/wrd-user-guide/data-scope/images/table-group-scope.png differ diff --git a/wrd-user-guide/getting-started.md b/wrd-user-guide/getting-started.md index bc0df8e3e..6f62a87fd 100644 --- a/wrd-user-guide/getting-started.md +++ b/wrd-user-guide/getting-started.md @@ -6,7 +6,7 @@ slug: web-report-designer-user-guide-getting-started tags: web, report, design, tool, create, started published: True reportingArea: WRDHTML5, WRDBlazorWrapper -position: 8 +position: 2 ---