You are on page 1of 48

Chapter 8: C/AL Functions

CHAPTER 8: C/AL FUNCTIONS


Objectives
The objectives are: Understand the concepts of functions and parameters. Review several built-in functions in the C/AL Symbol Menu. Use the DATE2DMY function in a codeunit. Test knowledge on functions and parameters. Describe the use and syntax of essential C/AL functions. Describe the use and syntax of user communications functions. Describe the use and syntax of string functions. Describe the use and syntax of system functions. Describe the use and syntax of date functions. Describe the use and syntax of number functions. Describe the use and syntax of array functions. Describe the use and syntax of several other important functions. Provide an overview of benefits from creating custom functions. Describe aspects of parameters to consider when creating custom functions. Understand the concepts of local functions and local variables. Create custom functions in a page and call the functions from Actions.

Introduction
Sometimes the exact code must be run from different locations. Other times similar code with different variable values must be run from different locations. Writing these codes in a function when they need to be called from different locations not only saves developers' time in development, but also eases developers' tasks in managing and debugging the code. C/SIDE provides many built-in functions in C/AL. These functions can be used in most parts of the application without defining them. They are predefined to achieve certain tasks, such as perform string operations, retrieve a system date, and so on. Understanding C/AL built-in functions and creating custom functions completes developers' skills to build custom application in C/SIDE.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-1

C/SIDE Introduction in Microsoft Dynamics NAV 2009

Functions and Parameters


Functions are a fundamental programming element. A function is a named part of a program, also known as a subprogram or subroutine, because, when code that is running reaches a function, the main application is paused while the function code is handled.

Functions
When the function name, which is known as the identifier, is used, the current program is suspended and the trigger code for the specified function is executed. Using the identifier in this manner "calls" the function. When the trigger code in the called function is completed, the function "returns" to where it is called from. How the function is called determines what happens when it returns. A function can be used as an expression. For example, the following code uses a function named CalculatePrice as an expression:
TotalCost := Quantity * CalculatePrice;

The CalculatePrice function must return a value that is used in evaluating the expression. This return value is then multiplied by the Quantity variable and that result is assigned to the TotalCost variable. A function can also be called by using a function call statement. This statement only calls the function and does not return any value. The following is an example of calling a function named RunFunction:
IF Quantity > 5 THEN RunFunction;

The RunFunction returns no data back to the calling trigger.

Parameter
A parameter is one or more variables or expressions sent to the function through the function call. The parameter provides information to the function, and the function can modify that information. If a function has parameters, the function identifier has a set of parentheses that follows it. Within these parentheses are one or more parameters. If there is more than one parameter, the parameters are separated by commas.

8-2

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


Pass by Value
When a parameter is passed to a function strictly to give information to the function, the parameter is said to be passed by value. The parameter knows only the value of the variable or expression that is used for the parameter. Because it is only a value, any change that the function does to this parameter does not affect any variables in the calling trigger.

Pass by Reference
When a parameter is passed to the function and the function modifies that parameter, the parameter is said to be passed by reference. The parameter knows the variable's location in the computer memory, and it passes the computer memory location to the new function. Any changes that the function makes to this kind of parameter are permanent and affect variables in the calling trigger. If a parameter is passed by value, any expression can be used for that parameter. However, if a parameter is passed by reference, a variable must be used for that parameter so that its value can be changed. A variable has a location in memory, whereas an expression or a constant does not.

Built-in Function
A built-in function is a function that is provided within C/SIDE. Its trigger code cannot be viewed, because it is built into C/SIDE. The following table describes some built-in functions: Function Name MESSAGE MAXSTRLEN COPYSTR CLEAR ARRAYLEN Description Displays a message on the screen. Returns the defined length of a string variable. Returns a part of a string. Clears the passed in variable. Returns the number of elements in an array.

Functions such as MESSAGE and CLEAR, have no return value. They can only be called by using a function call statement. Functions such as COPYSTR and MAXSTRLEN return a value, and they can be used in an expression. The CLEAR function changes the passed in parameter. It is an example of pass by reference, whereas the other functions are examples of pass by value.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-3

C/SIDE Introduction in Microsoft Dynamics NAV 2009

Review Built-in Functions


The C/AL Symbol Menu is a useful tool to review available variables and functions in the current scope of the trigger. It also shows the built-in functions available to developers, together with their syntax.

The C/AL Symbol Menu


The following steps show how to open the C/AL Symbol Menu. 1. In the Object Designer's Codeunit List, click the New button. 2. Click the first line under the OnRun trigger, and then click View, C/AL Symbol Menu. 3. Click through the elements in the left column, and view what functions are displayed.

FIGURE 8.1 THE C/AL SYMBOL MENU

8-4

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


The MESSAGE Function
The following steps show how to review the MESSAGE function in the C/AL Symbol Menu. 1. In the left column of the C/AL Symbol Menu, click the DIALOG element to view some built-in functions that are listed. 2. In the right side column, click the MESSAGE function.

FIGURE 8.2 THE MESSAGE FUNCTION IN THE C/AL SYMBOL MENU

The syntax of the MESSAGE function is displayed at the bottom of the frame, above the command buttons in the C/AL Symbol Menu window. The MESSAGE function has the following syntax:
MESSAGE(String [, Value1] )

The syntax tells the following: There is no return value. There is one mandatory parameter (String.) There are multiple optional parameters (the square brackets indicate an optional parameter and the ellipsis indicates multiples.)

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-5

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The ERROR Function
The following steps show how to review the ERROR function in the C/AL Symbol Menu. 1. In the left column of the C/AL Symbol Menu, click the DIALOG element. 2. In the right side column, click the ERROR function.

FIGURE 8.3 THE ERROR FUNCTION IN THE C/AL SYMBOL MENU

The syntax of the ERROR function is displayed. It has the following syntax:
ERROR(String [, Value1] )

The syntax of the ERROR function is identical to that of the MESSAGE function, except for the function identifier and the functionality. When an ERROR function is called in a function call statement, the processing stops with an error condition and the message is displayed in a similar manner as the MESSAGE function.

The DATE2DMY Function


The following steps show how to review the DATE2DMY function in the C/AL Symbol Menu. 1. In the left column of the C/AL Symbol Menu, click the SYSTEM element. The middle column lists various function groupings, such as string functions, numeric (mathematical) functions, and so on. Depending on the selection in the middle column, the right side column shows different functions.

8-6

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


2. In the middle column, click the Date group, and in the right side column, click the DATE2DMY function.

FIGURE 8.4 THE DATE2DMY FUNCTION IN THE C/AL SYMBOL MENU

The syntax of the DATE2DMY function is displayed. It has the following syntax:
Number := DATE2DMY(Date, What)

The syntax tells the following: The function has a return value, that is a number, indicated by the 'Number :=' right before the function identifier. The first parameter (Date) is an expression of type Date. The second parameter (What) is described in more detail in the online Help.

