# Data Manager to RDL Conversion

This section explains some details on how reports defined in *DataManager* classes are converted to the *Report Definition Language* (RDL).

Notice that this mapping is done automatically at runtime . This document gives and overview on how the internal process of converting DataManagers to RDL work.

## Overview <a href="#overview" id="overview"></a>

As described in the [Reports in code](http://product-docs.azurewebsites.net/PBNet/articles/reports/reportsInCode.html) section when a report is requested to the modernized application the *ReportWatcher* service is invoked when all the elements required for creating the report. These elements are (mainly):

1. Report definitions in the RDL format
2. Report data using XML and `System.Data.DataSet` format

The generation of the RDL format is performed *at runtime* from the definition of a *DataManager*. This conversion is performed based on the object model of a *DataManager*. The runtime system takes the definition and converts all of the parts of a DataManager to the RDL format. For example for a DataManager with a label control like this:

```
    this.name_t = new Mobilize.Web.DmText();
    this.name_t.Band = Mobilize.Web.CaseExtensions.String("detail");
    this.name_t.Alignment = 1;
    this.name_t.Text = "Name:";
    this.name_t.Border = 0;
    this.name_t.Color = "33554432";
    this.name_t.X = 37;
    this.name_t.Y = 4;
    this.name_t.Height = 64;
    this.name_t.Width = 174;
    this.name_t.Name = Mobilize.Web.CaseExtensions.String("name_t");
    this.name_t.Visible = true;
    this.name_t.Font.FontFace = "Tahoma";
    this.name_t.Font.Height = -10;
```

The conversion generates the following RDL Fragment for DataManager instances created with the previous snippet:

```

    0.01042in
    0.08333in
    0.39583in
    0.16667in
    true
    
    
        
        
            Name:
            
        
        
        
    
    

```

Notice that this conversion is performed *at runtime*. This is done this way to support dynamic operations performed on the *DataManager* at runtime .

## DataManager layout vs RDL File organization <a href="#datamanager-layout-vs-rdl-file-organization" id="datamanager-layout-vs-rdl-file-organization"></a>

The following diagrams show how different top-level sections of a *DataManager* are converted to RDL.

### Page configuration section: <a href="#page-configuration-section" id="page-configuration-section"></a>

This section contains properties for page width, height, margins, etc. (left: lines 14-18 in the left source file). These properties are converted to XML elements in RDL in lines 24-29.

### Data configuration section <a href="#data-configuration-section" id="data-configuration-section"></a>

This section contains configuration for report data columns (left: lines 27-30). Theses columns are converted to RDL report Fields in the DataSet section (right: lines 8-12).

### Header and footer configuration <a href="#header-and-footer-configuration" id="header-and-footer-configuration"></a>

This section contains configuration for report header and footers (left: lines 27-30). Theses columns are converted to RDL report Fields in the DataSet section (right: lines 30-31).

### Controls and report content <a href="#controls-and-report-content" id="controls-and-report-content"></a>

This section contains most of the elements of the report. Controls used inside the report are defined as class properties (left: lines 5-9) and also inside the *DataManager* constructor as a sequence of control property initialization (left: lines 32-40). These elements are converted to RDL elements inside the report body (right: line 18) .

## Dealing with embedded reports <a href="#dealing-with-embedded-reports" id="dealing-with-embedded-reports"></a>

The *DataManager* to RDL conversion support embedded reports using the RDL [Subreport element](https://docs.microsoft.com/en-us/openspecs/sql_server_protocols/ms-rdl/40ed3768-0835-4989-a20d-3c06907f43df).

The following code snippet shows an embedded report inside a DataManager:

```
this.rpt_1 = new DmReport();
this.rpt_1.Band = "detail";
this.rpt_1.Name = "rpt_1";
this.rpt_1.DataObject = "my_subrepo";
this.rpt_1.Nest_Arguments = new string[] { "col1", "col1 + 1" };
this.rpt_1.X = 37;
this.rpt_1.Y = 4;
this.rpt_1.Width = 174;
this.rpt_1.Height = 64;
```

The `DataObject` property says which *DataManager* will be used to render the embedded report. This control is converted to RDL as follows:

```

  0.39583in
  0.16667in
  rpt_1
    
        
        = Fields!col1.Value 
        
        
        =Code.SumValues( Fields!col1.Value , 1)
        
    

```

The binding to the new report is performed by the *ReportWatcher* service. This service uses the [ReportViewer.LoadSubReportDefinition](https://docs.microsoft.com/en-us/dotnet/api/microsoft.reporting.webforms.localreport.loadsubreportdefinition?view=sqlserver-2016) to provide the definition of the embedded report .

## Label reports <a href="#label-reports" id="label-reports"></a>

The original platform allowed the creation of a special *DataWindow* used to print labels. This concept is converted to a DataManager which is converted to a RDL report that tries to emulate the behavior of the original report.

The [Tablix SSRS concept](https://docs.microsoft.com/en-us/sql/reporting-services/report-design/tablix-data-region-report-builder-and-ssrs?view=sql-server-ver15) is used to emulate the layout of a label *DataWindow* . The general strategy to create a `Tablix` having row groups for blocks of labels, a column group is created to show several labels in the same row, with a dummy column at the end for spacing.

## Crosstab reports <a href="#crosstab-reports" id="crosstab-reports"></a>

The *CrossTab* DataWindow, which presents data in a spreadsheet-like grid. A *CrossTab* lets users view summary data instead of a long series of rows and columns. The strategy was to use the [Tablix SSRS concept](https://docs.microsoft.com/en-us/sql/reporting-services/report-design/tablix-data-region-report-builder-and-ssrs?view=sql-server-ver15) to create a report using multiple Tablix elements to generate the matrix-like structure that emulates the same structure as the original DataWindow.

## Limitations <a href="#limitations" id="limitations"></a>

There are some limitations to the DataManager to RDL conversion strategy. There are some techniques that were valid on the original platform but that could not be emulated in the target platform.

Here is a list of some of this issues

### Position of elements could not be changed at render time <a href="#position-of-elements-could-not-be-changed-at-render-time" id="position-of-elements-could-not-be-changed-at-render-time"></a>

In the original platform the position, height or width of an element could be changed at runtime by evaluating a custom expresion. For example:

```
this.myLabel.X = "10\t opt_1 + 10"
```

In this cases the `X` property of the `myLabel` control is determined at runtime depending on the evaluation of the `opt_1 + 10` expression. This in turn is evaluated for each row. In SSRS and RDL it's not possible to associate an expression to the position, with or height of an element or band.

To support this same behavior it is recommended to examine the original intension of the developer. As an example, the following snippet specify that the height of a label will be zero if the `opt_1 = 100` condition is satisfied:

```
this.myLabel.Height = "10\t IF(opt_1 = 100,0, 10)"
```

In this case it's better to use the `Visible` property . This property supports expressions in SSRS.

### Evaluation of code inside report expressions <a href="#evaluation-of-code-inside-report-expressions" id="evaluation-of-code-inside-report-expressions"></a>

The original platform supports calling global functions inside report expressions. This is not supported in the SSRS/RDL version since the report is being rendered outside of the application process.

In this case the *DataManager* to RDL conversion generates evaluation of report expressions that required access to original code as part of the data of the report. This allows the evaluation of the original expressions.

For example if a property is assigned as:

```
this.name_t.Text = "a\tmyglobalfunc(10)";
```

The generated report definition is going to have an additional field to stored the evaluation of this property:

```

    name_t__TEXT

```

The process that generates the data dump for the report data evaluates these expressions for each row of the *DataManager*. This data dump is passed to the *ReportWatcher* service to render the report.

### Evaluation of code and render time properties <a href="#evaluation-of-code-and-render-time-properties" id="evaluation-of-code-and-render-time-properties"></a>

The original platform allowed the evaluation of functions which value could only be determined at render time. For example the `Page()` function which returns the current page of the report. Uses of this function are converted to the RDL equivalent `Globals!PageNumber` . However the evaluation of this property could not be combined with expressions evaluated on the server side .For example:

```
this.name_t.Text = "a\tmyglobalfunc(Page())";
```

This expression could not be converted to RDL since it requires both evaluating user code and evaluating a render time property.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gapvelocity.ai/webmap/powerbuilder-to-.net/reports/untitled-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
