Development Tips

How to: Specify the Start ID Offset of Elements on Objects – In Navision 2015

You can specify a start ID for new objects so that elements on these new objects have IDs that are offset by the number that you specified.

For example

You can specify a start ID of 50000 and then create a new page. The first element that you create on the page, for example, a Container control, has ID 50000. The next element that you create on the page, for example, a Group control, has ID 50001. The ID of each element on the page is incremented by 1, starting with the offset that you specified.

If you create variables or text constants on the page, then the first variable or text constant has ID 50000. The ID of each variable or text constant that you create is incremented by 1, starting with the offset that you specified.

If you create functions on the page, then they start with ID 50000. Parameters, return value, local variables, and local text constants of a function start with ID 50000.

Note

In earlier versions of Microsoft Dynamics NAV, you specified the start ID offset by using the GetUidOffset function in codeunit 1.

You can use the start ID to identify a set of elements in your application, for example, to identify the elements in a country/region-specific version.

When you merge changes from different country/region-specific versions, having different start IDs lets you easily identify the country/region-specific version for each element.

If you do not specify a start ID, then the IDs are determined by your license.

 

To specify the start ID

  • In the development environment, on the File menu, choose Database, and then choose Alter.
  • In the Alter Database window, select the Advanced tab.
  • On the Advanced tab, under Designer, in the Start ID (UidOffset) text box, enter an integer, and then choose the OK button.

Start-Id
Important

Microsoft recommends that you specify a start ID that is greater than or equal to 1000. If you specify a start ID that is less than 1000, then variables and text constants on the object have a starting offset of 1000, not the value that you specified. Other elements on the object have the starting offset that you specified.

  • Create a new table, page, report, codeunit, query, or XMLport. The IDs of the elements on that object are offset by the number that you specified.

Note

To view the ID of an element, select the element in the designer, and then on the View menu, choose Properties.

 

 

Development Tips

Object Specifications and Limitations – in Navision 2015

Today I would like to discuss few important information. It always good to know out limitations, so do the limitation of the tools we are using. It helps in planning the design what all are possible and where are the limitations.

This could be also helpful for person taking interviews or appearing for interviews.

Below are the specifications and limitations for the database and application objects.

Specifications for the database

Feature Characteristic
Maximum number of physical disk files 16
Database file size 256 GB
Maximum number of objects in a database 1,000,000,000
Maximum number of characters in application object names 30
Maximum number of characters in a Database Authentication password 80

Specifications for Tables

Feature Characteristic
Range for table object ID numbers 1 – 999,999,999
Maximum number of characters in a table name 30
Maximum table size Depends on available storage
Maximum number of records in a table Depends on available storage
Maximum record size 8000 bytes
Maximum number of fields in a record 500
Range for field numbers 1 – 999,999,999
Maximum number of keys for a table 40
Maximum size of a Microsoft Dynamics NAV key 900 bytes
Maximum number of distinct fields per key 16
Maximum size of an index 900 bytes
Maximum number of SumIndexFields per key 20
Maximum number of characters in a text or code field 250
Maximum size of a BLOB field 2 GB
Maximum number of characters in a field name 30

 Specifications for Pages and Reports

Feature Characteristic
Range for page or report object ID numbers 1 – 999,999,999
Maximum number of characters in a caption 1024
Maximum bitmap size in bitmap property 32500 bytes

Specifications for Codeunits

Feature Characteristic
Range for codeunit object ID numbers 1 – 999,999,999
Maximum number of characters in variable names 30
Maximum number of dimensions in array variables 10
Maximum number of elements in an array variable 1,000,000
Maximum physical size of a codeunit 2 GB
Lower bound of index in an array 1

All application objects are identified by an ID number. There are restrictions, however, on the numbers you can use when you create your own application objects. Check with your Partner License Agreement for more information.

Development Tips

AccessByPermission Property – in Navision 2015

