AL control statements
Note
We're working on improving the onboarding experience for AL developers. If you've input for this article, we'd love to hear from you. Please use the Feedback section at the bottom of this article to help us make improvements that you’d like to see.
We also welcome contributions to our docs. New to contributing to docs? Don't worry, read more about contributing here Contribute to the help.
AL code consists of one or more statements, which are executed sequentially in a top-down order. However, you'll often need to control the direct top-down flow of the execution. One or more statements may have to be repeated more than once, or you may have to make the execution of a certain statement conditional. To do so, you use control structures.
The control structures in AL are divided into the following main groups, as described in this article:
Note
In the following sections, conventions for how to structure and align AL code are presented to introduce best practices. In many cases, the structure isn't necessary to get the code to compile, but rather to improve readability.
AL compound statements
In some cases, the AL syntax only lets you use a single statement. However, if you have to run more than one simple statements, the statements can be written as a compound statement by enclosing the them between the begin
and end
keywords.
begin
<Statement 1>;
<Statement 2>;
..
<Statement n>;
end;
The individual statements are separated by a semicolon. In AL, a semicolon is used to separate statements and not to terminate them, as in other programming languages. Nevertheless, an extra semicolon before an end doesn't cause an error because it's interpreted by the compiler as an empty statement.
Blocks
The begin-end structure is also called a block. Blocks can be useful to refer to the other control structures in AL.
When begin follows, then, else, or do should be on the same line and preceded by one space character.
Example 1
if (x = y) and (a = b) then begin
x := a;
y := b;
end;
Example 2
if (xxx = yyyyyyyyyy) and
(aaaaaaaaaa = bbb)
then begin
x := a;
x := y;
a := y;
end else begin
y := x;
y := a;
end;
AL conditional statements
You use conditional statements to specify a condition and one or more commands to execute if the condition is evaluated as true or false. There are two types of conditional statements in AL:
- if-then-else, where there are two choices
- case, where there are more than two choices
If-then-else statements
if-then-else statements have the following syntax.
if <Condition> then
<Statement1>
[else
<Statement2>]
If <Condition>
is true, then <Statement1>
is executed. If <Condition>
is false, then <Statement2>
is executed.
The square brackets around else <Statement2>
mean that this part of the statement is optional. The else statement is used when different actions are executed depending on how <Condition>
is evaluated.
You can build more complex control structures by nesting if-then-else statements. The following example is a typical if-then-else statement.
if <Condition1> then
if <Condition2> then
<Statement1>
else
<Statement2>
If <Condition1>
is false, then nothing is executed. If <Condition1>
and <Condition2>
are both true, then <Statement1>
is executed. If <Condition1>
is true and <Condition2>
is false, then <Statement2>
is executed.
Note
A semicolon in front of an else statement is not allowed.
Reading several nested if-then-else statements can be confusing but generally, an else statement belongs to the last if statement that lacks an else statement.
Programming conventions
if
andthen
should be on the same line,else
should be on a separate line.If there are many or long expressions,
then
should be on a new line and be aligned withif
.When you write
if
expressions withthen
andelse
parts, write them so that thethen
result is more probable than theelse
one.If the last statement in the
then
part of anif-then-else
statement is anexit
or anerror
, don't continue with anelse
statement.
Example
if x = y then
x := x + 1
else
x := -x - 1;
Example
if (xxxxxxxxxx = yyy) and
(aaa = bbbbbbbbbb)
then
x := a
else
y := b;
Example
if x <> y then
exit(true);
x := x * 2;
y := y - 1;
Incorrect example
if x < y then
exit(true)
else begin
x := x * 2;
y := y - 1;
end;
Example
The following example shows an if-then statement without the optional else statement.
if Amount < 1000 then
Total := Total + Amount;
Example
The following example shows a nested if-then-else statement.
...
if Amount < 1000 then begin
if I > J then
Max := I
else
Max := J;
Amount := Amount * Max;
end;
else
...
Case statements
Case statements have the following syntax.
case <Expression> of
<Value set 1>:
<Statement 1>;
<Value set 2>:
<Statement 2>;
<Value set n>:
<Statement n>;
[else
<Statement n+1>]
end;
In this definition, the result of <Expression>
is matched against each value set and <Value set>
must be an expression or a range.
Note
<Expression>
cannot be an application object variable, since application objects don't have a comparator.
Case statements are also called multiple option statements and are typically used when you must choose between more than two different actions. The method of the case statement is as follows:
The
<Expression>
is evaluated, and the first matching value set executes the associated statement, if there's one.If no value set matches the value of the expression and the optional else part has been omitted, then no action is taken. If the optional else part is used, then the associated statement is executed.
The data type of the value sets must be the same as the data type of <Expression>
or at least be convertible to the same data type.
In most cases, the data type of the value sets is converted to the data type of the evaluated expression. The only exception is if the evaluated expression is a Code variable. If the evaluated expression is a Code variable, then the value sets aren't converted to the Code data type.
Note
This type conversion can cause an overflow at run time if the resulting data type cannot hold the values of the datasets.
For more information about Code variables, see Code Data Type.
Programming conventions
When you use a case statement, indent the value sets by four character spaces. If you've two or more value sets on the same line, then separate them by commas without spaces. The last value set on a line is immediately followed by a colon without a preceding space. The action starts on the line after the value set and is further indented by four character spaces. If there's a begin, then it should be put on a separate line unless it follows else. If a begin follows an else, then it should be on the same line as else.
If there are more than two alternatives, use a case statement. Otherwise, use an if-then-else statement.
Example
case Field of
Field::A:
begin
x := x + 1;
y := -y - 1;
end;
Field::B:
x := y;
Field::C,Field::D:
y := x;
else begin
y := x;
a := b;
end;
end;
Example
The following AL code prints various messages depending on the value of Number. If the value of Number doesn't match any of the entries in the case structure, then the else entry is used as the default.
case Number of
1,2,9:
message('1, 2, or 9.');
10..100:
message('In the range from 10 to 100.');
else
message('Neither 1, 2, 9, nor in the range from 10 to 100.');
end;
Example
The following AL code shows how value sets in a case
statement are evaluated if the expression is a Code data type.
MyCode := 'ABC';
case MyCode of
'abc':
message('This message is not displayed.');
'def':
message('This message is not displayed.');
else
message('The value set does not match the expression.');
end;
This example requires that you create the following code data type variable.
var
MyCode : Code[10];
The value set 'abc' isn't converted because the evaluated expression MyCode is a code variable.
AL repetitive statements
A repetitive statement is also known as a loop. The following table shows the looping mechanisms in AL.
Looping mechanism | Description |
---|---|
for | Repeats the inner statement until a counter variable equals the maximum or minimum value specified. |
foreach | Repeats the inner statement for each statement in a List, XmlNodeList, XmlAttributeCollection, or JsonArray. |
while | Repeats the inner statement as long as the specified condition is true. The statement in a loop of this kind is repeated zero or more times. |
repeat | Repeats the inner statements until the specified conditions evaluate to true. The statements in a loop of this kind are always executed at least one time. |
For-to and for-downto control structure
The following syntax shows the for-to and for-downto statement.
for <Control Variable> := <Start Number> to <End Number> do
<Statement>
for <Control Variable> := <Start Number> downto <End Number> do
<Statement>
The data type of <Control Variable>
, <Start Number>
, and <End Number>
must be Boolean, number, time, or date.
Use for-to
and for-downto
statements when you want to execute code for a specific number of times. The <Control Variable> controls the number of times that the code of the inner statement is executed according to the following:
In a
for-to
loop statement, the<Control Variable>
value is increased by one after each iteration. The inner<Statement>
is executed repeatedly until the*<Start Number>
* value is greater than the*<End Number>*
value.In a
for-downto
loop statement, the<Control Variable>
value is decreased by one after each iteration. The inner<Statement>
is executed repeatedly until the<Start Number>
value is less than the<End Number>
value.
Note
When the for statement is executed, <Start Number>
and <End Number>
are converted to the same data type as <Control Variable>
if it's required. This type conversion can cause a run-time error.
Note
If the value of the <Control Variable>
is changed inside the for loop, then the behavior is not predictable. Furthermore, the value of the <Control Variable>
is undefined outside the scope of the for loop.
Example 1
The following code initiates a for loop that uses the integer control variable named Count.
for Count := 1000 to 100000000000000 do
This example requires the following Integer data type variable.
var
Count : Integer;
When this statement is executed, then a run-time error occurs because the start, and end values are converted to the same data type as the Count control variable. Count has been declared as an integer variable. The end number 100000000000000 is outside the valid range for integers, and an error occurs.
Example 2
The following example shows how to nest for statements.
Set the Dimensions property of variable A to 5;7.
The following for
statements could be used to initialize every element in a 5x7 array with the value 23.
for I := 1 to 5 do
for J := 1 to 7 do
A[I,J] := 23;
This example requires the following Integer data type variables.
var
I : Integer;
J : Integer;
Foreach control structure
You can use the foreach statement to iterate through List, XmlNodeList, XmlAttributeCollection, and JsonArray expressions.
Tip
With Business Central 2023 release wave 1, you can use the foreach
loop on Text
variables as well, which allows you to detect, as well as remove or replace individual characters in strings.
The foreach statement has the following syntax.
foreach <Element> in <List> do
<Statement>
The <List>
variable must be of the List, XmlNodeList, XmlAttributeCollection, or JsonArray type. The <Element>
variable must be a data type that is compatible with elements specified by the <List>
.
The following code example iterates through a list of customer names and returns each customer name in a message.
procedure PrintCustomerNames(customerNames : List of [Text])
var
customerName : Text;
begin
foreach customerName in customerNames do
message(customerName);
end;
While-do control structure
The following syntax shows the while-do statement.
while <Condition> do
<Statement>
If <Condition>
is true, then <Statement>
is executed repeatedly until <Condition>
becomes false. If <Condition>
is false from the start, then <*Statement>
is never executed.
The while do statement can be used when some code should be repeated as long as an expression is true.
Programming conventions
When there's only one condition, put while
and do
on the same line. Put the statements on separate lines and indented by two spaces.
When there are multiple conditions, put the conditions on separate lines, and indented by two spaces and put do
on a separate line that is aligned with while
.
Example
while <expr> do
<Statement>;
Example
while <expr> do begin
<Statement>;
<Statement>;
end;
Example
while <expr> and
<expr> and
<expr>
do begin
<Statement>;
<Statement>;
end;
Example
The following AL code increases the variable I until it equals 1000 and displays a message when it's finished.
while I < 1000 do
I := I + 1;
message(format(I));
This example requires the following integer data type variable.
var
I : integer
Repeat-until control structure
The following syntax shows the repeat-until statement.
repeat
<Statements> until <Condition>
<Statements>
is executed repeatedly until <Condition>
is true.
The repeat until
control structure resembles the while control structure. The difference is that because the repeat until
statement is executed from left to right, the <Statements>
is always executed at least one time, regardless of what the <Condition>
is evaluated to. This contrasts with the while
control structure, which performs the evaluation before the <Statement>
is executed. In the while
control structure, if the first evaluation of <Condition>
returns false, then no statements are executed.
Programming conventions
Always put repeat on a separate line.
Example
if x < y then begin
repeat
x := x + 1;
a := a - 1;
until x = y;
b := x;
end;
Example
This code uses a repeat-until loop to count the number of entries in the Customer table.
Count := 0;
if Customer.find('-') then
repeat
Count := Count + 1;
until Customer.next <= 0;
message('The Customer table contains %1 records.',Count);
This example requires the following variables.
var
Count : Integer;
Customer : Record Customer;
The find
method finds the first entry in the table. Each time NEXT is called, it steps one record forward. When NEXT equals 0, there are no more entries in the table. The loop is exited, and a message displays how many entries were found.
Exit statement
The exit statement is used to control the flow of the execution. The following syntax shows an exit statement.
exit([<Value>])
An exit statement is used to interrupt the execution of an AL trigger. The interruption occurs even when the code is executed inside a loop or a similar structure. The exit statement is also used when a local method should return a value.
Using exit without a parameter in a local method corresponds to using the parameter value 0. The AL method will return the value 0 or '' (empty string).
A compile-time error occurs if exit is called by using a return parameter from either:
- System-defined triggers, or
- Local methods that don't return a value.
Example
The following example shows the use of the exit statement in a local method. Assume that the if statement is used to detect an error. If the error condition is met, then execution is stopped and the local method returns the error code 1.
for I := 1 to 1000 do begin
if Amount[I] < Total[I] then
exit(1);
A[I] := Amount[I] + Total[I];
end;
Break statement
You use the break statement to terminate the iterative statement in which it appears.
break;
You typically use the break
statement in the repeating statements such as for
, while
, or repeat
to stop an iteration or loop when certain conditions are met.
Note
The break statement is different than the Break Method (Report, XMLport). Although both stop an iteration or loop, the break method will also terminate the trigger in which it's run.
Example
The following AL code increases the variable I by one for each iteration, and terminates the iteration when I
equals 10.
while Count < 1000 do
begin
Count := Count + 1;
message(FORMAT(Count));
if Count = 10 then
break;
end;
end;
This example requires the following integer data type variable.
var
I : integer
See also
Programming in AL
AL simple statements
Directives in AL
AL essential methods