4. X++ OVERVIEW
ďą X++ is the programming language used in MorphX IDE.
ďą X++ resembles other popular languages such as C# and Java.
ďą X++ includes many integrated SQL commands;
ďą X++ is object-oriented language and provides a clean and efficient
object-based development platform.
ďą Data Aware Includes keywords such as firstFast, forceSelectOrder,
and forUpdate, as well as a database query syntax application
aware client, server, changecompany, and display
8. Naming conventions
ďąNaming conventions contribute to consistency and to making
the application easier to understand.
ďź {business area name} + {business area description} + {action
performed (for classes) or type of contents (for tables)}
Examples:
⢠CustJournalPrintOutInvoice
⢠PriceDiscAdmDelete
⢠PriceDiscAdmSearch
â˘
PriceDiscAdmName
⢠PriceDiscAdmTrans
9. Comments
ďź Single line â//â
ďź Block comments â/* */â
ďź To do comments âTODO.â To do comments appear in the compilers
Tasks tab page.
ďź /// <summary>
/// This is an XML comment with tags to distinguish
sections.
/// </summary>
10. X++ CONTROL STATEMENTS
Data Type
Declaration
Keyword
Description/Example
String
str
âany stringâ
Integer
int
2356
Real
Real
3.14
Date
date
24112010
Enum
Must be declared
as a Base Enum
first
Enum values are represented
internally as Integers.
Boolean
boolean
True/False
Time
timeOfDay
15:23:08
utcDateTime
utcDateTime
9/28/2008
07:11:02 am
Guid
guid
Global Unique Identifier, a reference
number which is unique in any context
Int64
Int64
A large integer, represent by 64 bits.
11. X++ CONTROL STATEMENTS(Contd.)
Composite Date Types
Variable Declaration:
dataType variableIdentifier;
Array Declaration:
real realUnlimtedArray[];
real realLimitedArray[10];
// Unlimited index values
// maximum of 10 values
12. X++ CONTROL STATEMENTS(Contd.)
Containers:
ďź A variable that can contain different types and values of simple and extended data types, including
arrays and other container variables. Classes cannot be put into containers.
container c;
int i, j;
str txt;
;
c = [10, 20, "test"];
print conPeek(c, 3);
[i,j,txt] = c;
// the container is declared
// the container has 3 values set
// the third element is printed
// Variables being set
13. ⢠Containers There are many functions that manipulate container
⢠conPeek: Returns the value being held in a specific position in the
â˘
â˘
â˘
â˘
â˘
â˘
container.
conDel: Removes a value from a specific position in the container.
conNull: Returns an empty container.
conFind: Finds the position in the container that a certain value is
being held (if found).
conIns: Inserts a value into a specific position in the container.
conPoke: Replaces the value in a specific position in the container
with a new value.
conLen: Returns the number of elements in the container.
14. X++ CONTROL STATEMENTS(Contd.)
Operators:
a) Assignment operators
Operator
Term
Description
=
Becomes equal
to
Assigns the expression on the right of the
equal sign to the variable on the left.
+=
Increments the variable on the left by the
value on the right.
++
Increments the variable on the left by 1.
-=
Decrements the variable on the left by the
value on the right.
--
Decrements the variable on the left by 1.
18. X++ CONTROL STATEMENTS(Contd.)
Conditional Statements
a)
If Statement
Code syntex is just like c#, c++
if (condition)
{ //if true these statements are executed }
else
{ //if false these statements are executed }
19. X++ CONTROL STATEMENTS(Contd.)
Conditional Statements
b) Switch statement
switch (expression)
{
case 'Choice1': Statement1;
Statement2;
break;
case 'Choice2': Statement3;
break;
case 'Choice3': Statement4;
Statement5;
Statement6;
break;
default : DefaultStatement;
}
24. X++ CONTROL STATEMENTS(Contd.)
Built-in functions:
ďź Built-in functions can be used anywhere in X++ code.
ďź These functions can be typed manually or accessed by using the context (rightclick) menu in the code editor and selecting List Built-in Functions, or by pressing
Shift+F4.
Example
str letters;
;
letters ="ABCDEFG";
print subStr(letters, 2, 4);
print subStr(letters, 5, -3);
Result :
BCDE
CDE
25. X++ CONTROL STATEMENTS(Contd.)
Communication Tools:
ďź Communicating with the end-user
Main types of communication are the following:
ďź
Forms and reports which are used for input and output of
larger amounts of data
ďź Print commands, infologs and dialog boxes which are
generally used for specific data input and output
27. X++ CONTROL STATEMENTS(Contd.)
Communication Tools:
Infolog
ďź Infolog is the most common method of communicating to the user
information about how a process has been executed.
ďź Boxes can output a message to a user, but sometimes multiple
messages are generated during processing.
Usage Example:
Info ("This is an info infolog");
28. X++ CONTROL STATEMENTS(Contd.)
Communication Tools:
Boxes
ďź Boxes display brief messages to application users.
ďź There are many different box types and each has their own box
method.
ďź Methods in the box class take the following parameters
⢠The main text
⢠The title bar text
⢠Help text
Example
box::info('Main Text', 'Title', 'This is the help text');
29. X++ CONTROL STATEMENTS(Contd.)
Communication Tools:
Dialog
ďź Dialog boxes are a simplified type of form in Microsoft Dynamics AX.
ďź They are generated from the Dialog class.
Example
static void Simple_Dialog(Args _args)
{
dialog
dlg;
dialogGroup dlgGroup;
dialogField dlgField;
;
dlg = new dialog("Simple Dialog");
dlgGroup = dlg.addGroup("Customer");
dlgField = dlg.addField(TypeID(custAccount),"Account Number");
if (dlg.run()) {
print dlgField.value();
pause;
}
}
30. CLASSES AND OBJECTS
ďź A class is a software construct that defines the data (state) and
methods (behavior) of the specific concrete objects that are
subsequently constructed from that class.
How to create a Class
1. Open the AOT.
2. Locate the Classes node.
3. Right-click the Classes node and select New Class in the context
menu. The new class looks as shown below.
4. A new class named Class1 is created and contains one node: the
classDeclaration node. It is empty by default.
5. Double-click the classDeclaration node.
6. Enter the declarations between the two { } braces.
7. Right-click on the class and select New Method.
8. Rename the method.
9. Type code between the two { } braces.
31. Method Access
There are three modifiers available:
⢠Public allows the method to be called from any code in
the application.
⢠Protected allows the method to be called only by
methods in the same class or subclasses of the class in
which the method is defined.
⢠Private allows the method to be called only by methods in
the same class in which the method is defined.
32. CLASSES AND OBJECTS
Inheritance:
ďź Inheritance is a concept where one class can inherit all the methods
and variables from another class. A child class inherits the methods
of the parent class.
Syntax:
class Child extends Parent
{
}
multiple inheritance is not support. Use interfaces and/or composition
instead.
33. CLASSES AND OBJECTS
Method Types:
a) Static Methods
ďź
Static methods are methods that are attached to a class, but do not need that class
to be instantiated to execute that method. They are not within the scope of the class,
so any class variables are not available in a static method.
static void myStaticMethod() { }
myClass::myStaticMethod()
34. Main Method
It is used by the system when the class is run directly from a menu item
and it takes a parameter of type args.
static void main(Args args){}Args
is a class that is used to pass parameters between objects, for
instance, various parameters can beset on the properties on a menu
item.When the menu item calls a class, the args class containing those
property values is passed to the main
method using the args parameter.
35. Display Methods
Display methods are used on forms and in reports. Display
methods return a value.
display itemName itemName() {
inventTable
inventTable
;
select name from inventTable
where inventTable.itemId == this.itemId;
return inventTable.name;
}
36. CLASSES AND OBJECTS
Method Types:
d) Accessor
ďź Accessor methods enable other elements to set or get the values of
variables in a class. It is common that they do both.
str myName(str _myName = myName)
{
;
myName = _myName;
return myName;
}
37. CLASSES AND OBJECTS
Tables as Classes
⢠A place for a table buffer is automatically assigned in a table in
classes the new method is used.
⢠Fields in tables are public; they can be referred to from
everywhere. Fields in tables can be referred to directly;
for example, in a report, whereas variables in a method can only
be referred to using access or methods.
38. ACCESSING THE DATABASE
In Dynamics Ax 2012
⢠Retrieve data from the database using a select statement
Table Buffers:
A table buffer is declared like a variable â the table name is specified
in the declaration.
A table buffer stores complete records in a variable.
Select Statements:
Select statements are used to retrieve data from a database.
The pure select statement returns records to a table buffer.
39. ACCESSING THE DATABASE (Contd.)
Select
static void Q1_Select1(Args _args)
{
CustTable CustTable;
;
select Address from CustTable;
where CustTable.AccountNum == '1102';
print CustTable.Address;
pause;
}
// To Loop Records
while select AccountNum, Name, Address
from CustTable
{
print CustTable.AccountNum+ ": " + CustTable.Name + ": " + CustTable.Address;
}
pause;
40. Sort
You can sort data retrieved from the database in many ways. This
includes:ď
⢠Using existing indexes on the tables.
⢠Using the order by clause in a select statement.
⢠Using the group by clause in a select statement.
while select custTable index AccountIdx { print
custTable.AccountNum, " ", custTable.currency; }
41. Inner join
while select ledgerTable
join ledgerTrans
where ledgerTrans.accountNum ==
ledgerTable.accountNum
{
amountMST += ledgerTrans.amountMST;
}
42. Exist
while select AccountNum, Name from custTable
order by AccountNum
exists join * from ctr
where (ctr.AccountNum ==
custTable.AccountNum)
43. notExists
while select AccountNum, Name from custTable
order by AccountNum
notExists join * from ctr
where (ctr.AccountNum ==
custTable.AccountNum)
44. outer
while select AccountNum from custTable order by
AccountNum outer join * from custBankAccount where
custBankAccount.AccountNum
== custTable.AccountNum { print
custTable.AccountNum, " , ",
custBankAccount.DlvMode; } pause;
47. ACCESSING THE DATABASE (Contd.)
Update:
static void Q14_Update(Args _args)
{
SalesTable SalesTable;
;
ttsbegin;
while select forupdate SalesTable
where SalesTable.CustAccount == "1102"
{
SalesTable.SalesName = "aaaaa";
SalesTable.update();
info("Updated Successfully");
}
ttscommit;
}
SalesTable SalesTable;
;
update_recordset SalesTable
setting salesName = "Update RecordSet",
DeliveryStreet = "New Address"
where SalesTable.CustAccount == "1102 â;
info("Updated Successfully via RecordSet");
48. ACCESSING THE DATABASE (Contd.)
Delete
static void Q16_Delete(Args _args)
{
CustTable CustTable;
;
ttsbegin;
select forupdate CustTable
where CustTable.AccountNum == "supposedAccount1";
CustTable.delete();
info("Deleted");
ttscommit;
}
CustTable CustTable;
;
while select forupdate CustTable
where CustTable.AccountNum == "4018"
delete_from CustTable
where CustTable.AccountNum == "4018";
49. ACCESSING THE DATABASE (Contd.)
Transaction Integrity Checking
ďź It is important to ensure the integrity of all transactions within the
system. When a transaction begins, to ensure data consistency, it
must finish completely with predictable results.
ďź The following keywords help in integrity checking:
⢠ttsbegin â Indicates the beginning of the transaction.
⢠ttscommit â Indicates the successful end of a transaction. This
ensures the transaction performed as intended upon completion.
⢠ttsabort â Used as an exception to abort and roll back a
transaction to the state before the ttsbegin.
50. ACCESSING THE DATABASE (Contd.)
Queries:
ďź A query is an application object in the AOT
ďź A query performs the same function as the select statements, but is a
better option as it allows for more flexible user interaction when
defining which records are to be retrieved.
Queries Using X++:
ďź Queries can also be created and manipulated using X++. There are a
number of classes available that you can use to achieve this.
ďź Two important classes when executing a query are:
ďź Query()
ď§ The Query() class provides the framework for the query
ďź QueryRun()
ď§ QueryRun() class starts this framework dynamically.
52. ACCESSING THE DATABASE (Contd.)
Accessing data from Different Companies:
static void Q10_CrossCompanies1(Args _args)
{
Container ConComapnies = ['cee','ceu'];
CustTable CustTable;
;
while select crossCompany : ConComapnies CustTable
{
Print CustTable.Name;
}
pause;
}
53. EXCEPTION HANDLING
Exception:
ďź When code is running, errors can occur due to user input, setup, data,
code, or installation problems.
ďź Users need a clear indication of when errors occur so they can
resolve the problem or report it to an administrator or systems
developer, who can investigate what went wrong.
54. EXCEPTION HANDLING
Exception Example:
static void Exception3(Args _args)
{
CustTable custTable;
;
try
{
custTable.AccountNum = '54299';
custTable.CustGroup = '50';
custTable.Address = 'Lahore Pakistan';
if(!custTable.validateWrite())
throw error("1. Record Failed during Validation.");
custTable.insert();
info("2. Record saved in database successfully, while passing validation");
}
catch(Exception::Error)
{
error("3. There was an error, while inserting the record.");
}
}