Warning: number_format() expects parameter 1 to be float, string given in /data/web/virtuals/7298/virtual/www/wp-includes/functions.php on line 412

Returning complex types in AL Language

by May 23, 2021AL Language, Major

Home 9 Development 9 AL Language 9 Returning complex types in AL Language ( Page )

In Microsoft Dynamics 365 Business Central 2021 w1 (released in May 2021), a profound change was introduced to ways how we can design our applications

Until this version, the only way to return complex data types (like records, codeunits, Lists etc.) was using the var parameter (see example below).

 trigger OnRun()
 var
   SalesHeader: Record "Sales Header";
 begin
   FindSalesOrder('SO210001', SalesHeader);
   SalesHeader.TestStatusOpen();
 end;

 local procedure FindSalesOrder(OrderNo: Code[20]; var SalesHeader: Record "Sales Header")
 begin
   Clear(SalesHeader);
   SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
   SalesHeader.SetRange("No.", OrderNo);
   SalesHeader.FindFirst();
 end;

Although it allows returning any data type, working with var parameters is not as friendly as working with return parameters. For example, var parameters do not allow method chaining.

It was not possible in C/AL or AL Language. Until now!

 trigger OnRun()
 var
   SalesHeader: Record "Sales Header";
 begin
   FindSalesOrder('SO210001').TestStatusOpen();
 end;

 local procedure FindSalesOrder(OrderNo: Code[20]) SalesHeader: Record "Sales Header"
 begin
   Clear(SalesHeader);
   SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
   SalesHeader.SetRange("No.", OrderNo);
   SalesHeader.FindFirst();
 end;

With returning of complex types, we can chain methods similarly to C# (or any other modern object-oriented language) with returning of complex types.

 // With var parameter
 FindSalesOrder('SO210001', SalesHeader);
 SalesHeader.TestStatusOpen();

 // With returning complex types
 FindSalesOrder('SO210001').TestStatusOpen();

What is/isn’t possible to return

It is possible to return almost any data type.

  • Any simple type
    • Boolean, Integer, Text, Char, …
    • RecordRef, FieldRef, Variant
  • Any AL object
    • Records (Record “Sales Header”)
    • Pages (Page “Customer Card”)
    • Codeunits (Codeunit “Sales-Post”)
  • Selected DotNet objects
    • HttpClient, HttpContent, …
  • Other complex types
    • Lists (List of [Text])
    • Dictionaries (Dictionary of [Integer, Text])

The only things that are not possible to return are collections of complex types (something like List of [Records “Sales Header”]). However, it is not a limitation of return statements, but it is impossible to use collections of complex type in AL Language in general.

For this purpose, use Temporary Records instead.

Let’s chain it!

So how we can advance from method chaining in AL Language?

For example, imagine you want to work with data from the customer card for a customer from the sales header. Without chaining, the only way was to create a Customer variable and find the corresponding customer manually or using var parameter using the method in the Sales Header.

With chaining, we can use the getter method in the Sales Header that returns the customer (unfortunately, there isn’t the method yet). See the example below.

Example

Unfortunately, there aren’t any useful function in the base app yet, so the example uses methods as if they were in the base app.

I added a method procedure GetCustomer(): Record Customer to the Sales Header table and procedure GetShipToAddress(ShipToAddressCode: Code[10]): Record “Ship-to Address” to the Customer table.

 // Method in Sales Header table
 procedure GetCustomer(): Record Customer
 var
   Customer: Record Customer;
 begin
   Customer.Get(Rec."Sell-to Customer No.");
   exit(Customer);
 end;

 // Method in Customer table
 procedure GetShipToAddress(ShipToAddressCode: Code[10]): Record "Ship-to Address"
 var
   ShipToAddress: Record "Ship-to Address";
 begin
   ShipToAddress.Get(Rec."No.", ShipToAddressCode);
   exit(ShipToAddress);
 end;

Now we can get values (in our example, the value of email field) from Ship-to Address only with one line of custom code.

 procedure DoSomething(SalesHeader: Record "Sales Header")
 var
   EmailFromShipToAddressTable: Text[80];
 begin
   EmailFromShipToAddressTable := SalesHeader.GetCustomer().GetShipToAddress('ADDR-001')."E-Mail";
   Message(EmailFromShipToAddressTable);
 end;

Recent Articles from the category

Field Level Permissions (Restricted Fields)

Field Level Permissions (Restricted Fields)

I just add a new project to my GitHub repositories. It is a new extension for Business Central that extends security functionalities with field-level permission. Using this extension, users are able to define who can or can not change specific fields in any table in...

read more
How to let users choose field(s) properly

How to let users choose field(s) properly

When some complex functionality is developed, it is sometimes necessary to let users choose a specific field. This can be required for field permissions, mapping imported values or any similar process. Earlier, the usual way was to create a link on the Field table...

read more
Import various file types with Interfaces

Import various file types with Interfaces

A few weeks ago, I described a solution for importing an Excel file to the Business Central using Excel Buffer in AL Language (see here). In today's article, we will look at how to build a more complex solution that can be used for file imports without the needs to...

read more

Sign Up for News

Certifications

Highest certification
Microsoft Data Management and
also in D365 Business Central

Microsoft Certified: Dynamics 365 Business Central Functional Consultant Associate

See other certifications here