Sets a value for a table field or UI element that determines the permission mask for an object that a user must have to see and access the related page fields or UI element in the client. The UI element will be removed at runtime if the user does not have permissions to a certain object as specified in the Access by Permission window.

AccessByPermission-1
AccessByPermission-2
AccessByPermission-3

Depending on the setting in the UI Elements Removal field in the Microsoft Dynamics NAV Server Administration tool, only user interface (UI) elements on objects in the license or on objects that the user has permissions to will appear in the user interface.

AccessByPermission-4

To make full use of the LicenseFileAndUserPermissions option in the UI Elements Removal field, it is recommended that you assign the special permission set, FOUNDATION, along with the relevant permission sets that define which application objects the user will access.

AccessByPermission-5

The majority of the permission sets that are provided with the CRONUS demonstration database cannot be combined with the FOUNDATION permission set to fully use the UI Elements Removal feature. You must first create or edit the relevant permission sets to avoid that the user is blocked from performing the involved tasks. You must first create or edit the relevant permission sets to avoid that the user is blocked from performing the involved tasks.

If you only use the LicenseFile option in the UI Elements Removal field, then you do not have to edit any permission sets as they will not affect which UI elements are removed.

To specify when UI elements are removed
  1. Open the Microsoft Dynamics NAV Server Administration
  2. In the UI Elements Removal field, choose the relevant option as described in the following table.
Option Description
None All UI elements are displayed, even if the license file does not include the related object and the user does not have permissions to the related object.
LicenseFile A UI element is removed if the related object is not included in the license file.
LicenseFileAndUserPermissions A UI element is removed if the related object is not included in the license file and the user does not have permissions to the object as defined in the AccessByPermission property for the related UI element.

By default, this option is selected.

AccessByPermission-6

When you configure user interfaces in Microsoft Dynamics NAV, you should make sure that the UI Elements Removal field is set to its default, LicenseFileAndUserPermissions, so that you only see the relevant UI elements in the Customize window.

When you develop in Microsoft Dynamics NAV, you should make sure that the UI Elements Removal field is set to its default, None, to make sure that all UI elements are visible when you review your development in the UI.

All types of UI elements will be removed if they relate to objects that are not included in the license or the user does not have the required permission to the objects:

  • Fields
  • Actions
  • Page parts

UI elements that are directly related to an object through the TableRelation or the CalcFormula property can be removed automatically according to the license file and/or user permissions.

For UI elements that are not directly related to an object, you can use the AccessByPermission property to remove the element according to the user’s permission to a related object

All types of UI elements will be removed if they relate to an object to which the user does not have the required permissions:

Fields on pages, including FactBoxes

Actions on pages, including toolbars and navigation panes

Page parts, such as Lines FastTabs

Note

To use this property, the UI Elements Removal field in the Microsoft Dynamics NAV Server Administration tool must be set to LicenseFile or LicenseFileAndUserPermissions.

This Property Applies To

Fields in tables (affecting all related fields on pages)

Fields on pages

Actions on pages

MenuSuite items

Page parts, such as a Lines FastTab

Property Value

When you choose the AssistEdit button, the Access By Permission window opens. Fill the fields as described in the following table.

Field Description
Object Type Specify the type of object to which permission is required to display the UI element.
Object ID Specify the object to which permission is required to display the UI element.
Read Specify if Read permission is required to display the UI element.
or Insert Specify if Insert permission is required to display the UI element.
or Modify Specify if Modify permission is required to display the UI element.
or Delete Specify if Delete permission is required to display the UI element.
or Execute Specify if Execute permission is required to display the UI element.

AccessByPermission-7

Note

If multiple permissions are selected, then one or the other applies.

Example: Remove the Unit Price field if the user does not have permission to the Sales Price table

Open table 27, Item Card, with the Table Designer.

View the properties of field 18, Unit Price.

For the AccessByPermission property, choose the AssistEdit button in the Value field.

In the Access By Permission window, fill the fields as described in the following table.

