Powered By Blogger

Friday, July 2, 2010

Exporting table data to a xml doc in Ax using X++

Main thing which is associated with XML in Dynamics AX is the AIF that allows exposing business logic or exchanging data with other external systems. The communication is done by using XML formatted documents. By using existing XML framework application classes prefixed with Axd, you can export or import data from or to the system in an XML format. It is also possible to create new Axd classes using the AIF Document Service Wizard from the Tools Wizards menu to support exporting and importing newly created tables.

Apart from this AX also contains a set of application classes prefixed with Xml like XmlDocument, XmlNode etc to handle the xml import/export which are basically wrappers around the System.

This recipe to show the principle of XML, we will create a new simple XML document by
using the standard xml classes. We will create the file with the data from the chart of accounts table and will save it as an XML file.

just copy the below code and put in a new class named as 'CreateXmlFile' and run it....it will create the xml file at C:\ with the name of 'test'...


public static void main(Args _args)
{
XmlDocument doc;
XmlElement nodeAccount, nodeName, nodeTable, nodeXml;
LedgerTable ledgerTable;
#define.filename("C:\\Test.xml")

;

// Creating a new XmlDocument, which represents an XML structure using its newBlank() method.

doc = XmlDocument::newBlank();

// create it's root node named xml using createElement(), and add the node to the document by calling appendChild().
nodeXml = doc.createElement('xml');
doc.appendChild(nodeXml);

// Query on the table and use the fields which we wanted to include in the xml file.

while select ledgerTable
{
nodeTable = doc.createElement(tablestr(ledgerTable));

nodeTable.setAttribute(fieldstr(LedgerTable, RecId), int642str(ledgerTable.RecId));
nodeXml.appendChild(nodeTable);

nodeAccount = doc.createElement(fieldstr(LedgerTable, AccountNum));
nodeAccount.appendChild(doc.createTextNode(ledgerTable.AccountNum));
nodeTable.appendChild(nodeAccount);

nodeName = doc.createElement(fieldstr(LedgerTable, AccountName));
nodeName.appendChild(doc.createTextNode(ledgerTable.AccountName));
nodeTable.appendChild(nodeName);
}

doc.save(#filename);
}

Thursday, June 24, 2010

How to open a form in workspace in DAX2009 like in AX 4.0

ALL,

You all might be aware that all forms in Ax2009 are behaving like an independent application forms and used to open in a separate window which becomes a bit cumbersome 2 handle.

While doing some work over it, i found something not to go with this and restrict DAX to open the forms in workspace rather in a separate window as a workaround (though it's an intentional design in product).

There are two ways to handle it..
1. Just put the below code to the 'SysSetupFormRun' class b4 super() call.

this.form().design().windowType(FormWindowType::Workspace);
super();

2. Change the formdesign property windowtype from standard to workspace. This has to be done for all the forms user wanted 'not 2 open' in a separate window.

Enjoy same feel 2 work in DAx2009.

Cheers DaXing.......

Friday, June 18, 2010

Workfow being submitted multiple times by clicking submit button

During working with workflow i have seen this issue in standard Ax.
Click on submit on your main form, wait for the comments dialog to appear, change focus back to your main form again and click on submit again.

Now click the ok/submit button on your two comments dialogs and unless you have added some extra checking down the line, your record will be submitted into workflow twice, be assigned twice, approved twice (if the approver doesn’t catch on) -:)......seems to be horrible for me , even faced the same issue in standard Ax Purcahse requisition workflow. ...see below screen




Found two ways to handle this as below---

1. Put an additional check after your your .dialogOk() call and before your activateFromWorkflowTemplate() to see if the record has been submitted.

2. Go to form 'WorkflowSubmitDialog' Form and add below code to 'wait' method.

public void wait(boolean _modal=false)
{
// super(_modal);
//Comment this standard overriden line and call super
super(true);
}


But still i think issue need to be fixed in standard Ax as it doesn't make sense to submit the workflow multiple times...

Tuesday, May 11, 2010

Workflow doc

Dear All,
find the attached work flow document which will help you to understand the work flow configuration and initial development.

http://www.docstoc.com/docs/38308697/workflow-guide

hope it helps -:)

Wednesday, April 28, 2010

Spell checker in Ax

