You can update custom report layouts by creating upgrade codeunits to handle changes in report datasets that affect the report layouts. Upgrade codeunits enable you to programmatically update multiple custom report layouts in the database to changes in report datasets. Although report layout updates can be done from the Microsoft Dynamics NAV client, there are certain changes to the dataset that require the user to manually modify report layouts before they can be used. These types of changes include, for example, deleted fields or field name conflicts as a result of renaming. Upgrade codeunits enable you handle these breaking changes to report datasets and layouts without requiring end-user interaction.
To design the report upgrade logic in an upgrade codeunit, you add C/AL code that implements the report upgrade API (through .NET Framework interoperability) and a set of functions that are available in codeunit 9651Document Report Mgt.. In the Microsoft Dynamics NAV application, codeunit 9651Document Report Mgt. is the main component for running and maintaining customized report layouts.
For general information about upgrade codeunits, see Upgrade Codeunits.
Report Upgrade API Overview
The upgrade and maintenance of report layouts in the databases is controlled by the following .NET Framework assemblies on the Microsoft Dynamics NAV Server:
The Microsoft.Dynamics.Nav.Types.Report assembly contains the following types that you can use to for programmed report layout upgrades in upgrade codeunits.
The DeleteAction enumeration determines how content controls for fields (data items and columns of the report's dataset) in a report layout are deleted. The following table describes the members of the DeleteAction enumeration:
Deletes the entire XML node that is contained in the content control or the tablix that is associated with the field.
Deletes the content control that is associated with the field, but leaves a blank text string in the text element (keep including paragraph formatting).
Deletes the repeater content control, but leaves the table structure (rows) that is contained in the content control or the tablix.
Deletes the repeater content control and the table structure that is contained in the control.
Deletes the content control for the field and replaces it with a text constant.
The IReportUpgradeSet interface provides an interface to the object that stores all changes that must be applied to a specific report layout in the current database.
The following table describes the properties of the IReportUpgradeSet interface.
Gets the ID of the application report object that pertains to set of changes.
Gets the number of errors that occurred during the upgrade.
Gets the number of changes that are required for the report layout as a result of dataset changes.
Gets the list of changes to report layouts.
The following table describes the methods of the IReportUpgradeSet interface. You use the methods to specify whether to delete or modify the content controls for data items and columns (fields) in a report layout. The behavior is controlled by the DeleteAction enumeration parameter.
Deletes a content control for data field or label field from the report layout that is associated with a column in the dataset. The method can completely remove the content control or it can replace it with a text constant as specified by the DeleteAction enumeration parameter.
Deletes the content control from the report layout that references a data item in the dataset. The content control is deleted according to the behavior that is specified by the DeleteAction enumeration parameter. This pertains to Word layout types only.
Renames a content control for data field or label field. You can also use this method to move the content control to a different XML path in the dataset.
Rename a control for a data item, and optionally move it to a different XML path in the dataset. This pertains to Word layout types only.
All methods with matching names and paths will overwrite existing change definitions in the collection for the same item.
The following table describes the parameters of the IReportUpgradeSet interface methods.
The name of the data item, column, or label in the dataset.
Original name of the data item, column, or label in the dataset.
New name of the data item, column, or label in the dataset.
Path of the data item that contains the data item or field. The path is the hierarchy of the data item which contains the data item or field. The path is used to identify the content control's data bindings in Word report layouts.
Original parent path that you want to change.
New parent path. If this parameter is left empty, then this parameter uses the value of the fromParent by default.
Text constant to use in place of the deleted field in the layout.
The Microsoft.Dynamics.Nav.DocumentReport assembly contains several types for creating and managing report layouts. With regards to upgrading report layouts, only the ReportUpgradeCollection class is relevant.
The ReportUpgradeCollection class stores sets of changes that have been calculated or specified for reports in the current database.
The ReportUpgradeCollection class has only the AddReport method. This method adds a new report to the upgrade collection.
public IReportUpgradeSet AddReport(int reportId)
This method instantiates a new object for the report ID that is specified by the reportId parameter. If the report already exists in the collection, the existing object will be returned.
Custom Report Layout Upgrade Example
This example illustrates how you can update custom report layouts to dataset changes by using C/AL code, the report update API, and upgrade codeunits. This example will update a custom report layouts for report ID 1306 Mini Sales - Invoice. The following table describes the changes to the report dataset and how to the handle the updates in the custom report layouts:
|Dataset change||Report Layout Update|
Removed the CompanyIBAN column
Remove the content control and text for the associated field in the report layout.
Removed the Unit Price column
Remove the associated field control in the report layout and replace it with the text "deleted".
Removed the Quantity_ShipmentLine column
Remove the associated field control and replace it with the text "Deleted".
Renamed the VariantCode_AssemblyLine column to VariantCode_NewAssemblyLine.
Rename the VariantCode_AssemblyLine field to VariantCode_NewAssemblyLine.
|This example is based on the codeunit 104060 Report Layout Upgrades that is available in the Upgrade800800.fob file of the Microsoft Dynamics NAV 2017 upgrade toolkit.|
To create the upgrade codeunit
Create a codeunit and set the SubType Property (Codeunit) to Upgrade.
Create a new local function called UpgradeReportLayout, and then do the following:
Define a parameter that has the name TestMode and datatype Boolean.
Define the following variables:
Name DataType SubType
Microsoft.Dynamics.Nav.Types.Report.IReportUpgradeSet.'Microsoft.Dynamics.Nav.Types.Report, Version=126.96.36.199, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
Microsoft.Dynamics.Nav.DocumentReport.ReportUpgradeCollection.'Microsoft.Dynamics.Nav.DocumentReport, Version=188.8.131.52, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
Microsoft.Dynamics.Nav.Types.Report.ReportChangeOptions+DeleteAction.'Microsoft.Dynamics.Nav.Types.Report, Version=184.108.40.206, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
Document Report Mgt.
- Define a parameter that has the name TestMode and datatype Boolean.
Add the following code to the UpgradeReportLayout function.
// Instantiate the ReportUpgradeCollection variable ReportUpgradeCollection := ReportUpgradeCollection.ReportUpgradeCollection; // Calculate the set of changes for all layouts in the current database DocumentReportMgt.CalculateUpgradeChangeSet(ReportUpgradeCollection); // Example code snippet for applying a "breaking" change to a report design. // The example uses report 1306 Mini Sales - Invoice. ReportUpgradeSet := ReportUpgradeCollection.AddReport(1306); IF NOT ISNULL(ReportUpgradeSet) THEN BEGIN // Delete the text content control for the CompanyIBAN column and replace with empty text string) ReportUpgradeSet.DeleteField('CompanyIBAN', '/Header', DeleteAction.DeleteContent, ''); // Delete the text content control for the UnitPrice and replace the control with the text Deleted. ReportUpgradeSet.DeleteField('UnitPrice', '/Header/Line', DeleteAction.ReplaceWithText, 'Deleted'); // Delete the control containing the field. ReportUpgradeSet.DeleteField('Quantity_ShipmentLine', '/Header/Line/ShipmentLine', DeleteAction.DeleteNode, ''); // Rename the VariantCode_AssemblyLine field ReportUpgradeSet.ChangeField('VariantCode_AssemblyLine', 'VariantCode_NewAssemblyLine', '/Header/Line/AssemblyLine', '/Header/Line/AssemblyLine'); END; // Apply the upgrade steps to the report layouts DocumentReportMgt.ApplyUpgradeToReports(ReportUpgradeCollection,TestMode);
The UpgradeReportLayout function instantiates a report upgrade collection object and calculates the change set based on the current report dataset designs and the XML documents that are stored with the custom report layouts in the application database. Then, it adds additional changes to the custom report layouts for report 1306, including deleting fields and renaming a field.
Finally, the DocumentReportMgt.ApplyUpgradeToReports method applies all the updates to report layouts in the current database. If the TestMode parameter is True, the layout changes are only tested and will not be committed to the database.
Add a function called TestLaypoutUpgrade and set the FunctionType Property (Upgrade Codeunits) to CheckPrecondition. Add the following code:
The defines a CheckPrecondition function type, which is the first function that is executed when the codeunit is run. This function will test the report layout changes before they are applied to the layouts in the database. If an error occurs when this function is run, then the changes are not applied.
Add a function called RunLayoutUpgrade and set the FunctionType Property (Upgrade Codeunits) to UpgradePerDatabase. Add the following code:
This function is run after the CheckPrecondition function to perform the upgrade the report layouts.
Save and compile the codeunit.
Perform a data upgrade to run the upgrade codunit.
Open development environment as an administrator. On the Tools menu, choose Data Upgrade, and then choose Start and follow the instructions.
Note You can also perform the data upgrade by running the Start-NavDataUpgrade cmdlet from the Microsoft Dynamics NAV 2017 Administration Shell.