Field Description
Object Type TableData
Object ID Sales Price
Read Select
Insert Select
Modify Leave blank
Delete Leave blank
Execute Leave blank

Close the Access By Permission window and save the changes on table 27.

All instances of the Unit Price field on pages are now removed if the user does have Read or Insert permission to the Sales Price table.

AccessByPermission-8

Important

If you defined the property for a table field, then all instances of the field on pages are removed. To override the property on an individual page field, delete the permission value after the = sign in the Value field. Do NOT delete the whole string as that will be replicated on the property of the table field.

Note

To use the LicenseFileAndUserPermissions option in the UI Elements Removal field, you must assign the special FOUNDATION permission set to the user along with the relevant application permission sets that define which application objects the user will access. Unlike the BASIC permission set, the FOUNDATION permission set only grants access to application setup and system tables and requires that other assigned permission sets define which specific application objects can be accessed.

Not all of the 167 default permission sets that are provided with Microsoft Dynamics NAV are ready to support the FOUNDATION permission set to remove UI elements according to user permissions. You must therefore edit the relevant permission sets as explained in the following procedures.

To experience how UI elements are removed for a user performing the task to create and edit a new customer, you can create a sample user interface based on default permission sets provided with Microsoft Dynamics NAV.

Special Permission Sets

The following permission sets have special definitions that you should be aware of as you implement permissions and security for Microsoft Dynamics NAV users.

Permission set Definition
SUPER Can read, use, update, and delete all data and all application objects in the scope of your license. Microsoft Dynamics NAV requires that at least one user be assigned this permission set in each database.

You cannot modify permissions for the SUPER permission set.

SUPER (DATA) Can read, use, update, and delete all data. You typically assign this permission set to an accounting manager who needs to work with all data but does not need to change Microsoft Dynamics NAV.

This permission set does not give access to the Object Designer.

SECURITY Can create new users and assign them the same permission sets. Must be able to access the User, User Property, Permission Set, and Access Control tables.

For example, you can create a SECURITY permission set that includes the four required tables and any additional permissions that you want to include. You can then assign this permission set to a user who is a department administrator. This user can then administer permissions for other users in their department.

Only a user who has the SUPER permission set can create and modify a SECURITY permission set. Users who have this permission set can assign the same permissions to other users, but they cannot assign themselves the SUPER permission set.

BASIC Grants Read access to almost all application tables and all system tables.

The main purpose of this permission set is to enable the client to open and show all pages.

When you create a new database, you must import the BASIC permission set from an XML file.

FOUNDATION A prerequisite for all other permission sets. The FOUNDATION permission set grants access to system tables and application setup tables that are required for most application features to work.

Note

This permission set is recommended when using the UI Elements Removal feature to automatically remove UI elements according to user permissions.

Development Tips

Testing Best Practices

There is always trade-off between Quality & Quantity of deliverables.

Sometimes small Partners don’t want to invest on resources and time for their deliverables to make big profits.

Sometimes customers are not interested in paying more for their customizations requested, their after they keep investing on recursive fixes for their solutions.

Sometime requirement is not well aligned with Business Logic and the process keeps refining over the time.

Which leads to arguments on Product capability and Partner Quality of work.

Whatsoever may be the reason but before any piece of code is moved to the Production environment should be well tested and accepted by the clients/customers.

Microsoft recommends the following best practices for designing your application tests:

  • Test code should be kept separate from the code that is being tested. That way, you can release the tested code to a production environment without releasing the test code.
  • Test code should test that the code being tested works as intended both under successful and failing conditions. These are called positive and negative tests. The positive tests validate that the code being tested works as intended under successful conditions. The negative tests validate that the code being tested work as intended under failing conditions.
    • In positive tests, the test function should validate the results of application calls, such as return values, state changes, or database transactions.
    • In negative tests, the test function should validate that the intended errors occur, error messages are presented, and the data has the expected values.
  • Automated tests should not require user intervention.
  • Tests should leave the system in the same well-known state as when the test started so that you can re-run the test or run other tests in any order and always start from the same state.
  • Test execution and reporting should be fast and able to integrate with the test management system so that the tests can be used as check-in tests or other build verification tests, which typically run on unattended servers.
  • Create test functions that follow the same pattern:
    • Initialize and set up the conditions for the test.
    • Invoke the business logic that you want to test.
    • Validate that the business logic performed as expected.