There is a class in AX that allows to perform spell checking. This class uses Microsoft Word spell checker to do the validation. So, in order to use it, Microsoft Word should be installed together with proofing language pack. Because of this requirement it is also important to consider where to run spell checking - on the server or on the client.

public static server void spellCheckerTest()
{
SysSpellChecker sp = SysSpellChecker::newLanguageId('en-us');
;

info(strfmt('%1', sp.checkSpelling("behavior")));
info(strfmt('%1', sp.checkSpelling("behaviour")));
}


The output in infolog will be as below :-
1
0

Monday, April 19, 2010

Identical AX 2009 AUC File Created For Multiple AX Installations

We came across an issue recently where we had the same GUID for two different AX installations running on the same server and therefore only one AUC file existed for both installations instead of two separate ones for use by the AX Client.
This caused various anomalies when the client was used to access both instances. We expect each of the AX installations having their own separate objects and application files associated to the AUC file.

In order to ensure that a unique AUC file is created per instance for the AX client to use, and also to ensure that the AX instances had a unique Global GUID, the solution was to delete the GlobalGUID from the SysSQMSettings table in one of the instances and replace the value with an empty GUID (00000000-0000-0000-0000-000000000000).
Then restart the AOS service, as this will then generate a new GUID and allows a new AUC file to be created for the AX client when it is next run.

The above problem was most likely caused by using a copy of the same database.

The GUID is stored in the SysSQMSettings table and is unique for each AX installation.
You can find it by using the following Select statement:

" select GlobalGUID from SysSQMSettings ".. even you can have a look for the below job as well which will give you GUID and recId.

static void getGUID(Args _args)
{
SysSQMSettings SysSQMSettings;
;
select GlobalGUID from SysSQMSettings;

info(strfmt('%1, & rec id is -- %2', SysSQMSettings.GlobalGUID, SysSQMSettings.RecId));

}

Wednesday, April 7, 2010

Ax session issue in Axapta

Some Axapta system administrator may feel it is really annoying that Axapta allows the user to create multiple Axapta sessions and log in as the same user. If you want to give the user notification prior to logging in as the same User ID, see the below code. Under the Info class, modified the startupPost method something like below:

void startupPost()
{
int counter;
int num = 0;
int maxSessions = Info::licensedUsersTotal();
xSession session;
UserInfo userInfo;
UserId currentUserId;
;

currentUserId = curuserid();
for(counter = 1; counter < maxSessions;counter++ )
{
session = new xSession(counter, true);
if(session && session.userId())
{
select firstOnly userInfo where userInfo.id == session.userId();
if (userInfo && (currentUserId == session.userId()))
{
num++ ;
}
}
}
if (num > 1)
{
if(box::yesno("The same user id can't log in twice. Do you want to log in anyway? ", DialogButton::Yes, "Log in", "Log out") == DialogButton::No)

{
infolog.shutDown(true);
}
}
}

Tuesday, April 6, 2010

Code snipet 2 remove the identical copy of AOT object

For some unknown reasons, sometimes AOT objects are touched in VAR layer but actually are identical copies. When the developer compared the VAR layer object with the one in lower layer (BUS, SYS etc.), AX showed it was an identical copy and no difference as such.

Below is the code example on how can we remove the identical copy in X++ 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.name == UtilElements.name && joinUtilElements.recordType == UtilElements.recordType;

if (joinUtilElements.RecId)
{
curLevelTreeNode = SysTreeNode::findNodeInLayer(UtilElements.recordType, UtilElements.name, 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", UtilElements.name, enum2str(UtilElements.recordType)));
//Remove the node
curLevelTreeNode.AOTdelete();
}
}
}
}

It's a bit cumbersome here while pasting, but i think its gives an overview to understand the fact :)

Revised layer version in DAX 2009

In Microsoft Dynamics AX, a layer system is used to manage application objects. A single index file named Axapd.aoi automatically makes sure that the top-level version of an application object is always used. The USR layer is the top layer and the SYS layer is the bottom layer. The following illustration shows the 10 Microsoft Dynamics AX layers.





For example, when a user opens a form, a check is made to determine whether there is a USR layer version of the form. Next, a check is made to determine whether there is a CUS layer version, and so forth, until the SYS layer version is used.

Most application objects, such as tables, fields, indexes, enum types, and extended data types have unique application object ID numbers in addition to names. Microsoft Dynamics AX uses an application object ID number series corresponding to the layers, as shown in the following picture.


