They can be separated into two main groups:
• Primitive data types
• Composite data types
Primitive data types
Primitive data types are the building blocks of the programming language. They are
used to store a single value based on the type in runtime code. The values that we
are able to store in each data type vary, depending on which data type is used. If you
would like to store a text string you can use the string data type. If you would like
to store a date value you can use the date data type, or perhaps the utcdatetime.
You can also use the data type anytype if the type of data read into the variable is
decided at runtime.
The different primitive data types available in AX are:
• String (str)
• Integer (int)
• Real (real)
• Boolean (boolean)
• Date (date)
• Enum (enum)
• TimeOfDay (timeofday)
• UtcDateTime (utcdatetime)
• Anytype (anytype)
String
The string data type is probably one of the most used data types. It is used to hold
text information, and its length can either be set while declaring the variable or it can
be dynamic. When using fixed length strings simply add the number of characters
you would like to limit the variable to between the variable type and the name of the
variable, as shown in the next example.
Also note that the variable type keyword is str and not string.
static void PrimitiveDatatypes_string(Args _args)
{
str 9 fixedLengthString;
str dynamicLengthString;
;
fixedLengthString = "Welcome to X++ Programming";
dynamicLengthString = "Welcome to X++ Programming";
print fixedLengthString;
print dynamicLengthString;
pause;
}
Note about (;) : The extra semicolon after the variable declaration is mandatory
as long as the first line of code is not a keyword. The semicolon tells the
compiler that variable declarations have come to an end. You cannot
declare new variables after this semicolon.
When working with strings there are some functions that are nice to know about,
that help you manipulate strings, search for text inside a string, and so on. These
functions can be found in the Application Object Tree (AOT) under System
Documentation\Functions and some under Classes\Global.
strfmt
This method is used to format a string and change any occurrences of %n with
parameter n.
static void PrimitiveDatatypes_string_strmft(Args _args)
{
str name;
int a;
;
name = "DynamicsAx";
a = 100;
print strfmt("%1: Welcome to %2", a, name);
pause;
}
Notice that the strfmt function also converts any other data types into string.
substr
The substr function returns a part of a string. The first parameter is the original
string, the second is the start position, and the third is the number of characters
to read.
static void PrimitiveDatatypes_string_substr(Args _args)
{
str carBrand;
;
carBrand = "Volkswagen";
print substr(carBrand, 6, 5);
pause;
}
The print command from the method will display wagen as the substring starts at
position 6 of the value of the first parameter, which is Volkswagen, and reads 5
characters ahead.
Integer
Integers are numbers without decimals. They are divided into two separate data
types in AX: the int which is a 32 bit integer, and the int64 which is a 64 bit integer.
The int data type ranges from -2,147,483,647 to 2,147,483,647. The int64 ranges from
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,808, which should be enough for
most of us.
static void PrimitiveDatatypes_integer1(Args _args)
{
int a;
int b;
;
a= 6;
b= 4;
print strfmt("Multiplication of a,b is %1", a *b);
pause;
}
Dividing two integers will result in a real number unless you are returning the value
to an integer. This means that dividing 24/4 gives the result 6.00, but returning the
result to an integer and printing it results in 6 as you will see in the next example.
static void PrimitiveDatatypes_integer2(Args _args)
{
int x = 24;
int y = 4;
int res = x/y;
;
// Prints a real value
print strfmt("%1 / %2 = %3", x, y, x/y);
// Automatically type casted to int
// to print the integer value
print strfmt("%1 / %2 = %3", x, y, res);
pause;
}
Real
A real variable can consist of decimal number and integers. It spans a range
of –(10)127 to (10)127 with a precision of 16 significant digits. It is worth
mentioning that even though your locale use comma as decimal separator
the code in AX accepts only period as comma separator.
When the code is executed, however, the print will show the decimal separator that
is set in your regional settings.
static void PrimitiveDatatypes_real1(Args _args)
{
real a;
real b;
;
a =25;
b = 5;
print strfmt("a/b value is %1",a/b);
pause;
}
str2num
If you have a string variable representing a number, you can convert the value into a
real variable by using the str2num function.
static void PrimitiveDatatypes_str2num(Args _args)
{
str nameStr;
real nameStrNum;
;
nameStr = "9999.99";
nameStrNum = str2num(nameStr);
print strfmt("The String is converted into real %1", nameStrNum);
pause;
}
num2str
You can also go the other way around by converting the value of a real variable
into a string.
static void Datatypes_num2str(Args _args)
{
str mileage;
real mileageNum;
;
mileageNum = 388272.23;
// num2str(number to be converted,
// minimum characters required,
// required number of decimals,
// decimal separator <1=point, 2=comma>,
// thousand separator <0=none, 1=point,
// 2=comma, 3=space>)
mileage = num2str(mileageNum,0,2,2,0);
print strfmt("The car has run %1 miles", mileage);
pause;
}
number === The number to convert to a text string.
character === The minimum number of characters required in the text.
decimals === The required number of decimals.
separator1 === The decimal separator.Possible values:
1 – point (.)
2 – comma (,)
separator2 === The thousands separator.Possible values:
0 – no thousands separator
1 – point (.)
2 – comma (,)
3 – space ( )
Boolean
The boolean data type is just a representation of an integer that can only have the
values 0 (false) or 1 (true).
boolean isAvailable = true;
Date
The date data type obviously holds date values. The dates are system formatted
as dd\mm\yyyy.
date birthday = 29\01\2008
The date variable can hold values from 1\1\1900 to 31\12\2154, and you can use
integers to add or subtract a date.
To get the session date set in AX you can use the systemdateget() function. The
session date in AX is automatically set to the machine date on the computer running
your AX client when you start the AX client. You can change the session date by
pressing the Dynamics AX button (Alt + M) and selecting Tools | Session Date. In
the form that opens, you can change both the session date and time. This is typically
done to post a journal as if it was posted on a different date than the actual date.
To retrieve the local machine's date, use the today() function.
Boolean
The boolean data type is just a representation of an integer that can only have the
values 0 (false) or 1 (true).
boolean isAvailable = true;
Date
The date data type obviously holds date values. The dates are system formatted
as dd\mm\yyyy.
date birthday = 29\01\2008
The date variable can hold values from 1\1\1900 to 31\12\2154, and you can use
integers to add or subtract a date.
To get the session date set in AX you can use the systemdateget() function. The
session date in AX is automatically set to the machine date on the computer running
your AX client when you start the AX client. You can change the session date by
pressing the Dynamics AX button (Alt + M) and selecting Tools | Session Date. In
the form that opens, you can change both the session date and time. This is typically
done to post a journal as if it was posted on a different date than the actual date.
To retrieve the local machine's date, use the today() function.
Enum
Enums are represented in the AOT under Data Dictionary | Base Enums. You can
use these enums in the code as a list of literals, as it is much more convenient to read
and understand than a list of integers. Each enum can have maximum 251 literals.
The first literal in an enum is indexed by the integer 0, the next one is indexed by 1,
and so on; each of these integers represent a more understandable value, as shown in
the next example.
Here, you can see how you can assign an enum value to an enum variable of
type Weekdays.
Weekdays day = Weekdays::Monday;
The value that is stored in the variable day will be the integer 1 since the enum
Weekdays also has a value 0 that represents the enum "None", but it's a lot easier
to read this code instead of the following that does the exact same thing:
Weekdays day = 1;
To get a list of all base enums while in the code editor simply press F11
enum2str
To get the label for one specific enum value, simply use the enum2str function as
shown in the next example:
static void Datatypes_enum2str(Args _args)
{
SalesType salesType; // a standard enum in Ax
;
salesType = SalesType::Sales;
//info(strfmt("The name of the current sales-type is '%1'",enum2str(salesType)));
or( both wil give same output)
info(strfmt("The name of the current sales-type is '%1'",(salesType)));
//info("The name of the current sales type is " + salesType);//u can get error
}
--Actually, in the previous example, you don't have to use the enum2str as the enum
value is automatically converted to a str as it is used in a strfmt() function.
However, trying to use the enum variable directly in the info will result in a
compilation error because you cannot add an enum variable to a string. Hence, in
this example the enum2str method would come in handy.
info("The name of the current sales type is " + salesType);
--Note that we used the info method in this example instead of the print
statement. The info method is a more user friendly way of displaying
information to the end user. It is defined as a static method in the Global
class and simply adds a new message of type info to the AX information
log. Other types that can be put into the information log (also known as
the infolog) is error and warning. Try them out by using error() and
warning() instead of info().
enum2int
In the same way that you can get the label of the enum value, you can also
get the integer that it represents by using the enum2int function.
static void Datatypes_enum2int(Args _args)
{
SalesType salesType;
;
salesType = SalesType::Sales;
info(strfmt("The value of the current sales-type element is %1",
enum2int(salesType)));
}
TimeOfDay
The variable type timeofday is an integer representing the number of seconds since
midnight. It can have values from 0 to 86400 that is stored in the database. When
used in a report or a form, it is automatically converted to values from 12:00:00 a.m.
to 11:59:59 p.m.
str2time
The str2time function converts a string representation of time to the timeofday value
as long as the string is a valid time. If it's not a valid time, the method returns -1.
static void Datatypes_str2time(Args _arg)
{
str timeStr;
timeofday time;
;
timeStr = "09:45";
time = str2Time(timeStr);
info(strfmt("%1 seconds has passed since midnight when the clock
is %2", time, timeStr));
}
Utcdatetime
The utcdatetime data type was introduced in AX 2009, and holds both date and
time information (and actually also time zone information although this is not
available in X++ code).
One of the really nice things about utcdatetime is that you can store a value in a
utcdatetime variable and have it displayed to users around the world in their local
time zone and time format.
Anytype
The anytype data type can contain any of the other primitive data types.
The type of the variable data is decided by the first value that is set for the variable.
In the next example, the any variable will work as a string variable at runtime as the
first value is a string. Since the second value is an integer it is actually converted to a
string during runtime so the print will show 33 when executing the Job.
static void Datatypes_anytype1(Args _args)
{
anytype any;
;
any = "test";
any = 33;
print any;
pause;
}
Composite data types
Composite data types are data types where each variable can consist of multiple
other variables.
The different kind of composite data types are:
• Container
• Class
• Table
• Array
Container
A container can consist of multiple values of any primitive data types mixed together.
You can store containers as fields in tables by using the container field.
Containers are immutable and adding or deleting a value in the container requires
the system to actually create a new container, copy the value before and after the
new value, and remove the deleted value.
static void Datatypes_container_functions(Args _args)
{
container con;
;
// conins - Insert values to the container
con = conins(con, 1, "Toyota");
con = conins(con, 2, 20);
con = conins(con, 3, 2200.20);
con = conins(con, 4, "BMW");
con = conins(con, 5, 12);
con = conins(con, 6, 3210.44);
// condel - Delete the third and the fourth element
// from the container
con = condel(con, 3, 2);
// conpeek - Read values from the container
info(conpeek(con,1));
info(conpeek(con,2));
info(conpeek(con,3));
info(conpeek(con,4));
// connull - Reset the container
con = connull();
// conlen - Get the length of the container
info(strfmt("Length: %1",conlen(con)));
}
Class
In order to access any data stored with an object you need to have a reference
to the memory locations where these objects are stored. This is done by using
class variables.
When you create an object of a class you also want to be able to reference that
object and the data stored with it throughout the scope where you are using the
class methods.
static void Datatypes_class_variable(Args _args)
{
// Declare a class variable from the RentalInfo class
RentalInfo rentalInfo;
;
// An object is created and referenced by the
// class variable rentalInfo
rentalInfo = new RentalInfo();
// Call methods to set/get data to/from the object
rentalInfo.setCar("BMW 320");
info(strfmt("The car is a %1", rentalInfo.getCar()));
}
The RentalInfo class is implemented like this:
public class RentalInfo
{
str car;
}
void setCar(str _car)
{
;
car = _car;
}
str getCar()
{
return car;
}
Table
A table can be used in X++ by creating a table variable.
This means that you can easily insert, update, delete, search, and perform other
actions with table data directly without creating a connection and a statement.
In the code, you can simply write a select-statement directly like in the next example.
static void Datatypes_table(Args _args)
{
CustTable custTable; // This is the table variable
CustAccount custAccount;
;
custAccount = "1000";
select Name from custTable
where custTable.AccountNum == custAccount;
info(strfmt("The name of the customer with AccountNum %1 is %2",
custAccount, custTable.Name));
}
All tables in the data dictionary are actually classes that extend the system class
Common. They can be seen as wrappers for their corresponding tables in the
database, as they have all necessary functionality needed read, create, modify, and
delete the data stored in the table that they wrap. In addition the developer can of
course add more methods than what is inherited by the common class.
find
All tables should have at least one find method that selects and returns one record
from the table that matches the unique index specified by the input parameters.
The last input parameter in a find method should be a Boolean variable called
'forupdate' or 'update' that is defaulted to false. When it is set to true, the caller object
can update the record that is returned by the find method.
See the next example from the InventTable:
static InventTable find(ItemId itemId,
boolean update = false)
{
InventTable inventTable;
;
inventTable.selectForUpdate(update);
if (itemId)
{
select firstonly inventTable
index hint ItemIdx
where inventTable.ItemId == itemId;
}
return inventTable;
}
exists
As with the find method, there should also exist an exists method.
It basically works the same as the find method, except that it just returns true if a
record with the unique index specified by the input parameter(s) is found.
In the next example from the InventTable you can see that it returns true if the
input parameter has a value AND the select statement returns a value.
static boolean exist(ItemId itemId)
{
return itemId && (select RecId from inventTable
index hint ItemIdx
where inventTable.ItemId == itemId
).RecId != 0;
}
initFrom
Tables that are related to each other share the data that make up the relationship and
possibly also other information. When creating new records in the 'many' table in
a one-to-many relationship you can create initFrom methods that set the common
fields in the table.
It can also be used to enter the values in fields in a table from another table.
The next example is taken from the BOMTable and shows how it initiates
the ItemId and ItemGroupId fields in the BOMTable from the corresponding fields
in the inventTable.
void initFromInventTable(InventTable table)
{
this.bomId = table.ItemId;
this.ItemGroupId = table.ItemGroupId;
}
Array
An array is a list of values that are all of the same data type, as opposed to a
container that can consist of values of different types.
The list of values starts with element 1. If you set a value to index number 0 of an
array, the array is reset.
There are two different ways of using an array. You can either use a fixed-length
array if you know how many elements (max) you will have in the array. If you don't
know how many elements can be stored in the array at run time, you can use a
dynamic array.
In addition to this, you can also specify something called "partly on disk arrays" that
specify how many elements that should be loaded into memory when the array is
referenced. This might be a good performance optimization if you have arrays with a
lot of data.
The next example explains the different usage of arrays:
static void Datatypes_array(Args _args)
{
// Fixed lenght array
str licenceNumber[10];
// Fixed lenght array partly on disk.
// 200 elements will be read into memory when this array
// is accessed.
int serviceMilage[1000,200];
// Dynamic array
str customers[];
// Dynamic lenght array partly on disk.
// 50 elements will be read into memory when this array
// is accessed.
Amount prices[,50];
}
No comments:
Post a Comment
Leave your comments and solutins