For more details see below Links:

Creating a Test Codeunit and Test Function
Creating a Test Runner Codeunit
Adding a Test to a Test Runner Codeunit

Development Tips

Adding a Test to a Test Runner Codeunit

How to add a line to test runner codeunit that runs the new TestVendorDiscount codeunit.

The test runner codeunit runs all the test codeunits that you may have created to test the other customized functionality.

To add a test to a test runner codeunit

  • In the development environment, on the Tools menu, choose Object Designer.
  • In Object Designer, choose Codeunit, select the existing test runner codeunit, and then choose the Design button.
  • In the C/AL Editor, in the OnRun function, add the following code.

CODEUNIT.RUN(CODEUNIT::TestVendorDiscount);

  • On the File menu, choose Save.

For more details see below posts:

Creating a Test Codeunit and Test Function
Creating a Test Runner Codeunit

Development Tips

Creating a Test Runner Codeunit

Follow below Steps to Create Test Runner

  • In the development environment, on the Tools menu, choose Object Designer.
  • In Object Designer, choose Codeunit, and then choose New.
  • On the View menu, choose Properties.
  • In the Properties window, in the Subtype field, select TestRunner to specify that this is a test runner codeunit.
  • In the TestIsolation field, specify which changes to that you want to roll back. You can choose from the following values:
    • Disabled
    • Codeunit
    • Function

TestCu-5

Value Description
Disabled Do not roll back any changes to the database. Tests are not isolated from each other.This is the default value.
Codeunit Roll back all changes to the database after each test codeunit executes.
Function Roll back all changes to the database after each test function executes.

It is recommend that you design tests to be independent of each other. Tests might read from and write to the same database, which means that tests can interact with each other.

If tests interact, then you may experience incorrect test results.

To eliminate test interactions, use the TestIsolation property to roll back changes to the database after each test function or after each test codeunit.

If you specify that you want to roll back database changes, then all database changes are rolled back, including changes that were explicitly committed to the database during the test by using the COMMIT function.

  • In the C/AL Editor, in the OnRun function, enter code to run the test codeunits. For example, the following code in the OnRun function of a test runner codeunit runs test codeunits.

CODEUNIT.RUN(CODEUNIT::TestVendorDiscount);

Note
You may want to define your test suite in a table and then write code in the OnRun function of the test runner codeunit to iterate through items in the table and run each test codeunit.
  • (optional) To create an OnBeforeTestRun trigger, do the following steps:
    • On the View menu, choose C/AL Globals.
    • In the C/AL Globals window, on the Functions tab, on a new line in the Name field, enter OnBeforeTestRun, and then choose Locals.
    • In the C/AL Locals window, on the Parameters tab, enter the following.

TestCu-6

    • In the C/AL Locals window, on the Return Value tab, enter the following

TestCu-7

    • Close the C/AL Locals window.
    • In the C/AL Editor, in the OnBeforeTestRun trigger, enter code that executes before each test function. Typically, the code in the OnBeforeTestRun function determines if the test function should execute and returns true if it should. Otherwise, the trigger returns false. The OnBeforeTestRun trigger may also initialize logging variables. For example, the following code initializes a logging variable and returns true to indicate that the test function should execute. This example requires that you create the following global variable.

TestCu-8

  • (optional) Do the following steps to create an OnAfterTestRun trigger:
    • On the View menu, choose C/AL Globals.
    • In the C/AL Globals window, on the Functions tab, on a new line in the Name field, enter OnAfterTestRun, and then choose Locals.
    • In the C/AL Locals window, on the Parameters tab, enter the following.