3. Press F1. The online Help opens and displays information for the DATE2DMY function. A complete description of what the function does and what it returns is shown. The What parameter is an integer expression that resolves to one of three values: If it is a 1, this function returns the day of the month. If it is a 2, this function returns the month (from 1 to 12). If it is a 3, this function returns the year (the full 4 digits).

4. Close the codeunit without saving it.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-7

C/SIDE Introduction in Microsoft Dynamics NAV 2009

Demonstration: Use the DATE2DMY Function


The following demonstration shows how to use the DATE2DMY function. 1. Create a new codeunit, and save it as codeunit 90003, My Codeunit 4. 2. Define the following global variables: Name When Was It Description DataType Date Text 30 Length

3. Type the following code in the OnRun trigger:


"When Was It" := TODAY; CASE DATE2DMY("When Was It",2) OF 1:Description := 'January'; 2:Description := 'February'; 3:Description := 'March'; 4:Description := 'April'; 5:Description := 'May'; 6:Description := 'June'; 7:Description := 'July'; 8:Description := 'August'; 9:Description := 'September'; 10:Description := 'October'; 11:Description := 'November'; 12:Description := 'December'; END; MESSAGE('%1 is in %2',"When Was It",Description);

4. Compile, save, and close the codeunit. The first line in the code uses the TODAY function. This function has no parameters. It always returns the current date from the client's computer operating system, also known as the system date. 5. Run the codeunit and examine the result.

8-8

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions

Test Your Knowledge


The questions on this self-test relate to the following code. Hand-execute this code to determine the answers. Use the C/AL Symbol Menu and online Help to determine what the various functions do. All these functions can be found in the String group of the SYSTEM element. Do not actually run this code in the test codeunit until reaching question seven.
// UserInput is a Text variable of length 100. The other variables are Integers. UserInput := 'The colors are red, orange, yellow, green, blue and violet.'; Count := 0; REPEAT Comma := STRPOS(UserInput,','); //Q1 IF Comma > 0 THEN BEGIN //Q2 Count := Count + 1; UserInput := DELSTR(UserInput,Comma,1); //Q3 UserInput := COPYSTR(INSSTR(UserInput, ' and',Comma),1,MAXSTRLEN(UserInput)); END; UNTIL Comma <= 0; // Display Results MESSAGE('The sentence is "%1". Number of commas is %2.',UserInput,Count); EXIT(Qty * Unit);

1. What is the value of Comma after the statement labeled Q1 is executed the first time? 2. Is the value of Comma ever less than zero in this code (refer to the statement labeled Q2)? 3. What is the value of UserInput after the statement labeled Q3 is executed the first time? 4. What is the value of Count when the comment line is reached the first time? 5. Suppose that UserInput is redefined so that it is a Text of length 60. Now, what is its value when the MESSAGE function after the comment line is reached?

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-9

C/SIDE Introduction in Microsoft Dynamics NAV 2009


6. The end of the sentence can be lost under these circumstances. Modify the UNTIL clause of the REPEAT statement so that it looks as follows:
UNTIL (Comma <= 0) OR (STRLEN(UserInput) + 3 > MAXSTRLEN(UserInput));

Although better, this is not the result desired. Why did it not work? 7. Run this code in a codeunit. Do not forget to define the variables. Make the simplest change possible to address the problem uncovered in question seven. Write down the changes.

Essential C/AL Functions


Although there are more than 100 C/AL built-in functions in C/SIDE, developers only use several of these functions repeatedly and the rest of the functions occasionally. Approximately 20 different functions are used most frequently during basic application development. This does not mean that the rest of the C/AL functions are obsolete or never used. It means that becoming comfortable with this set of essential functions can help new developers in C/AL programming. Those who have to add more specialized functionality to their applications can familiarize themselves with the full set of functions.

Searching for Records


The functions in this group are used to search for records. When searching for records, remember the difference between GET and FIND - and how to use FIND and NEXT together.

GET
The GET function retrieves one record, based on the value of the primary key. For example, if the No. field is the primary key of the Customer table, the GET function can be used as follows:
GET(Customer,'4711');

The result is that the record of customer no. 4711 is retrieved. The GET function produces a run-time error if it fails, and the return value is not inspected by the code. The code can look as follows:
IF GET(Customer,'4711') THEN .... // do some processing ELSE .... // do some error processing

8-10

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


The GET function searches for records, regardless of current filters, and it does not change any filters. It always searches among all records in a table.

FIND
The differences between the GET function and the FIND function are as follows: The FIND function respects (and is limited by) the current setting of filters. The FIND function can be instructed to look for records where the key value is equal to, larger than, or smaller than the search string. The FIND function can find the first or the last record, given the sorting order defined by the current key.

These features can be used in various ways. When developing applications under a relational database management system, developers frequently have one-tomany relationships between tables. An example is the relations between the Item table that records items, and the Sales Line table that records the detail lines from Sales Orders. A record in the Sales Line table can only be related to one item. But each item can be related to any number of sales line records. An item record in the Item table must not be deleted while there are still open Sales Orders that include the item. The following code sample can be put in the OnDelete trigger of the Item table, and shows how to check for this condition:
SalesOrderLine.SETCURRENTKEY("Document Type",Type,"No."); SalesOrderLine.SETRANGE("Document Type",SalesOrderLine."Document Type"::Order); SalesOrderLine.SETRANGE(Type,SalesOrderLine.Type::Item); SalesOrderLine.SETRANGE("No.","No."); IF SalesOrderLine.FIND('-') THEN ERROR('You cannot delete because there are one or more outstanding sales orders that include this item.');

FINDFIRST, FINDLAST and FINDSET


To find the first record in a table, depending on the current key and filter, use the FINDFIRST function. The FINDFIRST function must be used instead of FIND('-') when only the first record is needed. To find the last record in a table, depending on the current key and filter, use the FINDLAST function. The FINDLAST function must be used instead of FIND('+') when only the last record is needed. To find a set of records in a table, depending on the current key and filter, use the FINDSET function. The FINDSET function must be used when developers want to loop through a recordset, in combination with REPEAT...UNTIL. It only lets to loop the recordset from the top down. To loop from the bottom up, use FIND('+') instead.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-11

C/SIDE Introduction in Microsoft Dynamics NAV 2009


NEXT
The NEXT function is frequently used with FIND and FINDSET to step through records of a table. The following code sample shows how to use the NEXT function:
FINDSET; REPEAT // process record UNTIL NEXT = 0;

The FINDSET function is used to locate the first record of the table. Afterward, the NEXT function is used to step through every record, until there are no more (then, NEXT returns zero.)

Sorting and Filtering Records


The functions in this group are used to filter records in a table so that only a subset of the records are displayed, modified, or deleted. Other functions can be used to change the sorting of the records in a table. The following functions are related to sorting and filtering: SETCURRENTKEY SETRANGE SETFILTER GETRANGEMIN GETRANGEMAX

