How to use Dialog in Dynamics Ax.

If you came accross a requirement , where you need to collect the information and then executes a task . In such scenario Please make use of RunBase class.
Advantage of RunBase class
1. It provides dialog for presenting and collecting the information from user.
2. Pack/Unpack methods , for storing the last value entered by the user.
3. Progress bar ,for long time process where in you can show a progress bar.
4. Validate method , to validate the data entered by the user in the dialog.

you can refer tutorial in AOT->Classes->tutorial_RunBaseForm .

How to Use Temporary Table in Form

Temporary table(Table whose property temporary set to "yes") is not persistent media , so at run-time you have to populate the temporary table and attach the same to the form/report.
For illustration purpose ,I am using inventTable data and attaching the items whose group is Parts.

1. Create temporary table as TmpTestTable with 3 fields(ItemId,Itemname,ItemGroup).
2. Create a form as TempTestTable and attach the table as datasource
3. Create a new method on the form and copy the following code

TmpTestTable populateRecords(ItemGroupId _itemGroupId)

TmpTestTable tmpTable;
InventTable inventTable;

while select inventTable
where inventTable.ItemGroupId == _itemGroupId
tmpTable.Itemid = inventTable.ItemId;
tmpTable.ItemName = inventTable.ItemName;
tmpTable.Itemgroup = inventTable.ItemGroupId;

return tmpTable;

4. Call the above method in init() after super as below
public void init()


// Call the setTmpData method to attach records to datasource

X++ code to identify multiple selected records in Grid

Steps :
1. Create a new method on form and copy the following code.
2. Next create a button on form . and call the method on the button click event.
(for the button property makesure the Multiselect should be set to yes , or else by default for multiple selection system will disable the buttons)

void checkSelectedRecords()
InventTable inventLocal;
//getFirst method gets all the selected records in the grid
inventLocal = InventTable_ds.getFirst(true);

while (inventLocal)
info(strfmt("You selected Item %1",inventLocal.ItemId));
// get the next selected record
inventLocal = InventTable_ds.getNext();

As shown below ..

X++ code to hide content pane in ax2009

This is for developers , not for endusers.As you know it will irritate during developemnt since it is appearing on top of all windows when we open form.

static void hideContentPaneWindow(Args _args)

HWND contentPane = WinApi::findWindowEx(WinAPI::findWindowEx(infolog.hWnd(), 0, 'MDIClient', ''),0,'ContentFrame','' );
if (contentPane)
WinApi::ShowWindow(contentPane,#SW_HIDE); // To restore use #SW_RESTORE

Get AX4.0 look and feel back in Ax2009

You all might be aware that all forms in Ax2009 are behaving like independent application forms.i,e When you open any form it will get open outside the application.

So following are the two solutions to open forms in same workspace as in Ax4.0
1. Change the formdesign property windowtype(from standard to workspace).this you have to do for all the forms which is time cosuming.
2. Or else Add following line in the init method of SysSetupFormRun class.
before super() as shown in the following code

public void init()

//at run-time you are setting property to workspace.


if (this.isWorkflowEnabled())
workflowControls = SysWorkflowFormControls::construct(this);

Security Keys in Ax

Dynamics Ax provides following keys to provide the security for application

1.License Keys :
First Level Security , specifies what all featues/modules/developemnt tools we can access in the standard product.License Keys will be used after installation to unlock the product.License Keys will be issued by the microsoft for partners/vendors to develop vertical/generic solutions.

2.Configuration Keys :
Second Level Security , To Enable/Disable the object/feature for all the users.

3.Security Keys :
If you want to enable/disable object/features to group of users.

4. Record Level security :
Basically it deals with the data , if you want to restrict the viewing of records per user group than we setup record level security.

Dynamics Ax Systemclass for RECID

As you all know that Dynamics Ax uses recid(Record Id)to uniquelly identify a record in the database.
Advantage of RecId
1.By default system uses Recid as primary index,so if query optimizer didn't find any index to use then it will use RecId.

Dyamics Ax uses SystemSequence class(AOT->SystemDocumentation->Classes) to generate recId for table.
Using SystemSequence class you can reserve RECID's for your table.
Ax Kernel uses SystemSequences Table to generate the Recid for table as shown below
Goto AOT->SystemDocumentation->Tables->SystemSequences ,

X++ code to write data to XML File

static void CreateXml(Args _args)
XmlDocument xmlDoc; //to create blank XMLDocument
XmlElement xmlRoot; // XML root node
XmlElement xmlField;
XmlElement xmlRecord;
XMLWriter xmlWriter;
InventTable inventTable;
DictTable dTable = new DictTable(tablenum(InventTable));
DictField dField;
int i, fieldId;
str value;

xmlDoc = XmlDocument::newBlank();
xmlRoot = xmlDoc.createElement(#ItemRootNode);

// Loop through all the records in the inventTable
while select inventTable
where inventTable.ItemGroupId == "Parts"
// Create a XmlElement (record) to hold the
// contents of the current record.
xmlRecord = xmlDoc.createElement(#ItemRecords);
// Loop through all the fields in the record
for (i=1; i<=dTable.fieldCnt(); i++)
fieldId = dTable.fieldCnt2Id(i);
// Find the DictField object that matches
// the fieldId
dField = dTable.fieldObject(fieldId);

// Skip system fields
if (dField.isSystem())
// Create a new XmlElement (field) and
// have the name equal to the name of the
// dictField
xmlField = xmlDoc.createElement(;
// Convert values to string. I have just added
// a couple of conversion as an example.
// Use tableName.(fieldId) instead of fieldname
// to get the content of the field.
switch (dField.baseType())
case Types::Int64 :
value = int642str(inventTable.(fieldId));
case Types::Integer :
value = int2str(inventTable.(fieldId));
default :
value = inventTable.(fieldId);
// Set the innerText of the XmlElement (field)
// to the value from the table
// Append the field as a child node to the record
// Add the record as a child node to the root
// Add the root to the XmlDocument
// Create a new object of the XmlWriter class
// in order to be able to write the xml to a file
xmlWriter = XMLWriter::newFile(@"c:\Items.xml");
// Write the content of the XmlDocument to the
// file as specified by the XmlWriter

//Open the file in Internet Explorer

X++ code to Read/Write Dynamics Ax data to excel

Writing Data to Excel file
How it works
1. Use SysExcelApplication class to create excel file.
2. Use SysExcelWorkbooks and SysExcelWorkbook to create a blank workbook(by
default 3 worksheets will be available).
3. Use SysExcelWorkSheets to select worksheet for writing data.
4. SysExcelCells to select the cells in the excel for writing the data.
5. SysExcelCell to write the data in the selected cells.
6. Once you done with write operation use SysExcelApplication.visible to open

static void Write2ExcelFile(Args _args)

InventTable inventTable;
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
SysExcelCell cell;
int row;

application = SysExcelApplication::construct();
workbooks = application.workbooks();
workbook = workbooks.add();
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();

cell = cells.item(1,1);
cell = cells.item(1,2);
row = 1;
while select inventTable
cell = cells.item(row, 1);
cell = cells.item(row, 2);

Reading Data from Excel File
static void ReadExcel(Args _args)

SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
COMVariantType type;
int row;
ItemId itemid;
Name name;
FileName filename;


application = SysExcelApplication::construct();
workbooks = application.workbooks();
//specify the file path that you want to read
filename = "C:\\item.xls";
catch (Exception::Error)
throw error("File cannot be opened.");

workbook = workbooks.item(1);
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
itemId = cells.item(row, 1).value().bStr();
name = cells.item(row, 2).value().bStr();
info(strfmt('%1 - %2', itemId, name));
type = cells.item(row+1, 1).value().variantType();
while (type != COMVariantType::VT_EMPTY);

X++ code to create a customized lookup on form

Override the lookup method on Formdatasource field(on which you want to show lookup) , and copy the following code to your method.
Comment the super() method in the lookup.

public void lookup(FormControl _formControl, str _filterStr)

SysTableLookup sysTableLookup; // systemclass to create //customlookup
Query query;
QueryBuildDataSource qbd;

sysTableLookup = SysTableLookup::newParameters(

// Construct query on the table,
// whose records you want to show as lookup.
query = new Query();
qbd = query.addDataSource(tablenum(InventTable));

// add the fields to the lookup list

// pass the query as parameter
// system will show the records in the lookup
// as per your query


X++ code to find the Stock of Item by Date

static void findOnHand_ByDate(Args _args)

InventDim inventDim;
InventDimParm inventDimParm;
Itemid itemid;
InventOnHand inventOnHand = new InventOnHand();
InventSumDateDim inventSumDateDim;
TransDate transDate;

// take a sample item for testing
itemid = "20 MM RMC";
transDate = 13\01\2010;

// take a combination of dimension , against which you want to find the stock
inventDim.InventLocationId = "GW";

//Set the flag for the selected dimensions as active.

//initialize the inventSumDateDim with Date,item,dimension and dim paramter

inventSumDateDim = InventSumDateDim::newParameters(transDate,

// Retrieve the onhand info
info(strfmt("PostedQty: %1",inventSumDateDim.postedQty()));
info(strfmt("DeductedQty: %1",inventSumDateDim.deductedQty()));
info(strfmt("ReceivedQty: %1",inventSumDateDim.receivedQty()));


X++ Code to find OnHand Stock for Item

In Dynamics Ax , use InventOnHand class for finding the stock of an item as shownbelow

static void findOnHand(Args _args)

InventDim inventDim;
InventDimParm inventDimParm;
Itemid itemid;
InventOnHand inventOnHand = new InventOnHand();

// take a sample item for testing
itemid = "20 MM RMC";

// take a combination of dimension , against which you want to find the stock
inventDim.InventLocationId = "GW";

//Set the flag for the selected dimensions as active.

//initialize the inventonhand with item,dimension and dim paramter


// Retrieve the onhand info
info(strfmt("Available Physical: %1",
info(strfmt("On order: %1",inventOnhand.onOrder()));


Dynamics Ax 2009 Layers

Dynamics AX 2009 consists of sixteen application object layers that contain all the
elements you see in the AOT.
These layers can be looked at as an onion with multiple layers. In the middle is the
core application in the SYS layer and the outermost layer is the user layer USR.
Therefore, when any application element is being executed the system will look at
the outermost code layer first to see if there is any code for that element; if not, it peels a layer off the onion, and tries the next layer. When it hits a layer where the element exists, it will use the code from this layer, and will not continue to peel off layers to find code for that element in the innermost layers.

Layers with their description

SYS The standard application is implemented at the lowest level,
the SYS layer.The application objects in the standard
application can never be deleted.

GLS Country/region specific changes will be developed in GLS
Layer.For e.g as you all know that Tax structure differs
from country to country.So such localization functionality
can be developed in GLS layer.

HFX HFX is an application object patch layer reserved by
Microsoft for future patching or other updates.

SL1, SL2,or SL3 A layer where the distributor can implement
vertical partner solutions.

BUS When a business partner creates their own generic solution,
their modifications are saved in the BUS layer and the top-
level application objects are used.

VAR Value Added Resellers (VAR) can make modifications or new
developments to the VAR layer as specified by the customers
or as a strategy of creating an industry-specific solution.
Such modifications are saved in the VAR layer.

CUS The supervisor or administrator of an end user installation
might want to make modifications that are generic to the
company. Such modifications are saved in the CUS (CUStomer)

USR End users might want to make their own modifications, such
as in their reports.These modifications are saved in the USR

X++ code to create and post Inventory Movement Journal

Following is the sample job to show how we can create and post movement journal by making use of available api's in the Dynamics Ax.

static void createMovJournal(Args _args)
InventJournalTable journalTable;
InventJournalTrans journalTrans;
InventJournalTableData journalTableData;
InventJournalTransData journalTransData;
InventTable inventTable;
InventDim inventDim;
Counter cnt;
InventJournalCheckPost journalCheckPost = new InventJournalCheckPost();

journalTableData = JournalTableData::newTable(journalTable);
journalTransData = journalTableData.journalStatic().newJournalTransData(journalTrans,journalTableData);

// Init JournalTable


journalTable.JournalId = journalTableData.nextJournalId();
journalTable.JournalType = InventJournalType::Movement;
journalTable.JournalNameId = journalTableData.journalStatic().standardJournalNameId(journalTable.JournalType);


// Init JournalTrans
select firstonly inventTable;

journalTrans.TransDate = systemdateget() + 1 div 2;
journalTrans.ItemId = inventTable.ItemId;
journalTrans.Qty = 100;
journalTrans.CostAmount = 100;

// Dimension details

inventDim.InventLocationId = 'GW';
journalTrans.InventDimId = InventDim::findOrCreate(inventDim).inventDimId;




// Call the static method to post the journal


X++ NumberSequence Code to generate numbers

Axapta uses following classes for generating numbers against numberseq code.

1.NumberSeq class--> Main class which will generate,assigns numbers and vouchers for
2.NumberSeqReference--> Used to find the reference.

static void numberSeq_Demo(Args _args)

NumberSeq numberSeq;
numberSeq = numberSeq::newGetNum


How it works
1.NumberSeq Table act as master table for numberseq code , which stores
format to be generated , next sequence etc.
2.NumberSequenceReferences stores all the references and their corresponding
numberseq codes.
3.As shown in the above code , NumberSeq class needs numberseqreference ,
i,e "EDT. Unique Id for the Process " So first get the references by
passing an EDT as parameter to the findReference method of numberseqreference
class.Than you can call numberSeq.num() method to generate the number
for you.
4.Use NumberSeqFormHandler class if you want to use the numbersequencs on form.

Axapta(X++) Glossary with their definition

Widely used Axapta Terms and their Definition


Microsoft Dynamics AX Label Description files have the extension .alc. Also see ALD and ALI.


Label data files have the extension .ald (AX Label Data). Also see ALC and ALI.


Microsoft Dynamics AX Label Index files have the extension .ali. Also see ALC and ALD.


Application Object Server is windows service used to coordinate with different components of Dynamics Ax.


Application object tree , repository that stores metadata information about the objects created in Axapta.

Base data

Data which is customer-dependent. Examples: Customers, Vendors, Items.
This is often data from an existing system, which must be entered or imported into
Microsoft Axapta.


Graphical object, such as a text box or command button that you put on a form or
report to display data, perform an action, or make the form or report easier to


An abbreviation for the four basic database operations: Create, Read, Update,


Distributed COM

efault data

Data which is customer-independent. Examples: Zip codes, Address formats, Time
Intervals, Units, Unit conversions, VAT parameters, Transaction texts.
When a user modifies default data, it becomes custom data, which is customer-
dependent. This means that default data can sometimes be customer dependent,
because of historic reasons, such as Chart of Accounts.


Collection of one or more companies. Domains enable you to define user groups that
have the same permissions in more than one company while allowing the same user
groups to have other permissions within other companies.


Extended Data Type: a user-defined data type based on a primitive data type or


Integrated Development Environment. MorphX is the Microsoft Dynamics AX IDE.


The Runtime Environment embedded in Microsoft Dynamics AX, that draws menus, forms,
and reports for Windows- and Web-clients with the correct contents, size, and
layout according to:
the language your texts are displayed in.
what features you can access.
how wide you want the fields on your installation.
the formats you are using for dates and numbers.


The Development Environment of Microsoft Dynamics AX, including:
Data Dictionary
Tools for creating menus, forms and reports for Windows- and Web clients
Compiler and debugger for the object oriented programming language X++
Version control system
Label (multi language text) systems


Provide more than one method with the same name but with different signatures to
distinguish them.
Overloading is not supported by X++. Also see override.


Replace the superclass's implementation of a method with one of your own. The
signatures must be identical.

Only non-static methods may be overridden.

Record ID

A record ID uniquely identifies a row of data in a table. Record IDs are integers. They are assigned and managed by Microsoft Dynamics AX.

super ()

Reference to the system class that contains the required method. When super() is used, the system method is automatically used.


Reference to the current object. this is frequently used as a parameter to methods
that need an object reference.for e.g at Table level if it used gives you the
selected record.


Transaction Tracking System. For more information, see Transaction Integrity.


Windows Application Programming Interface. Contains System level API's
like "WinAPI::shellExecute("file.exe");" for opening applications from axapta.

Copying License in Dynamics Ax

Axapta stores the License data in the following two tables.


So if you copy data of these tables(from Running instance) and import at your instance , this will serve your purpose.

GlobalCache (alternative to GlobalVariables in X++)

Many times because of flawed implementation designs, we often need global variables. We may use a table with a key field and a container field for this purpose, but the simplest way of doing this will be using a Global Cache.
A global cache is an instance of class - SysGlobalCache, which is nothing but a Map containing Maps with Userid as Key. These Maps contain the actual value and a key.
In Ax, we have three(infact 4) Global Caches - Infolog.globalCache(), Appl.globalCache(), ClassFactory.GlobalCache().

How to use:
To Set a Value:
static void GlobalCacheSet(Args _args)
SysGlobalCache globalCache;
globalCache = ClassFactory.globalCache();
globalCache.set(curuserid(), 1, "One");
To Get the Value:
static void GlobalCacheGet(Args _args)
SysGlobalCache globalCache;
globalCache = ClassFactory.globalCache();
print globalCache.get(curuserid(), 1);
globalcache.remove(curuserid(), 1);

In the above the example, we can also use Infolog.globalCache() or Appl.globalCache().

Why do we have three Caches?

Its simple, the term "Caching" comes when there is something to do with Performance.

Infolog Object resides in Client and Application Object resides in Server.
To share your global variable across the network and accept the performance penalty of a client/server call, use the infolog variable (Info class) or appl variable (Application class) instead of ClassFactory.

ClassFactory is a special class, which has instances residing at both server and client. At run time, two instances of the ClassFactory class exist, and they share name classFactory. However confusing the implementation details might sound, this is a powerful concept. When you call a method on classFactory from code running on the client, you are calling the classFactory object on the client tier; when you call a method on classFactory from code running on the server, you are calling the classFactory object on the server tier. Remember this when debugging the ClassFactory class.

How to Login After Changing Domain in Axapta

As you know axapta uses windows authentication for login.
So SID,Networkuser and NetworkDomain should be updated in the USERINFO table.

Steps to find SID :
open registry editor and click HKEY_USERS in left pane to expand it. There in left pane itself you will find the SID of users.Means folder name that starts with something like "S-1-5-21-2152947634"

Update the correct SID and Domain then try to start the AxClient.

Dynamics Ax 2009 Whitepapers

Please find the following link for Setup,configuration materials in 2009

Download 2009 Docs

X++ Code to remove the duplicate objects in AOT

Scenario : Nags came across a requirement for duplicating the production instance.He followed the following steps
1. Setup a new instance and Copied the var.aod files from production
instance and restored the DB with production DB.
2. After that he kept the application for compilation. When the
compilation ends , he tries to synchronize the Data dictionary. But
he was getting error during synchronization because some objects were
duplicated in layers. e.g System will show two ItemId fields at
table level.

Use the following code to delete the identical copy.

//Thanks for Fredshen for the following code

static void FindAndDeleteIdenticalObjects(Args _args)
SysTreeNode comparable1, comparable2;
TreeNode curLevelTreeNode, upperLevelTreeNode;
UtilIdElements utilElements, joinUtilElements;

while select UtilElements
where UtilElements.utilLevel == UtilEntryLevel::var &&
UtilElements.recordType == UtilElementType::Form ||
Utilelements.recordType == UtilElementType::Report ||
Utilelements.recordType == UtilElementType::Table ||
Utilelements.recordType == UtilElementType::Class ||
Utilelements.recordType == UtilElementType::Enum ||
Utilelements.recordType == UtilElementType::ExtendedType
//Should use join if for a normal table, but not applicable for UtilElements
//Performance hit if use exists join
select firstonly recid from joinUtilElements
where joinUtilElements.utilLevel != UtilElements.utilLevel && == &&
joinUtilElements.recordType == UtilElements.recordType;
if (joinUtilElements.RecId)
//Thanks for Jim Shepherd here
curLevelTreeNode = SysTreeNode::findNodeInLayer(UtilElements.recordType,, UtilElements.parentId, UtilElements.utilLevel);

upperLevelTreeNode = SysTreeNode::getLayeredNode(curLevelTreenode, 1);
comparable1 = SysTreeNode::newTreeNode(curLevelTreeNode);
comparable2 = SysTreeNode::newTreeNode(upperLevelTreeNode);
if (SysCompare::silentCompare(comparable1, comparable2))
info(strFmt("Element name: %1, Element type: %2",, enum2str(UtilElements.recordType)));
//Remove the node

X++ Code Optimzation

Following are the coding tips to improve your Axapta system's performance:
1. Smart Joins : Try to Use Joins instead of nested while loop
wherever possible.
2. Select Statement : Mention the field names in the select statement
instead of feteching entire row , this will reduce
data amount to transfer from database.
e.g " Select Itemid from inventTable "

3. Display Methods : Make sure that generic display methods should be
moved at table level and cached by
4. Local caching : Use Variables for storing the constantly used
caculated values in loop , by doing so you can
reduce the calls to the database and different
5. Monitor the Database Calls : For bulk records
updation,deletion,insertion use
RecordSet Based operator like
update_recordset , delete_from and insert_recordset .
6. Aggregate Function: Use sum, avg, minof, maxof and count where
applicable. Because this can utilize the database’s
built-in function instead of calculating and analyse
data in Axapta.

For Ax Developers

Keep following things in your mind before you start coding in Ax.

1. Whenever you came accross new functionality , don't start coding immediately please first cross check whether the same/similar kind of functionality is there in the standard product. By doing so you will save time for coding,learn ax coding style and also this will help you to understand the various functionalities in the standard product.
2. Start with pseudo-code , just draw sketch on paper how you want the data to flow , which will help you in understanding the different override methods in Axapta.
3. Code should be modular , Instead of writing all the code in one method please write plug and play functions.

Happy New Year

Have a Wonderfull Year.