TestCu-9

    • Close the C/AL Locals window.
    • In the C/AL Editor, in the OnAfterTestRun trigger, enter code that executes after each test function. For example, the following code logs the results of the tests to the test reporting system. This example requires that you create a record variable named log.

TestCu-10

TestCu-11

log.INIT;

log.UnitId := CodeunitId;

log.Unit := CodeunitName;

log.Func := FunctionName;

log.Before := Before;

log.After := CURRENTDATETIME;

If Success THEN

log.Status := log.Status::Success

ELSE BEGIN

log.Status := log.Status::Failure;

IF FunctionName <> ” THEN

log.Message := GETLASTERRORTEXT;

END

log.INSERT(true);

Note

If you implement the OnAfterTestRun trigger, then it suppresses the automatic display of the results message after the test codeunit runs.

  • On the File menu, choose Save.
  • In the Save As window, in the ID field, enter an ID and in the Name field, enter a name for the codeunit. Verify that the Compiled check box is selected, and then choose OK.

For more details see also below posts:

Creating a Test Codeunit and Test Function
Adding a Test to a Test Runner Codeunit

Development Tips

Creating a Test Codeunit and Test Function

Let’s creates the test function, which tests the Purch-Calc.Discount functionality, to this test codeunit.

To create the test codeunit and test function

  • In the development environment, on the Tools menu, choose Object Designer.
  • In Object Designer, choose Codeunit, and then choose New.
  • On the View menu, choose Properties.
  • In the Properties window, in the Subtype field, select Test to specify that this is a test codeunit.
  • On the View menu, choose C/AL Globals.
  • In the C/AL Globals window, on the Functions tab, enter CalculateVendorDiscount. This is the name of the test function.

TestCU-1

Note
By default, functions that you add to test codeunits have the FunctionType property set to Test.
  • On the Functions tab, choose Locals.
  • In the C/AL Locals window, on the Variables tab, enter the following variables, which you will use in the CalculateVendorDiscount test function.

TestCU-2

Important

Be sure to create these variables on the Variables tab, not on the Parameters tab. If you create them on the Parameters tab, then you get an error when you compile that says the test method signature is invalid

  • In the C/AL Locals window, on the Text Constants tab, in the Name field, enter VendorDiscountError. In the ConstValue field, enter Vendor Discount Error – Line Amount: %1, Discount: %2, Discount Amount: %3.

TestCU-3

  • Close the C/AL Locals window and the C/AL Globals window.
  • In the C/AL Editor, in the CalculateVendorDiscount function, enter the following code.

TestCU-4

You can copy above code from below:

Discount := RANDOM(99) + 1; // Set Discount > 0, <= 100

// Find purchase line.

PurchaseLine.SETFILTER(“Line Amount”, ‘>0’);

PurchaseLine.SETFILTER(“Allow Invoice Disc.”, ‘=%1’, TRUE);

IF NOT (PurchaseLine.FINDFIRST) THEN

ERROR(‘No Purchase Line found for the Calculate Vendor Discount test’);

// Create vendor discount.

WITH PurchaseLine DO BEGIN

IF NOT (VendorDiscount.GET(“Buy-from Vendor No.”, “Currency Code”, “Line Amount”)) THEN BEGIN

VendorDiscount.INIT;

VendorDiscount.Code := “Buy-from Vendor No.”;

VendorDiscount.VALIDATE(“Currency Code”,”Currency Code”);

VendorDiscount.VALIDATE(“Minimum Amount”,”Line Amount”);

VendorDiscount.INSERT(TRUE);

END;

END;

VendorDiscount.VALIDATE(“Discount %”, Discount);

VendorDiscount.MODIFY(TRUE);

// Run codeunit “Purch.-Calc.Discount” for calculating discount.

PurchCalcDisc.RUN(PurchaseLine);