SETCURRENTKEY
The SETCURRENTKEY function is used to select a key for a record. This sets the sorting order used for the associated table. It has the following syntax:
[Ok :=] Record.SETCURRENTKEY(Field1, [Field2],...)

Some characteristics of the SETCURRENTKEY function are as follows: Inactive fields are ignored. When searching for a key, C/SIDE selects the first occurrence of the specified field(s).

For example, even if a developer specifies only one field as a parameter when calling SETCURRENTKEY, the key that is actually selected may consist of more fields.

8-12

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


If no keys can be found that include the specified field or fields, a run-time error occurs unless the Boolean return value of SETCURRENTKEY is handled in the code. If a developer handles the return value, the developer has to decide what the program must do if the function returns FALSE, because without the run-time error, the program continues to run even though no matching key is found.

SETRANGE
The SETRANGE function is used to set a delimitation on a field. It sets a simple filter. It has the following syntax:
Record.SETRANGE(Field [,From-Value] [,To-Value]);

The following code sample shows how to use the SETRANGE function:
Customer.SETRANGE("No.",'10000','90000');

This limits the Customer table by selecting only those records where the No. field has a value between 10000 and 90000. The SETRANGE function removes previous filters. If it is used without the From-Value or To-Value parameters, the function can be used to remove any filters that might already be set. If only the From-Value parameter is used, the To-Value parameter is set to the same value as the From-Value parameter.

SETFILTER
The SETFILTER function sets a filter in a more general way than SETRANGE. It has the following syntax:
Record.SETFILTER(Field, String [, Value], ...];

The Field parameter is the name of the field to set a delimitation on. The String parameter is a filter expression that can contain operators and placeholders such as %1, %2 and so on to indicate locations where the system inserts values given as the Value parameters. The following code sample shows how to use the SETFILTER function:
Customer.SETFILTER("No.", '>10000 & <> 20000');

This code selects records where the No. is larger than 10000 and not equal to 20000. The following code sample performs the same thing as the previous one, if the variable Value1 is assigned 10000 and Value2 is assigned 20000:
Customer.SETFILTER("No.",'>%1&<>%2',Value1, Value2);

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-13

C/SIDE Introduction in Microsoft Dynamics NAV 2009


GETRANGEMIN
The GETRANGEMIN function retrieves the minimum value of the delimitation currently in effect for a field. It has the following syntax:
Record.GETRANGEMIN(Field);

The GETRANGEMIN function causes a run-time error if the filter currently in effect is not a range. For example, if a filter is set as follows:
Customer.SETFILTER("No.",'10000|20000|30000');

Then the following fails, because the filter is not a range:


BottomValue := Customer.GETRANGEMIN("No.");

GETRANGEMAX
The GETRANGEMAX function works like the GETRANGEMIN function, except that it retrieves the maximum value of the delimitation currently in effect.

Inserting, Modifying, and Deleting Records


The functions in this group are used to maintain the database by adding, modifying, and removing records. Generally, these functions return a Boolean value that indicates whether they have succeeded or not. If developers do not handle the return value in their code, a run-time error occurs when a function returns as FALSE. If developers handle the return value, they have to decide what the program must do if the function returns as FALSE. The following functions are related to inserting, modifying, and deleting: INSERT MODIFY MODIFYALL DELETE DELETEALL

INSERT
The INSERT function inserts a record in a table. The following code sample shows how to use the INSERT function:
Customer.INIT; Customer."No." := '4711'; Customer.Name := 'John Doe'; Customer.INSERT;

8-14

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


This code inserts a new record, with the No. and Name having the assigned values, whereas the other fields have their default values. Supposing that No. is the primary key of the Customer table, the record is inserted in the Customer table unless there already is a record in the table with the same primary key. In that case, since the return value is not handled, a run-time error occurs.

MODIFY
The MODIFY function is used to modify an existing record. Similar to the INSERT function, it returns a Boolean value (TRUE if the record to be modified exists and FALSE otherwise.) The following code sample shows how to use the MODIFY function:
Customer.GET('4711'); Customer.Name := 'Richard Roe'; Customer.MODIFY;

The code changes the name of customer 4711 to Richard Roe.

MODIFYALL
The MODIFYALL function is used to do a bulk update of records. It respects the current filters, meaning that developers can perform the update on a specified set of records in a table. The MODIFYALL function does not return any value, nor does it cause an error if the set of records to be changed is empty. The following code sample shows how to use the MODIFYALL function:
Customer.SETRANGE("Salesperson Code",'PS','PS'); Customer.MODIFYALL("Salesperson Code",'JR');

The SETRANGE statement selects the records where the Salesperson Code is PS, and the MODIFYALL function changes these records to have the Salesperson Code set to JR.

DELETE
The DELETE function is used to delete a record from the database. The record to be deleted must be specified, by using the values in the primary key fields, before calling the function. The DELETE function takes filters into consideration. The DELETE function returns a Boolean value (TRUE if the record to be deleted exists and FALSE otherwise.) The following code sample shows how to use the DELETE function:
Customer."No." := '4711'; Customer.DELETE;

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-15

C/SIDE Introduction in Microsoft Dynamics NAV 2009


DELETEALL
The DELETEALL function is used to delete all records that are selected by the filter settings. If no filters are set, all records in the table are deleted. The following code sample shows how to use the DELETEALL function to delete all records where the Salesperson Code is PS from the Customer table:
Customer.SETRANGE("Salesperson Code", 'PS', 'PS'); Customer.DELETEALL;

Transactions
Usually, developers do not have to be concerned about transactions and table locking when they develop applications in C/SIDE. There are some situations where developers must lock a table explicitly. For example, if developers inspect data in a table at the beginning of a function, and then use this data to perform various checks and calculations, and finally want to write-back a record, based on the result of this processing, they want the values that are retrieved at the beginning to be consistent with the data in the table now. In short, other users must not be able to update the table while the function is busy doing its calculations.

LOCKTABLE
The solution to keeping others from using a table that is making calculations is to lock the table manually, at the beginning of the function, by using the LOCKTABLE function.

Working with Fields


The following functions perform actions on fields: CALCFIELDS CALCSUMS FIELDERROR FIELDNAME INIT TESTFIELD VALIDATE

CALCFIELDS
The CALCFIELDS function is used to update FlowFields. FlowFields are automatically updated when they are used as direct source expressions of controls. However, they must be explicitly calculated when they are not. That is, when they are part of a more complex expression.

8-16

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


When using FlowFields in C/AL functions, they must be updated, and this is what the CALCFIELDS function is used for. The following code sample shows how to use the SETRANGE function to set a filter and the CALCFIELDS to update the FlowFields.
SETRANGE("Date Filter",0D,TODAY); CALCFIELDS(Balance,"Balance Due");

The CALCFIELDS function calculates the Balance and Balance Due fields by taking account of filter setting and calculations that are defined as the CalcFormula properties of the FlowFields.

