Friday, July 2, 2010
Exporting table data to a xml doc in Ax using X++
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
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
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
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
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
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
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
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.
Tuesday, March 30, 2010
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
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
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
http://www.docstoc.com/docs/32087224/Axapta_keyboard_short_cuts
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
(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
{
#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
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
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");