PurchaseLine.GET(PurchaseLine.”Document Type”,PurchaseLine.”Document No.”,PurchaseLine.”Line No.”);

// Validate purchase discount amount

WITH PurchaseLine DO BEGIN

IF NOT (ROUND(“Line Amount” * Discount / 100) = “Inv. Discount Amount”) THEN

ERROR(VendorDiscountError, “Line Amount”, Discount, “Inv. Discount Amount” );

END;

The code in this test function prepares the test data by setting a random discount amount, getting a record from the Purchase Line table that satisfies two filters, and creating a record in the Vendor Invoice Disc. table with the random discount amount.

Next, it runs the Purch-Calc.Discount codeunit, which contains the code that is being tested. Finally, it validates the results of running the Purch-Calc.Discount codeunit and raises an error if the results are not as expected.

Note

This test code does not guarantee that the state of the database after you run the test is the same as the state of the database before you run the test.

  • On the File menu, choose Save.
  • In the Save As window, in the ID field, enter ID. In the Name field, enter TestVendorDiscount. Verify that the Compiled check box is selected, and then choose the OK button.

Now create additional test functions in the TestVendorDiscount test codeunit to test other aspects of vendor discounts.

These test functions should include negative tests, which validate that the code being tested works as intended under failing conditions.

For more details See below posts:

Creating a Test Runner Codeunit
Adding a Test to a Test Runner Codeunit

Development Tips

Defining Action Scope for Microsoft Dynamics NAV Pages – in Navision 2015

When developing pages for Microsoft Dynamics NAV Tablet client that include a repeater control, it is useful to be able to define whether the actions available on a page apply to the whole page or are related to the repeater control on the page. The purpose of the Scope property is to enable application developers to add row-specific actions to the shortcut menu which is available to the user on each line. This gives users a more direct way to invoke actions that relate to the selected row/line.

This is the case when you have, for example, Line Comments which are related to a line, but appear in the ribbon. You can specify the scope of action by setting the Scope property on the page action to be either Page or Repeater.

Specifies the scope of the action to be either page-specific, or specific to a repeater control. The Scope property has two options; Page and Repeater.

The Scope property is only used on pages that include a repeater control and it offers a way to determine the scope of an action to be the page or to be specific to the repeater control. The default behaviour of the Scope property is Page.

Let’s see how to do the same:

  • Open a Page which have repeaters for example I am using Page 42 Sales Order.

ScopeProperty

  • Select View Page Action.
  • Select the Action for which you wish to change the Scope Property, for example I have selected the Statistics for demo purpose.

The Scope property has the following effect:

  • On a Microsoft Dynamics NAV Windows client, the Scope property has no effect. All actions are shown in the ribbon.
  • On a Microsoft Dynamics NAV Web client, if the Scope property is set to Page, the action will be shown in the ribbon. If the Scope property is set to Repeater the action will be shown in both the repeater control and in the ribbon.
  • On a Microsoft Dynamics NAV Tablet client, if the Scope property is set to Page the action will be shown in the page action menu. If the Scope property is set to Repeater, the action is moved from the page action menu to the repeater control shortcut menu.
Development Tips

Creating File Attachment to Mail for Report

We generally get requirements from clients to send report output as attachment to the mail.

In Microsoft Dynamics Navision 2015 this feature is available at most of the places, but we can design for other earlier versions too.

Long-time back I was having this requirement from one of my client, those days I scanned lots of website and tried lots of method. This one I found compact and easy to use. Their after whenever I get similar requirements I prefer using this.

Today I wish to share the same with others, as I have used it in my several implementations and found it working perfect and tested with several clients.

Let’s see this, it could help someone getting his work done in easy way and can save lots of time from hit and try with several methods.

First step, I will create a function which will help us generating the file on Service tier and down load to local temporary folder, so that we can easily access and attach to our mail.

Let’s give it a meaningful name like: DownloadToClientFileName

I will define two parameters for this Function as below:

Var Name DataType Subtype Length
No ServerFileName Text 250
No ToFile Text 250

I will define Return Value of Function as: Text of Length 250

I will define Local Variables for Function as below:

Name DataType Subtype Length
ClientFileName Text 250
objScript Automation ‘Microsoft Script Control 1.0’.ScriptControl
CR Text 1

Now we will write Code for the Function as below:

ClientFileName := ToFile;

IF NOT DOWNLOAD(ServerFileName, ”, ‘<TEMP>’,”, ClientFileName) THEN

EXIT(”);

IF CREATE(objScript,TRUE,TRUE) THEN

BEGIN

CR := ‘ ‘; CR[1] := 13;

objScript.Language := ‘VBScript’;

objScript.AddCode(

‘function RenameTempFile(fromFile, toFile)’+CR+

‘set fso = createobject(“Scripting.FileSystemObject”)’+CR+

‘set x = createobject(“Scriptlet.TypeLib”)’+CR+

‘path = fso.getparentfoldername(fromFile)’+CR+

‘toPath = path+”\”+left(x.GUID,38)’+CR+

‘fso.CreateFolder toPath’+CR+

‘fso.MoveFile fromFile, toPath+”\”+toFile’+CR+

‘RenameTempFile = toPath’+CR+

‘end function’);

ClientFileName := objScript.Eval(‘RenameTempFile(“‘+ClientFileName+'”,”‘+ToFile+'”)’);

ClientFileName := ClientFileName+’\’+ToFile;

END;

EXIT(ClientFileName);

Second Step, I will write code to call this function to attach the file to Mail and send using SMTP as below:

//SMTP is an Variable of Codeunit SMTP Mail

SMTP.CreateMessage(SenderName,SenderAddress,Recipient,Subject,Body,TRUE);

//SenderName,SenderAddress,Recipent is an email addresses

SMTP.AppendBody(Body);

CLEAR(MailReport);

//MailReport is Variable for Report of which output we want to use as attachment.

//Name & ToFile is Text type variable of Length 250

Name := STRSUBSTNO(‘Estimate No. %1.pdf’, SalesHeader.”No.”);

//Creating File Name

ToFile := Name;

FileName := TEMPORARYPATH + ToFile;

//We are using temporarypath OS Variable to get the path for file

MailReport.SetMailFilters(SalesHeader);

MailReport.SAVEASPDF(FileName);

ToFile := DownloadToClientFileName(FileName, ToFile);

SMTP.AddAttachment(ToFile);

FILE.ERASE(FileName);

SMTP.Send;

Now you can create a template function and use where ever require.

Development Tips

UpdatePropagation Property

Sets a value that specifies what happens when a main page with a subpage is updated.

The UpdatePropagation property is available on part controls and has two options; Subpage and Both.

If UpdatePropagation is set to Subpage, an update action will update the subpage only.

If UpdatePropagation is set to Both, an update action will update both the main page and the subpage.

This is useful if a value on the subpage changes, and you want a main page total to be refreshed automatically.

Use the UpdatePropagation property to update a main page total, when the amount on the subpage lines is updated. Add a CurrPage.UPDATE(); call, for example, in the OnValidate trigger on the subpage to have the UpdatePropagation property take effect.

Let’s do it practically how it works:

I am taking Sales Order for demo of above property.

Let’s start with adding a field in Sales Header Table
UpdatePropagation-1

I have added Total Line Amount as Flow field to Sum Line Amount from Lines.

Next I will add this field to Sales Order Page.
UpdatePropagation-2

If we run now and make changes in Lines the Total Line amount will not update until we refresh the Page. To enable auto refresh we will be required to add Update Propagation Property of the Subpage to Both.
UpdatePropagation-3

After doing this if I make any changes which changes the Line Amount for the lines, The Total Line Amount in Header will get updated automatically, we will not require to refresh the page.
UpdatePropagation-4

We are done, so simple.