CALCSUMS
The CALCSUMS function is used to calculate the sum of one or more fields that are SumIndexFields in the record. For the CALCSUMS function to work, a key that contains the SumIndexFields must be selected as the current key. Similar to the CALCFIELDS function, the CALCSUMS function takes the current filter settings into account when performing the calculation. The following code sample shows the selection of the appropriate key, the filters setting, and the summation.
SETCURRENTKEY("Customer No."); SETRANGE("Customer No.",'10000','50000'); SETRANGE(Date,0D,TODAY); CALCSUMS(Amount);

FIELDERROR
The FIELDERROR function triggers a run-time error after displaying a fieldrelated error message. This function is similar to the ERROR function, but it is easier to use and has some benefits. Most importantly, if the name of a field is changed, for example, translated to another language in the Table Designer, the message from the FIELDERROR function reflects the current name of the field. The following code sample shows how to use the FIELDERROR function:
Item.GET('70000'); IF Class <> 'HARDWARE' THEN FIELDERROR(Class);

This causes an appropriate message to be displayed, depending on whether Class currently is empty or has a value.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-17

C/SIDE Introduction in Microsoft Dynamics NAV 2009


Custom text can be added if the default text does not suit the application. The following code sample shows how to use the FIELDERROR function with a custom text:
IF Class < '4711' THEN FIELDERROR(Class,'must be greater than 4711');

FIELDNAME
The FIELDNAME function returns the name of a field. By using the FIELDNAME function, messages that are created are still meaningful even if the field name is later changed. The FIELDNAME function can be used together with the FIELDERROR function. The following code sample shows this construction:
FIELDERROR(Quantity,'must not be less than ' + FIELDNAME("Quantity Shipped"));

INIT
The INIT function initializes a record. If a default value for a field is defined, by the InitValue property, this value is used for the initialization; otherwise, the default value of each data type is used. The INIT function does not initialize the fields of the primary key.

TESTFIELD
The TESTFIELD function is used to test a field against a value. If the values are not the same, the test fails, an error message is displayed, and a run-time error is triggered. This means that any changes made to the record are discarded. If the value to test against is the empty string, the field has to have a value other than blank or zero. The following code sample shows how to use the TESTFIELD function to generate an error message:
Code := 'DK' TESTFIELD(Code,'ZX');

VALIDATE
The VALIDATE function is used to call the OnValidate trigger of a field. The following code sample shows how to use the VALIDATE function to call the OnValidate trigger of the Total Amount field:
VALIDATE("Total Amount");

8-18

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


The VALIDATE function is useful for centralizing processing. It makes applications easier to maintain. Suppose that the OnValidate trigger of the Total Amount field performs a calculation with values from three other fields as operands. If the contents of any of these fields changes, the calculation must be performed. Avoid entering the calculation formula in the OnValidate triggers of every field because there are many possibilities for errors if the calculation formula must be changed later. Instead, perform the calculation in the OnValidate trigger in only one of the fields, and call this trigger code from the OnValidate triggers of the other fields by using the VALIDATE function.

User Communication Functions


The following functions give users feedback and an opportunity to input information into the program: MESSAGE CONFIRM STRMENU ERROR

MESSAGE
The MESSAGE function has the following syntax:
MESSAGE (String [, Value1, ...])