When an application object is created, Microsoft Dynamics AX automatically manages the application object ID and assigns a new ID. If you modify an existing object, the application object keeps its original ID and is not assigned a new ID in the same layer. If you move an application object to a new layer, a new ID is automatically assigned.
Note- If you delete the layer file, you should also delete the index file to make the system regenerate it.

Tuesday, March 30, 2010

SQL clustering

http://www.docstoc.com/docs/32088055/Document-to-understand-the-SQL-clustering
Clustering mainly refers to a group of two or more servers (generally called nodes) that work together and represent themselves as a single virtual server to a network.

Follow the above link to get the doc attached describing the basics of SQL clustering.

DAX09_GAB functionality

http://www.docstoc.com/docs/32087697/Dynamics_AX09_Global_Address_Book

I ahve uploaded one doc prepared by a MS consultant. It really helps to understand the Global address book functionality in DAX 2009
....Enjoy wth GAb

Monday, March 29, 2010

Axapta keyboard short cuts

Press this To do this Command

Tab Go to the next field Next Field
Ctrl+PgDn Go to the next field group Next Field Group
Ctrl+Shift+End Go to the last entry field in the form Last field
Alt+F9 Delete a record Delete Record



use the above link to download the doc which describes few more such shorctuts on DAX
...........enjoy shorctutting -:)

Friday, March 19, 2010

SQL Tracing in AX

Normally results of SQL Tracing is stored in SQL table, browsable from Axapta itself. The only reason for usage of SQL Tracing to log-file is a special request from Microsoft support team (because it is much easier to e-mail a log-file than log-table).

(A)
SQL Tracing work ONLY if your AOS configuration has “Allow client tracing on Application Server Instance” setting checked. In versions 2 and 3, SQL trace worked independent from any server configuration settings, so I was little surprised when I tried to run familiar SQL trace on DAX4.0 without any results. It seems,that in attempt to gain couple of extra percents of performance, DAX kernel’s team decided to make this SQL tracing globally switchable starting from version 4.0.

(B)

If you are trying to log SQL Trace into file, expect to find this file ON SERVER SIDE. In versions 2 and 3, SQL trace file was being stored on local log directory. Starting from version 4.0, SQL trace file is being stored on Server side log directory. Probably, this is because performance team decided to completely decouple tracing process from client. Before attempt to commence SQL Tracing to file, please ensure that your AOS user (I mean – AD user, under which account AOS is run) has enough rights to create and write files in log directory. (Normally, It is something like C:\Program Files\Microsoft Dynamics AX\50\Server\DynamicsAx\Log).

Apart from this we have Server & Client tracing also in Ax. wil post that in next blog, bored a bit now -:)

Add Fields to a table, using code In DAX

static void createFieldFromCode(Args _args)
{
#AOT
TreeNode tableNode;
AotTableFieldList myAOTTablefieldList;
SysDictTable sysDictTable = new SysDictTable(tablenum(AX));
;
if (! hasSecuritykeyAccess(securitykeynum(SysDevelopment),
AccessType::View))
{
return;
}
myAOTTablefieldList = new AotTableFieldList();
tableNode = TreeNode::findNode(#TablesPath+'\\'+sysDictTable.name());
myAOTTablefieldList =
TreeNode::findNode(#TablesPath+'\\'+sysDictTable.name() + "\\Fields");
if(!myAOTTablefieldList.AOTfindChild("newField")) // check if the field
alredy exists
{
myAOTTablefieldList.addString("newField");
}
tableNode.AOTsave();
}

Best Article --- check if the Dynamics AX 4 client crashes upon startup


This is a very common error we used to get while working with DAx and found below as a resolution for this..
If you get the following error when starting up a Dynamics AX 4 client and just can't see anything wrong with the configuration or anything else; look into the following folder on your local machine "\Documents and Settings\\Local Settings\Application Data\" for a file named "ax__.auc" and rename it or delete it.


when you want a section of code not to report to the infolog, but still want previous messages to be shown at the end of execution

Try this and see the output
public static void suppressInfolog(Args _args){ int i; ; info("A");
i = infolog.line();

info("B"); //Section of code that will not get reported to the infolog

if (infolog.line() > i) infolog.cut(i+1, infolog.line()); info("C");