Monday, December 21, 2009

Phone Number Formatting Mask

It is pity but AX does not have the mask functionality on StringEdit fields. (versions 3.x- 4.x at least)

I changed the standard functionality for Phone field of Customers form so that the input phone number will be formatted as (xxx) xxx-xxxx[x]

For example, if one input 1234567890 it will be presented and saved as (123) 456-7890


For 12fs3.45*6.78--90 it will be presented and saved as (123) 456-7890 with no non-numericals.

12345678901234567 will be as (123) 456-7890123456 it does not truncate the tail.

If finally it does not look like (xxx) xxx-xxxx the system alerts the user about that however the input value will be saved.

The following methods were added/changed:

ClassDeclaration of Customers form

public class FormRun extends ObjectRun

boolean sisValidateCalled;

StringEdit Phone field methods:

public void enter()
sisValidateCalled = false;

public boolean validate()
boolean ret;
int length;
Phone newPhone;
ret = super();

// creates new phone number in the format (xxx) xxx-xxxx[x]
newPhone = SISTools::formatPhoneNumber(this.text());
length = strlen(newPhone);

if (length != #CorrectPhoneLettersNumber)
checkFailed(strfmt("Phone numbers should be like: (xxx) xxx-xxxx"));

CustTable.Phone = newPhone;
sisValidateCalled = true;
return ret;
public boolean leave()
boolean ret;

ret = super();

if (!sisValidateCalled)

return ret;

SISTools class (some collection of utilities)

// creates new phone number in the format (xxx) xxx-xxxx[x]
static public Phone formatPhoneNumber(Phone _phone = "")
Phone newPhone = "";
str char;
int length = strlen(_phone);
int i;
container numbers = ['0','1','2','3','4','5','6','7','8','9'];
// remove all non numbers from field text
for (i=1; i<=length; i++)
char = substr(_phone,i,1);
if (confind(numbers,char))
newPhone = newPhone + char;
length = strlen(newPhone);

// create new phone number in the format (xxx) xxx-xxxx from 1234567890
newPhone = "(" + substr(newPhone,1,3) + ") " + substr(newPhone,4,3) + "-" + substr(newPhone,7, length-6);

return newPhone;

Inspired by Sonny Wibaba Adi

Friday, December 4, 2009

Flush Events related tables quickly

Quick job to delete all records from Events related tables. Inspired by this posting of Nitesh Ranjan.

static void FlushEventInbox(Args _args)
To implement Alert functionality, Dynamics AX uses following tables:

|- EventInboxData
|- EventRule
EventRuleRelData EventRuleRelData;
EventRuleRel EventRuleRel;
EventRuleIgnoreAggregation EventRuleIgnoreAggregation;
EventRuleIgnore EventRuleIgnore;
EventRuleField EventRuleField;
EventRuleData EventRuleData;
EventRule EventRule;
EventInboxData EventInboxData;
EventInbox EventInbox;
if (Box::okCancel("Flush all Events related table?", DialogButton::Cancel, "Confirm deletion",
"Delete all records from: delete_from EventRuleRelData, EventRuleRel,"
+" EventRuleIgnoreAggregation, EventRuleIgnore, EventRuleField, EventRuleData,"
+" EventRule, EventInboxData, EventInbox") == DialogButton::Ok)
delete_from EventRuleRelData;
delete_from EventRuleRel;
delete_from EventRuleIgnoreAggregation;
delete_from EventRuleIgnore;
delete_from EventRuleField;
delete_from EventRuleData;
delete_from EventRule;
delete_from EventInboxData;
delete_from EventInbox;


Tuesday, December 1, 2009

How to add all descendant classes to a new project

I bumped into the problem of a class compilation with no licence for X++ source code.

Forward compile option is not enough to make my changes working. Thus I need to export-import all descendant classes as well as the class I changed - FormLetter in my case.

I therefore have to add all these classes to my project. Natural laziness saved me again from this manual work.

I hope this short job inspired by system class SysCompilerOutput and miklenew's job from AXForum will help you in similar situations.

// add to a new project all descendant classes for forward compilation
public static void SISCreateCompileForwardProject(Args _args)
str project = 'SIS_CompileForward';
SysCompilerOutput sysCompilerOutput;
Dictionary dictionary = new Dictionary();
DictClass dictClass = new DictClass(className2Id("Formletter"));
int numOfClasses = dictionary.classCnt();
ProjectNode sharedProjects;
ProjectNode newProject;

void addToProjectForwardClass(DictClass _dictClass, Dictionary _dictionary, int _numOfClasses)
ClassNode classNode;
DictClass dictClassLoop;
DictClass childClass;
int i;
if (_dictClass)
classNode = infolog.findNode(#ClassesPath + #AOTDelimiter +;

if (classNode)

for (i=1; i <= _numOfClasses; i++)
dictClassLoop = _dictionary.classObject(_dictionary.classCnt2Id(i));

if (dictClassLoop.extend() ==
childClass = new DictClass(;
addToProjectForwardClass(childClass, _dictionary, _numOfClasses);

sharedProjects = infolog.projectRootNode().AOTfindChild('Shared');
newProject = sharedProjects.AOTfindChild(project);
newProject = newProject.getRunNode();
addToProjectForwardClass(dictClass, dictionary, numOfClasses);


Tuesday, October 20, 2009

Microsoft Brain

Yesterday, I was at a seminar about Microsoft Sharepoint Portal Services organized by Montreal community of .Net developers.

The presentation was good and interesting as usual. At the end of it they raffled three books about Best Practice for MOSS and one licence of Visual Studio 2008. However, yet there was one other prize that I got - Microsoft brain.

I am shocked how small it is...

picture borrowed from somebody

Thursday, July 16, 2009

Set 1920x1080x60 Resolution for LG LCD (VGA)

After installation of Ubuntu 9.04 I got a problem with my LCD as a second monitor to my Toshiba laptop. The resolution should have been 1920x1080 as a maximum but was 1280x768 indeed.

With a little help of my friend and this article I managed to add this absent line into xorg.conf file.

I am not sure about all these numbers in the following script for Terminal but it works as a charm.

sudo cvt 1920 1080 60 # 1920x1080 59.88 Hz (CVT 2.30MA) hsync: 74.56 kHz; pclk: 193.25 MHz Modeline "1920x1080" 193.25 1920 2056 2256 2592 1080 1203 1209 1245 -hsync +vsync

sudo xrandr --newmode "1920x1080" 193.25 1920 2056 2256 2592 1080 1203 1209 1245 -hsync +vsync

sudo xrandr --addmode VGA "1920x1080"

Now, you can easily set it in Display Setting utility.

Tuesday, May 5, 2009

Code Camp Montreal 2009: Les meilleures pratiques de développement logiciel

Have you already registred? I have

Date : Samedi 30 mai 2009
Heure : 8h30 à 17h00
Endroit : Marriott Château Champlain au centre ville (Carte), salles Viger A-B-C.
Stationnement: Payant. Le 1000 de la Gauchetière qui est juste à côté de l'hôtel offre un tarif réduit le week-end.
Métro: Bonaventure (ligne orange)
Coût : gratuit
Repas: non inclus
Thème : Les meilleures pratiques de développement logiciel.
Organisé par la Communauté .NET Montréal

Monday, May 4, 2009

Developer for Microsoft Dynamics AX Certification Roadmap

Microsoft Certified Business Management Solutions Professional - Developer for Microsoft Dynamics AX

MB6-819 AX 2009 Development Introduction

MB6-821 AX 2009 MorphX Solution Development

Collection 80011AE: Development I in Microsoft Dynamics AX 2009 (4 Hours)

Development I – Architecture

Development I - Data Dictionary

Development I - User Interfaces

Development I - Report Adjustments

Collection 80012AE: Development II in Microsoft Dynamics AX 2009 (3 Hours)

Development II - X++ Overview

Development II - Classes and Objects

Development II - X++ Control Statements

Development II - X++ Control Statements

Development II - Accessing the Database

Development II - Exception Handling

Development II - Appendix

MB6-820 AX 2009 Installation & Configuration

80019AE: Installation and Configuration for Microsoft Dynamics AX 2009 (6 Hours)

Installation and Configuration - Overview

Installation and Configuration - Planning Microsoft Dynamics AX Install

Installation and Configuration - Installing and Deploying Enterprise Portal

Installation and Configuration - Installing AIF Web Services

Installation and Configuration - Initializing Microsoft Dynamics AX

Installation and Configuration - Installing the Base System

Installation and Configuration – Deploying

Installation and Configuration - Installing and Deploying Workflow

Installation and Configuration - Install Microsoft Dynamics AX Reporting

MB6-825 AX 2009 Enterprise Portal Development


MB6-817 AX 2009 Trade & Logistics

80024AE: Trade and Logistics I in Microsoft Dynamics AX 2009 (9 Hours)

Trade and Logistics I - Introduction

Trade and Logistics I - Inventory

Trade and Logistics I - Purchase Orders and Purchase Order Posting

Trade and Logistics I - Serial and Batch Numbers

Trade and Logistics I - Item Arrival and Registration

Trade and Logistics I - Quarantine Management

Trade and Logistics I - Vendor Returns

Trade and Logistics I - Sales Orders and Sales Order Posting

Trade and Logistics I - Sales Order Picking

Trade and Logistics I - Over/Under Delivery and Miscellaneous Charges

Trade and Logistics I - Customer Returns

80025AE: Trade and Logistics II in Microsoft Dynamics AX 2009 (8 Hours)

Trade and Logistics II - Customer and Vendor Trade Agreements

Trade and Logistics II - Inventory Reporting and Statistics

Trade and Logistics II - Purchase Requisitions

Trade and Logistics II - Request for Quote

Trade and Logistics II - Transfer Orders

Trade and Logistics II - Sales Quotations

Trade and Logistics II - Quality Management

Trade and Logistics II - Reservations

Trade and Logistics II - Commissions

Trade and Logistics II - Inventory Journals

80010AE: Bill of Material in Microsoft Dynamics AX 2009 (6 Hours)

Bill of Materials - BOM Overview

Bill of Materials - Create Simple BOMs

Bill of Materials - Reports and Other BOM Functionality

Bill of Materials - Report a BOM as Finished

Bill of Materials - Scrap and Measurement

Bill of Materials - BOM Calculations

Bill of Materials - Creating BOMs with Versions

Bill of Materials - Sales Orders and BOMs

Bill of Materials - Working with BOM and Item Configurations

Full list of AX2009 exams

Thursday, April 30, 2009

How To Restrict Form Setup Conext Menu Item

To resrtict Form Setup context menu item you should:

Create security key, for example, SysSetupFormPermission

Add this key to SysSetupForm control tab

Create a new user group supposed to be restricted

Uncheck the key

A user included in the group will still have the context menu item
but will see an empty form

Thursday, April 9, 2009

Launching and closing Internet Explorer

One can run Internet Explorer in visible or invisible mode, then navigate any url and close the application, finally.

static void TestIE(Args _args)
COM c = new COM("InternetExplorer.Application");
str url = "";
if (DialogButton::Yes == BOX::YesNo("To close the browser press Yes", DialogButton::Yes))
info(strfmt("Job is done"));

Monday, March 30, 2009

Watching variables of a report

A little trick to watch your variables during debugging a report. Add a variable to watch and add the Element. prefix to its name.

Monday, March 16, 2009

Customized Comment In Your Code Editor

Standard code editor allows to create your own kind of comments. Generally, a style of comments depends on your programming style and the company's policies on that.

I prefer to frame changes I make in a code with parentheses in the following style:

// Voytsekhovskiy, Alexey (My company name) (2009/03/16) (#)
the code as it wasd before my changes

In order to have such an option in the editor's context menu I changed EditorScripts class as follows:

1. Created a new add-on function

boolean isEmptySelection(str s)
// delete all special symbols
return strLen(strRem(strRem(strRem(s," "),"\n"),"\r"))>0;

2. Changed getSelectedText standard method

// added here the new parameter takeAllIfEmpty
static str getSelectedText(Editor e, boolean takeAllIfEmpty = true)
int i;
str text;
str line;
int startLine = e.selectionStartLine()+1;
int endLine = e.selectionEndLine()+1;
int startCol = e.selectionStartCol();
int endCol = e.selectionEndCol();

if (startLine == endLine && startCol == endCol)
// added here
if (!takeAllIfEmpty)
return text;

while (e.moreLines())
text += e.getLine()+'\r\n';
(the rest of the method)

3. Created the method which implements this new kind of comments:

// Insert a comment in place of the cursor
// (Example: Developer's name (Your company name) (YYYY/MM/DD) (#))
// //-->
// Your code here as it was before
// //<--
void Comments_BetweenParentheses(Editor e)
#define.YourCompanyName("Your company name")
str selText = EditorScripts::getSelectedText(e, false);
str selFirstLine;
int startLine = e.selectionStartLine()+1;
int startCol = e.selectionStartCol();
xppSource xppSource;
startLine = e.selectionStartLine()+1;
selFirstLine = e.getLine();

startCol = strLen(selFirstLine) -strLen(strLTrim(selFirstLine));
xppSource = new xppSource(startCol);
e.insertLines(xppSource.indent()+strFmt("// %1 ("+#YourCompanyName+") (%2) (#)", XUserInfo::find(False, curUserId()).name, date2str(today(), 321, 2, 4, 2, 4, 4))+"\n");
startCol = e.columnNo();
xppSource = new xppSource(startCol);
e.insertLines(strFmt("// %1 ("+#YourCompanyName+") (%2) (#)", XUserInfo::find(False, curUserId()).name, date2str(today(), 321, 2, 4, 2, 4, 4))+"\n");

So, after compilation you can use the new comments style.

after commenting

Just to be on the safe side I place here the link to the whole project file CommentParentheses.xpo

книга Разработка бизнес-приложений в Microsoft Business Solutions - Axapta версии 3.0

С этой книги я начал изучение ERP-системы MS Axapta, во многом благодаря ей я нашёл первую работу в Канаде, и по сей день, она является наиболее востребованной среди прочих книг на моём столе для разработки для всех версий MS Dynamics: 3.0 4.0 и 2009.

Книга написана одновременно и как справочное пособие по архитектуре, среде разработки и языку X++, и параллельное описание реализации конкретного проекта "Управление гостиницей".
На примере последнего и разбираются варианты использования той или иной функциональности.

Вообще, примеры - это самая сильная часть любого руководства разработчика, и данная книга - отличный образец того, как это нужно делать: здесь можно найти не только соответствующие Best Practice стандартные паттерны программирования, которые особенно важно усвоить вначале работы с системой, но и такие приёмы, как, скажем работа с COM - Axapta Business Connector или организация многомерных массивов.

Название третьей главы "Что должен знать эксперт" говорит само за себя.

Мои любимые параграфы те, где речь идёт о создании и вызове сущностей системы, таких как формы, меню, запросы и так далее, напрямую из кода.

Особенно приятно, что она написана русскими ребятами на хорошем русском языке.

В целом, оценивая этот беспрецедентный по охвату материала, стройности и стилю изложения и оригинальности концепции труд, можно сказать, что данная книга является краеугольным камнем в построении карьеры разработчика MS Dynamics.

Wednesday, February 18, 2009

XPO file viewer

When you deal with a pile of Axapta project files (xpo-files) it might be very useful to take a look at what it consists of.

For this goal, I created a small application that allows to see the content of an XPO file in Tree view as you got used to see during the import procedure in AX.

No need anymore to load AX, just launch XPOViewer.exe (from archive) and open the file you want to see. You can also start this application by double-click on files having set it as default system action: by xpo files association.

Loading large project files can take much time, so, be patient and enjoy the progress bar.

In the Tree view you can copy any branch text to your clipboard by Ctrl-C key combination or from the context menu.