The MESSAGE function is frequently used for debugging, such as displaying values of variables. However, if an error occurs, the process stops and the message is not displayed, because it is run non-modally. If there is no error, the MESSAGE function displays a message to the user, only after the process is completed. The message window remains open until the user clicks the OK button (or presses the ENTER key). Several characters are used for special purposes in the String parameter. The plus character (+) is used to concatenate text. The backslash character (\) is used to start a new line. The % and # symbols can be used as variable placeholders. The percent symbol is used for free format and the pound symbol is for fixed formats.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-19

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The following code sample shows how to use the MESSAGE function:
Value1 := 12345.678; Value2 := 987.65; MESSAGE('The Free Format of Value1 is %1 \' + 'The Fixed Format of Value2 is #2#########', Value1, Value2);

When this code is run, the result is as follows:

FIGURE 8.5 THE MESSAGE FUNCTION

CONFIRM
The CONFIRM function has the following syntax:
CONFIRM (String [, Default] [, Value1, ...])

The CONFIRM function is similar to the MESSAGE function. It displays a message to the user. The difference is that the CONFIRM function enables the user to answer a question by clicking the Yes or No button and returns a Boolean value (TRUE or FALSE), that corresponds to the user's selection. The CONFIRM function is run modally. Therefore, the system waits for the user's response. The CONFIRM function is frequently used to confirm that the user wants to continue with a process. Microsoft Dynamics NAV uses the CONFIRM functions before posting records. The user is given an opportunity to stop the posting process or to continue. The Default parameter specifies the default button in the message window. If it is FALSE, the No button is set as the default button and is active. If the user only presses ENTER, the function returns a FALSE. If the Default parameter is TRUE, the Yes button is set as the default button instead. The following code sample shows how to use the CONFIRM function:
IF NOT CONFIRM('Do you want to post the Journal Lines?') THEN EXIT; // Otherwise run the posting routine.

8-20

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


When this code is run, the result is as follows:

FIGURE 8.6 THE CONFIRM FUNCTION

The CONFIRM function responses are limited to Yes and No. If other responses are needed, use the STRMENU function.

STRMENU
The STRMENU function has the following syntax:
STRMENU (OptionString [, DefaultNumber])

The STRMENU is used to create and display a menu window with an option group. It returns an integer value of the user's selection. If the DefaultNumber parameter is not set, the first element in the option string is defaulted as the choice, with a value of one. A zero value is returned if ESC is pressed. This indicates no choice by the user. The following code sample shows how to use the STRMENU function:
MESSAGE('Your selection returns the value of %1', STRMENU('Yes, No, N/A'));

When this code is run, the result is as follows:

FIGURE 8.7 THE STRMENU FUNCTION

ERROR
The ERROR function has the following syntax:
ERROR(String [, Value1, ...])

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-21

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The ERROR function raises an error condition and leaves the current process, canceling the whole process, not only the function. If the code is in a transaction, the transaction is stopped and all uncommitted data is rolled back. The ERROR function displays an error message to the user that informs the user why additional processing is not allowed. The String parameter specifies this error message. The following example uses the ERROR function:
Number := -1; IF Number <= 0 THEN BEGIN ERROR('Number must be positive. Current value: %1.', Number); MESSAGE('This Message is never displayed'); END;

When this code is run, the result is as follows:

FIGURE 8.8 THE ERROR FUNCTION

String Functions
The following functions enable the developer to manipulate strings: STRPOS COPYSTR PADSTR, STRLEN, MAXSTRLEN LOWERCASE and UPPERCASE CONVERTSTR DELCHR INCSTR SELECTSTR STRCHECKSUM

STRPOS
The following example uses the STRPOS function:
Position := STRPOS(String, SubString)

8-22

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


This function is used to search for the first occurrence of a substring in a string. It returns the position of the first character of the substring within the string. If the substring is not found within the string, the function returns a zero. As with all string functions, the STRPOS function is case-sensitive.

COPYSTR
The COPYSTR function has the following syntax:
NewString := COPYSTR(String, Position [, Length])

This function is used to copy a substring of any length from a specific position in a string to a new string. If the Length parameter is omitted, the result includes all characters from Position to the end of the string.

PADSTR
The PADSTR function has the following syntax:
NewString := PADSTR(String, Length [, FillCharacter])

This function is used to change the length of a string to another length. If the Length parameter is smaller than the actual length of the string, the string is truncated. Otherwise, it adds the filler characters to the end of the string. If the FillCharacter parameter is omitted, then blanks are added.

DELSTR and INSSTR


There are two other functions similar to PADSTR function. They are as follows: The DELSTR function which is used to delete a substring from a string. The INSSTR function which is used to insert a substring into a string at a specified position.

These functions have the following syntax:


NewString := DELSTR(String, Position [, Length]) NewString := INSSTR(String, SubString, Position)

STRLEN
The STRLEN function has the following syntax:
Length := STRLEN(String)

This function returns an integer that is the length of the string in the parameter.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-23

C/SIDE Introduction in Microsoft Dynamics NAV 2009


MAXSTRLEN
The MAXSTRLEN function has the following syntax:
MaxLength := MAXSTLEN(String)

Similar to the STRLEN function, the MAXSTRLEN function also returns an integer. However, that integer represents the maximum length defined for that string variable.

LOWERCASE and UPPERCASE


The LOWERCASE and UPPERCASE functions have the following syntax:
NewString := LOWERCASE(String), NewString := UPPERCASE(String)

They convert a string to an all lower-case or upper-case string, respectively.

CONVERTSTR
The CONVERTSTR function has the following syntax:
NewString := CONVERTSTR(String, FromCharacters, ToCharacters)

This function converts the characters in a string, depending on the characters in the strings FromCharacter and ToCharacters parameters that serve as conversion tables.

DELCHR
The DELCHR function has the following syntax:
NewString := DELCHR(String [, Where] [, Which])

This function is used to delete one or more characters in a string. It can delete characters from either end of the string or all instances throughout the string. This function can be used to trim strings of blanks as follows:
DELCHR(StringVar, '<>', ' ');

INCSTR
The INCSTR function has the following syntax:
NewString := INCRSTR(String)

8-24

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


This function is used to increase a positive number or decrease a negative number inside a string by one (1). If there is more than one number in a string, it changes the first number.

SELECTSTR
The SELECTSTR function has the following syntax:
NewString := SELECTSTR(Number, CommaString)

This function retrieves a substring from a comma-separated string. The substrings are numbered starting with one.

STRCHECKSUM
The STRCHECKSUM function has the following syntax:
CheckNumber := STRCHECKSUM(String [,WeightString] [, Modulus])

This function is used for various different applications such as bar codes. It calculates a checksum for a string that contains a number.

System Functions
System functions do not require any parameters because they return information that is stored in the system. They include the following: USERID COMPANYNAME TODAY and TIME WORKDATE GETLASTERRORTEXT and CLEARLASTERROR APPLICATIONPATH TEMPORARYPATH

USERID
The following code sample shows how to use the USERID function:
Name := USERID;

This function returns the ID of the current user.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-25

C/SIDE Introduction in Microsoft Dynamics NAV 2009


COMPANYNAME
The following code sample shows how to use the COMPANYNAME function:
Name := COMPANYNAME;

This function returns the current company that is used by the Microsoft Dynamics NAV client.

TODAY and TIME


The following code sample shows how to use the TODAY and TIME functions:
DateVar := TODAY; TimeVar := TIME;

These functions return the operating system's date and time.

WORKDATE
The WORKDATE function has the following syntax:
[WorkDate] := WORKDATE([NewDate])

This function returns the current work date or can be used to set the work date. However, according to Microsoft Dynamics NAV standard, the work date must not be changed by code.

GETLASTERRORTEXT and CLEARLASTERROR


The GETLASTERRORTEXT function returns the standard error text presented in an error dialog window. The function returns the last error text. If no error has occurred, it returns an empty string. The returned string cannot exceed 1024 characters. This is the maximum string length in Microsoft Dynamics NAV. The CLEARLASTERROR function clears any previous error text so that the next calls to GETLASTERRORTEXT returns an empty string.

APPLICATIONPATH
In some cases, the application must know where the Microsoft Dynamics NAV client is installed on the hard disk. For example, the application might have to read files that are installed with Microsoft Dynamics NAV, such as company setup templates or the End-User License Agreement. The APPLICATIONPATH function returns a string specifying the installation directory, ending with a backslash ("\") and without the executable file. The string cannot exceed 255 characters.

8-26

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


The following code sample shows how to use the APPLICATIONPATH function to display the path of the End-User License Agreement:
StrPath := APPLICATIONPATH + 'EULA.rtf'; MESSAGE(StrPath);

The run time system interprets backslashes as line feeds. Therefore, assuming that Microsoft Dynamics NAV is installed in the default location, the result is as follows:

FIGURE 8.9 THE APPLICATIONPATH FUNCTION

TEMPORARYPATH
The TEMPORARYPATH function returns the name of the folder where temporary files are created. The TEMPORARYPATH function returns the path and not a file name, so developers can determine the name of the temporary file that is created in the temporary folder. The tradeoff is that there is no guarantee that the name of the file is unique. Temporary files that are created in the temporary folder through the TEMPORARYPATH function are not deleted automatically when they are closed. The following code sample shows how to use the TEMPORARYPATH function:
TempName := TEMPORARYPATH + 'AppTemplate.HTM'; FileCreated := TempFile.CREATE(TempName); IF FileCreated THEN MESSAGE('created file: ' + TempName) ELSE MESSAGE('failed to create file');

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-27

C/SIDE Introduction in Microsoft Dynamics NAV 2009


When this code is run, the result is as follows:

FIGURE 8.10 THE TEMPORARYPATH FUNCTION

Date Functions
The following functions provide specific information about a given date: DATE2DMY DATE2DWY CALCDATE NORMALDATE CLOSINGDATE

DATE2DMY
The DATE2DMY has the following syntax:
IntegerVar := DATE2DMY(Date, Integer)

This function returns information about the Date parameter, depending on the Integer parameter. Integer value 1 2 3 Usage Returns the day of the month (1-31) Returns the month (1-12) Returns the year (0001-9999)

8-28

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


DATE2DWY
The DATE2DWY has the following syntax:
IntegerVar := DATE2DWY(Date, Integer)

This function also returns information about the Date parameter, depending on the Integer parameter. Integer value 1 2 3 Usage Returns the day of the week (1-7), where day 1 is Monday Returns the week of the year (1-53) Returns the year (0001-9999)

CALCDATE
The CALCDATE function has the following syntax:
CALCDATE(DateExpression [, Date])

The CALCDATE function is a powerful function. It calculates a new date based on a date expression and a reference date. The following are some examples of a date expression: Date Expression CQ + 1M - 10D -WD2 CM + 30D Usage Last Day of Current Quarter + 1 Month - 10 Days Last second Day of the Week, (last Tuesday) Last Day of Current Month + 30 Days

The following code sample shows how to use the CALCDATE function:
CALCDATE('CM +15D', 030502D);

In this code sample, the CALCDATE function starts with March 5, 2002 as the reference date and goes to the last day of that current month (CM). This brings the calculation to 03/31/02. Then it adds 15 days that results in April 15, 2002. The date expression can be of any length. It must have at least one subexpression. The system interprets the string from left to right, one sub-expression at a time. The sub-expression is either a positive or negative Term value.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-29

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The Term value can be a combination of the following: Number-Unit Unit-Number Prefix-Unit

The Number is a positive integer. The Unit can be one of the following: Term D WD W M Q P Y Definition Date WeekDay Week Month Quarter Period Year

There is one Prefix, C, that represents the closing date of that period. The closing date for a quarter represents 11:59:59 PM of the last day of the last month in the quarter. Every date, from 01/03/0001 to 12/31/9999 has a corresponding normal date and closing date, used for closing journal entries. To the system, a closing date represents 11:59:59 PM of that date. Closing dates are sorted immediately after the corresponding normal date, but before the next normal date. The letter D indicates a normal date, and C indicates a closing date. The NORMALDATE and CLOSINGDATE functions determine which type of date is being used.

NORMALDATE
The NORMALDATE function has the following syntax:
ReturnDate := NORMALDATE(Date)

This function returns the corresponding normal date of a date. A common location to view this function is in the posting routines. For example, posting dates or invoice dates must be normal dates. The following code sample ensures that only normal dates are posted, by using the NORMALDATE function:
IF "Posting Date" <> NORMALDATE("Posting Date") THEN ERROR('Posting Date cannot be a closing date');

8-30

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


CLOSINGDATE
The CLOSINGDATE function has the following syntax:
ReturnDate := CLOSINGDATE(Date)

This function is the opposite of the NORMALDATE function. It returns the corresponding closing date of a date.

Number Functions
The majority of number functions are rarely used, except for the ROUND function. The ROUND function is used very frequently when dealing with currency and tax. The number functions include the following: ABS POWER ROUND RANDOMIZE RANDOM

ABS
The ABS function has the following syntax:
NewNumber := ABS(Number)

This function returns the absolute value of the number.

POWER
The POWER function has the following syntax:
NewNumber := POWER(Number, Power)

This function raises the Number parameter to the Power parameter. It can also be used to calculate roots. For example, to calculate the square root of 16, use POWER(16, 0.5) which returns 4.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-31

C/SIDE Introduction in Microsoft Dynamics NAV 2009


ROUND
The ROUND function has the following syntax:
NewNumber := ROUND(Number [,Precision] [, Direction])

This function returns a rounded number. The Precision parameter specifies the precision used when rounding off. The default value is .01, although the settings in the General Ledger Setup affect this. The Direction parameter specifies how to round and has the following options: Direction Parameter = < > Rounding Direction Rounds to the nearest value (default) Rounds down Rounds up

RANDOMIZE
The RANDOMIZE function has the following syntax:
Randomize([Seed])

This function generates a set of random numbers. The Seed parameter is an optional integer value that is used to create a unique set of numbers. The same seed number results in the same set. If the Seed parameter is omitted, the total number of milliseconds since midnight is calculated for the current system time and is used as the seed.

RANDOM
The RANDOM function has the following syntax:
Number := RANDOM(MaxNumber)

This function returns a pseudo-random number between 1 and MaxNumber by using the random number set from the RANDOMIZE function. Until the RANDOMIZE is called again, the RANDOM function chooses a number from the same set of numbers.

Array Functions
Arrays are often used in reports for address and label information. The array functions include the following: ARRAYLEN

8-32

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


COMPRESSARRAY COPYARRAY

ARRAYLEN
The ARRAYLEN function has the following syntax:
Length := ARRAYLEN(Array [, Dimension])

This function returns the total number of elements in an array or the number of elements in a specific dimension of the array. A three-dimensional array has valid dimensions of one, two, and three. If the Dimension parameter is omitted, the return value represents the number of elements in the whole array, and not any dimension.

COMPRESSARRAY
The COMPRESSARRAY function has the following syntax:
[Count :=] COMPRESSARRAY(StringArray)

This function is only useful for text or code arrays. It moves all the non-empty strings of the array to the beginning of the array. The array contains the same number of elements. The empty entries and those that contain only blanks appear at the end of the array. If a return value is handled, it represents the number of non-empty strings the system compressed. A good example of how to use this function is when printing names and addresses. This function is useful to remove blank lines in account statements or from multiline addresses.

COPYARRAY
The COPYARRAY function has the following syntax:
COPYARRAY(NewArray, Array, Position [, Length])

This function copies one or more elements from an array to a new array. The Position parameter specifies the position of the first array element to copy, whereas the optional Length parameter specifies the number of array elements to copy. If the Length parameter is omitted, all array elements from Position to the last element are copied. The COPYARRAY function is only used for onedimensional arrays. It can be used repeatedly to copy more dimensions.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-33

C/SIDE Introduction in Microsoft Dynamics NAV 2009

Other Functions
The following functions are several other important functions that are used throughout Microsoft Dynamics NAV: EXIT CLEAR CLEARALL EVALUATE FORMAT

EXIT
The EXIT function has the following syntax:
EXIT (Value)

This function leaves the current function or trigger immediately. If there is a parent function that calls this current function or trigger, the Value parameter of the EXIT function is returned to the calling function. The EXIT function causes no error condition nor does it roll back any data. The following code sample shows how to use the EXIT function:
Function AddTen (Number : Integer) : Integer BEGIN EXIT(Number + 10); MESSAGE('This line is never read.'); END;

CLEAR
The CLEAR function has the following syntax:
CLEAR(Variable)

This function clears the value of a single variable, or all elements of an array, to the following: Variable Type Number String Date Time Boolean Number Clearing Result 0 (zero) Empty string 0D (undefined date) 0T (undefined time) FALSE 0 (zero)

8-34

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


CLEARALL
The CLEARALL function clears all internal variables in the current object and in any called objects such as reports, and units of code, that contain C/AL code. It works by calling CLEAR repeatedly for each variable. The CLEARALL function has no parameter. When an object is called repeatedly within the same process, the system retains all values for variables and filters in memory between calls. The CLEARALL function clears all of these.

EVALUATE
The EVALUATE function has the following syntax:
[Ok :=] EVALUATE(Variable, String[, Number])

This function converts a string expression into another appropriate data type. The result is assigned to the Variable parameter.

FORMAT
The FORMAT function has the following syntax:
String := FORMAT(Value [, Length] [, FormatNumber | FormatString])

This is a powerful function. At the basic level, it can convert any type of variable to a string variable. The following code sample shows how to use the FORMAT function to convert a decimal variable to a string:
TextVar := FORMAT(DecimalVar);

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-35

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The Length parameter is an integer value that ensures that if the value is larger than the maximum length that the String allows for, a run-time error does not occur. Length value 0 >0 Usage The system returns the whole value. This is the default. Returned string is exactly Length characters. If Value is less than Length characters, either leading or trailing spaces are inserted, depending on the format that is selected. <0 If Value is an integer that exceeds Length digits, Length asterisks are placed in String. If Value is not an integer and it exceeds Length characters, String is truncated accordingly.

Returned string will have the maximum length of Length characters. If Value is less than Length characters, the length of String will equal the length of Value. If Value is an integer that exceeds Length digits, Length asterisks are placed in String. If Value is not an integer and it exceeds Length characters, String is truncated accordingly.

Only one of the next two parameters is used at any time. The FormatNumber parameter specifies the format the system uses. The basic options are as follows: Format Number value 0 1 2 Usage Standard Display Format (the default for all data types) Standard Display Format 2 (edit) C/AL Code Constant Format

Other options are available depending on the data type. The FormatString parameter is a literal string that specifies a format as in the Format property. The Format property describes the various predefined formats in detail, and how to create customized formats. The following code sample shows how to use the FORMAT function:
MESSAGE('The formatted value: %1', FORMAT(-123456.78, 15, 0));

8-36

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


When this code is run, the message window displays the message:

FIGURE 8.11 THE FORMAT FUNCTION MESSAGE('The formatted value: %1', FORMAT(-123456.78, 5, 3)); // Changed Length to 5

When this code is run, the message window displays the following message:

FIGURE 8.12 THE FORMAT FUNCTION MESSAGE('Today is %1', FORMAT(TODAY,0,'<Month Text> <Day>.'));

When this code is run, the message window displays the following message:

FIGURE 8.13 THE FORMAT FUNCTION

Sometimes, negative numbers must be displayed as strings enclosed in parentheses instead of being preceded by a minus sign (-). If these numbers are part of a vertical list of numbers, usually a trailing space must be added at the end of the positive numbers (so that the negative numbers enclosed in parentheses are aligned with the positive numbers).

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-37

C/SIDE Introduction in Microsoft Dynamics NAV 2009


The following code sample shows how to use the FORMAT function to achieve this:
DecimalVar := -1234.56; IF DecimalVar < 0 THEN BEGIN StringVar := FORMAT(DecimalVar, 0, '(<Integer Thousand><decimals>)'); MESSAGE(StringVar); END ELSE BEGIN StringVar := FORMAT(DecimalVar, 0, '<Integer Thousand><decimals> '); MESSAGE(StringVar); END;

The < and > signs are part of the FormatString parameter. For the negative numbers, the parenthesis is inside the single quotation marks. For the positive values, there is a space before the last single quotation mark for alignment. When this code is run, the message window displays the following message:

FIGURE 8.14 THE FORMAT FUNCTION

Create Custom Functions


Creating custom functions helps make code more efficient. This includes adding, removing, or editing code one time in a function that is used several times in an application, and the change is applied in every instance of the function.

Reasons to Create Custom Functions


Some reasons to create custom functions include the following: To organize the program. A function is to code what the headings are to a well-organized written document. They make the program easier to follow, not only for the original developer, but also for other developers who may have to modify the code later. To simplify developers tasks. When designing a program, developers can break a complex problem into multiple smaller tasks. Each of these tasks can become a function in the program and the whole program can be built from these smaller tasks. If a function proves to be too complex, developers can do the same thing again: break it apart into smaller tasks and create a new function for each task.

8-38

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


To make code reusable, reducing work. If exactly the same thing or very similar things are done in two separate parts of a program, consider creating a function to do that task. Then, instead of writing the same or similar code in two or three locations, write it in one location and call it from other locations. To reduce the possibility of errors. A function can be tested thoroughly by itself. Therefore, when it is used in another location, it is a known quantity; when developers are searching for errors, they can reduce the search. Similarly, if an error is found in a function, it can be fixed in one place and it is automatically fixed in all the locations that called that function. If developers have to fix it in each location, they might forget one or add another bug. To make modifications easier. If developers have to modify the way a program works and they have similar code in many locations, their modifications must be made to each of those locations. If the common code is put in a function, developers can make modifications to one location and every other location that uses that function is updated also. This reduces work and reduces the possibility of introducing more errors. To localize data. When a function performs a task, it can have its own local data that cannot be tampered with by other functions in the same object. Similarly, by using its own local data, it does not tamper with data that is owned by other functions. If global variables are used by many tasks throughout the program, there is a good chance that this data can become corrupted. To reduce the size of the objects. Although a minor consideration, it can be worthwhile, especially when trying to locate something in the code.

There are many good reasons to create functions. In fact, when designing code for an object, the first thing to do is determine the major tasks and create, or define, a function for each one. Then, as similar things are organized in different locations, consider adding another function to handle that task. Another reason to create functions, which is specific to C/SIDE, is that functions are one of the main ways to communicate between objects. Variables cannot be shared across objects, but functions can.

Formal and Actual Parameters


It is important to understand the underlying elements for a function. Understanding the concepts of formal and actual parameters helps with the choices involved in creating a custom function.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-39

C/SIDE Introduction in Microsoft Dynamics NAV 2009


Formal Parameter
The formal parameter is defined in the function definition. For example, the DELSTR function has the following syntax:
NewString := DELSTR(String, Position [, Length])

The words that appear in parentheses are the formal parameters.

Actual Parameter
The actual parameter is used when the function is called. The following example shows an example of calling the DELSTR function:
UserInput := DELSTR(UserInput,Comma,1);

The constant and variables that appear in the parentheses are the actual parameters. There is a one-to-one correspondence between the actual parameters and the formal parameters. The actual parameter UserInput becomes the formal parameter String, the actual parameter Comma becomes the formal parameter Position and the actual parameter 1 becomes the formal parameter Length. Because this code uses a pass-by value for all three parameters, what is actually being passed to the function are the values of the three actual parameters. Therefore, the actual parameters are not changed when the formal parameters are changed inside the function. If the code uses a pass-by reference instead, it passes the variable references (memory addresses) to the function. Then the actual parameters are changed if the corresponding formal parameters are changed inside the function. Because constants cannot be changed, 1 cannot be used as an actual parameter if Length is passed by reference.

Local Functions, Variables and the EXIT Statement


Some functions and variables have a limited scope. They can only be used in the location where they are defined.

Local Function
A local function is a function that can only be called in the object in which it is defined. Any function that is not defined as a local function can be called from other objects and from the object in which it is defined.

8-40

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


Local Variable
A local variable is a variable that scope is limited to a single function. This means that in the particular function trigger code, a local variable can be used like any other variable. However, throughout the rest of the object, this variable cannot be accessed. If the name of a local variable is referred to outside the function in which it is defined, a syntax error occurs. The formal parameters of a function are also treated as local variables in that function.

The EXIT Statement


The EXIT statement is used to stop the execution of a trigger. It can be used for function triggers also. However, in functions, the EXIT statement has an additional use. When a function call is used in an expression, the function is required to return a value. When writing a function that has a return value, signal to the system to return a value by using the EXIT statement. The EXIT statement has the following syntax:
EXIT(<expression>);

For example, create a function named SQUARE that is used to square a value. The following expression results in the Answer variable being assigned the value 29.
Answer := 4 + Square(5);

The SQUARE function trigger code can be written as follows, if the formal parameter is named Param:
EXIT(Param * Param);

The EXIT statement's parameter is the expression that squared the parameter and that is what the function returns to its caller.

Demonstration: Create Custom Functions


The following demonstration shows how to create custom functions and add actions that calls the functions, in a page.

Set the Page


Instead of creating a new page from scratch, design page 90006, Test Statements and save it as a new page. 1. Design page 90006, Test Statements, from the Object Designer. 2. Compile and save it as page 90008, Test Functions Page.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-41

C/SIDE Introduction in Microsoft Dynamics NAV 2009


Create a Custom Function
The following steps show how to create a custom function in a page. 1. Click View, C/AL Globals. 2. Click the Functions tab. This is where developers define custom functions. 3. Type Accumulate in the Name column. This is the name of the first custom function. 4. Click View, Properties, to open the Properties window for the Accumulate function. 5. Set the Local property to Yes. This sets the function to a local function. This function can only be called within the page itself and not from any object outside this page. 6. Close the Properties window. 7. In the C/AL Globals window, click the Locals button. The Accumulate - C/AL Locals window opens. This window is used to complete the definition of the Accumulate function. The four tabs at the top of this window indicate that developers can set the formal Parameters, the Return Value, Local Variables and Text Constants for the function. 8. Type the following in the Parameters tab: Name Qty DataType Integer

The column named Var, an abbreviation for Variable, is used to set this parameter to be passed by reference. A parameter that is passed by reference must be a variable, not an expression. In this case, do not select this column. 9. Close the Accumulate - C/AL Locals window to return to the C/AL Globals window. The definition of the Accumulate function is now completed.

Create another Custom Function


The following steps show how to create another custom function in a page. 1. In the Functions tab of the C/AL Globals window, type Extend in the Name column. This is the name of the second custom function. 2. Set its Local property to Yes. 3. Click the Locals button and create two parameters: o Qty of type Integer o Unit of type Decimal

8-42

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


4. Click the Return Value tab on the C/AL Locals window. 5. Click the Return Type drop-down arrow, and select Decimal. This sets decimal as the return type for this function. 6. Close the C/AL Locals window and close the C/AL Globals window. The definition of the Extend function is now completed.

Add Code to the Functions


The following steps show how to add the code to the function trigger. 1. In the Page Designer, click View, C/AL Code to open the C/AL Editor. 2. Type the following code into the Accumulate function trigger:
Result := Extend(Qty,UnitPrice); IF Result < 0 THEN BEGIN TotalCredits := TotalCredits + Result; TotalQtyCredits := TotalQtyCredits + Qty; END ELSE BEGIN TotalSales := TotalSales + Result; TotalQtySales := TotalQtySales + Qty; END; GrandTotal := GrandTotal + Result; GrandQtyTotal := GrandQtyTotal + Qty;

3. Type the following code into the Extend function trigger:


EXIT(Qty * Unit);

4. Close the C/AL Editor.

Call the Function from an Action


The following steps show how to add an action that calls the custom function. 1. Open the Action Designer for the page. 2. Go to the last line and type the following to add an action. Ensure that it is indented under the ActionItems ActionContainer. Caption Execute Sale Type Action

3. Click View, C/AL Code to open the C/AL Editor.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-43

C/SIDE Introduction in Microsoft Dynamics NAV 2009


4. Locate the OnAction trigger for the Execute Sale action. 5. Type the following code into the OnAction trigger of the action:
IF Quantity = 0 THEN EXIT; Accumulate(Quantity);

6. Close the C/AL Editor.

Call the Function from another Action


One of the assets of having a function is that for similar code, developers do not have to write the code multiple times. The following steps show how to add another action that calls the same custom function, but with different actual parameter. 1. Still in the Action Designer, go to the last line and type the following to add another action. Ensure that it is indented under the ActionItems ActionContainer. Caption Type

Execute Credit Action 2. Click View, C/AL Code to open the C/AL Editor. 3. Locate the OnAction trigger for the Execute Credit action. 4. Type the following code into the OnAction trigger of the action:
IF Quantity = 0 THEN EXIT; Accumulate(-Quantity);

The code in both actions is similar. The only difference is that the Execute Credit action changes the Quantity to negative before calling the functions. This means that users no longer enter negative quantities, instead, they only enter quantities, and then click either the Execute Sale or the Execute Credit action, depending on what kind of transaction it is. 5. Close the C/AL Editor and close the Action Designer. 6. Open the Properties window for the Quantity field control, and set the MinValue property to be 0 (zero). 7. Close the Properties window 8. Compile, save and close the page.

8-44

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions


Test the Page
The following steps show how to test the page by running the action and viewing the result. 1. Run page 90008, Test Functions Page. 2. Type a value into the Unit Price and Quantity text box, and then click the Execute Sale action. Observe what happens. 3. Type another value into the Quantity text box, and then click the Execute Credit action again. Observe what happens. 4. Try entering a negative value in the Quantity text box (for example 4) and observe what happens.

Summary
C/SIDE provides many built-in functions that can be used by developers. These built-in functions are predefined with their syntax. C/SIDE also lets developers create custom functions, to extend their application. Understanding the concepts of functions, when to use built-in functions and when to create custom functions helps developers to efficiently develop custom solutions for Microsoft Dynamics NAV.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-45

C/SIDE Introduction in Microsoft Dynamics NAV 2009

Test Your Knowledge


In the Object Designer, locate codeunit 358, DateFilter-Calc. Design this codeunit, and answer the following questions by looking at this object. Remember, if a question is about the Function Definition, it is best to examine the Function tab in the C/AL Globals window, and at the C/AL Locals window. If a question is about the code, it is best to examine the trigger code. 1. How many Parameters does the CreateFiscalYearFilter function have? 2. What type of value (if any) is returned by the CreateAccountingPeriodFilter function? 3. In the CreateAccountingDateFilter function, is the first parameter (Filter) passed by value or passed by reference? 4. In the CreateAccountingDateFilter function, is the third parameter (FiscalYear) passed by value or passed by reference? 5. In the CreateAccountingDateFilter function, how many local variables are defined?

8-46

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

Chapter 8: C/AL Functions

Quick Interaction: Lessons Learned


Take a moment and write down three key points you have learned from this chapter 1.

2.

3.

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement

8-47

C/SIDE Introduction in Microsoft Dynamics NAV 2009

8-48

Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement