Showing posts with label Dynamics AX. Show all posts
Showing posts with label Dynamics AX. Show all posts

Wednesday, 3 November 2010

Dynamics AX Easter Egg

Jacob posted this easter egg on his blog - funny little thing
I know it's a "bit" off-season, but funny nonetheless

static void easterEgg(Args _args)
{;
    info(conPeek(new HeapCheck().createAContainer(), 4));
}

Sunday, 20 December 2009

MSDN with wiki content on AX 2009

There are many reasons why we bloggers blog, depending on the type of posts you post of course. Some rant about their personal relationsships, some about political stuff, and yet some about their work and / or hobbies. I fall into the last category - my posts are for myself ( so I don't forget stuff ) and for other AX people, much in the same way as Willy. When I started on AX development I knew only very little about programming in practice and very much about theory ( having a MA in Information Technology ). During my studies I buddied up with Tino at the VISL-project where I did the user-oriented studies and he did the programming ( his programming skills are still out of this world ).

So when it got round to AX development, I was scared s**tless over the lack of how-to's, documentation and manuals for AX. Much of know-how seemed to be anchored in the people who somehow were in contact with the Damgaard company or former Damgaard employees and the most common respons to programming problems was "see if you can find similar functionality in the std. application, and steal with pride". However, many of the problems were not represented in the std. application though of such a general nature, that someone out there must have a solution or hint to how to solve it. And this is where blogs and forums enter the scene. There are a plethora of blogs and forum posts out there which deal with, suggest solutions to an almost ever increasing pool of good questions ( imo - there are no stupid questions ).
Two of the sites which helped me - and continue to do so - are Axaptapedia and the Axapta Programming site and to a lesser extend MSDN, and this blog is my way of repaying the AX community in the same way I was helped in my hours of need for specific problems, and general discussions on AX related stuff.

Then I read the Microsoft Dynamics AX SDK Updates Blog and as of Nov. 10th Community content ( or wiki content ) can be added to articles ( currently only SDK 2009 - but 4.0 is in the making ). Great days are ahead of us - more books on X++ development are published now than when I started, the most recent ( 'Microsoft Dynamics AX 2009 Programming : Getting started' by Erlen Dalen ) appears to be an up-to-date of Steen Andreasen's MorphX IT ( which I still recommend to new AX developers ), but adding the possibilty of contributing to MSDN will increase it's overall value to AX developers out there. Kudos to the MS AX2009 SDK team which do a great job adding value to the documentation which was sparse to say the least until an increased effort from MS came about some years ago.

Happy hacking,
Steffen

Tuesday, 24 November 2009

Pass by reference vs. pass by value

This one is for myself, as I often forget how to implement pass by reference and pass by value, and what the difference is between them.
Pass by reference:

Declare varible and set it :
SalesLine salesLine = salesLine4

Down-side is if salesLine4 changes - so does salesLine

Pass by value:

SalesLine salesLine;
salesLine.data(salesLine4);

Happy ax-hacking

If salesLine4 changes - salesLine doesn't

Monday, 16 November 2009

Deleting duplicate records in SQL

Recently I needed to delete some duplicate records across several companies in AX. The table is self-contained so I needn't worry about delete actions or validation and as there are several companies I wanted to try and do it SQL-style. So this is what I came up with

DELETE FROM [Table with Duplicates]
WHERE [Primary Key Field] IN
DELETE FROM [Table with Duplicates]
WHERE [Primary Key Field] IN
(
SELECT a.[Primary Key Field]
FROM [Table with Duplicates] a,
[Table with Duplicates] b

WHERE a.[Primary Key Field]!= b.[Primary Key Field] -- i.e. Userkey
AND a.[Value to check]= b.[Value to Check] -- i.e. Lastname
AND a.[Second Value to Check] = b.[Second Value to Check] -- i.e. Firstname
AND a.[Primary Key Field] < b.[Primary Key Field] -- i.e. Userkey
)

Respect to the original poster at SQL Server forum.

Remember always to backup your data and try the SQL-statement on a test table before you do anything on data which will be used in live environments.

Tuesday, 17 February 2009

How to tell if a form was opened with 'Go to main table' function

I found this sample code really helpful in connection with a customization,where the customer wanted to alter the 'Go to main table' function.

Respect to original poster (though I can't remember where I found it - but the idea is not mine)

On main datasource:
public void executeQuery()
{
query q;
querybuilddatasource qbds;
querybuildrange qbr;
int fldLookupField;
str sLookupValue;
;
if ( element.args().caller() &&
!element.args().dataset() &&
element.args().lookupField() &&
element.args().lookupValue()) //jumpref
{
sLookupValue =element.args().lookupValue();
fldLookupField =element.args().lookupField();

q=this.query();
qbds=q.dataSourceTable(this.table());
qbr=qbds.addRange(fldLookupField);
qbr.value(sLookupValue);
this.query(q);
}
super();
}

Monday, 20 October 2008

RunBase - classes and Best Practice

There are certain classes which serve as excellent templates. One such class the LedgerExchAdj-class. If only all runbase-classes were as this one. In my opinion its simplicity and readability is top-notch. I've edited the class-specific code so that only the run() template is present, which included that all important error handling, which one might forget



public void run()
{
#OCCRetryCount
;

try
{
ttsbegin;
// Insert code here
ttscommit;
}

catch (Exception::Deadlock)
{
retry;
}

catch (Exception::UpdateConflict)
{
if (appl.ttsLevel() == 0)
{
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::UpdateConflictNotRecovered;
}
else
{
retry;
}
}
else
{
throw Exception::UpdateConflict;
}
}
}

Friday, 3 October 2008

Setting Cross-reference update in a Schedueld task

An updated Cross reference is an indispensable tool when developing for AX but the client-side dependency can be annoying. So after a little research I found the command line parameter/Windows build-in Scheduled task combo and it does the trick.

In the class SysStartupCmd's construct the command line parameter compileAll-startup command the the parm _+ instantiates a complete compile and cross reference update which means that if you set-up a Scheduled task in Window's standart scheduled task tool with the parameter -startupcmd=compileAll_+ you can update when it suits your development team best.

Tuesday, 26 August 2008

MB6503 - AX 4.0 Installation and Configuration certification

So, I've done it - I got my AX 4.0 Installation and Configuration certification. Actually this test was harder than I expected it to be but there's my five cent worth of advice for those of you who are preparing to take this exam. RTFM ( here an abbreviation of read the fun manual). Nearly all the answers are to be found in the Installation and Configuration manual provided by MS. Hands-on experience will also greatly increase your chances of passing this test, in my opinion.

Wednesday, 20 August 2008

OpenOffice and Dynamics ax

Here is an example of how to use OpenOffice together with Dynamics AX (code-wise of course)

static void Job2(Args _args)
{ COM OpenOffice;
COM DeskTop;
COM Document;
COMVariant arg;
Array arr = new Array(Types::String);

//Creating instance of OpenOffice.org
OpenOffice = new Com("com.sun.star.ServiceManager");
DeskTop = OpenOffice.CreateInstance("com.sun.star.frame.Desktop");

// create and initialize a COMVariant object
arg = COMVariant::createFromArray(arr);
//Creating the document
Document = DeskTop.LoadComponentFromURL("private:factory/scalc", "_blank", 0, arg);
}

Original post by Ivan Kasperuk

Monday, 7 July 2008

How to close a form after a certain timespan

Sometimes it would be really nice if a form closes automatically after a certain timespan. I found it particulary useful in ShopFloorControl, where end-users might not have a mouse to point to close on a form.

On the forms run:

public void run()
{
str JmgJobId;
// Define variable for timeout
// Created with new int on JmgParameters
int TimeOut = JmgParameters::find().JmgRegistredOnJobPromptTime;

// Check if there is a parm
if(element.args().parm())
{
JmgJobId = element.args().parm();
jobIdTxt.text(JmgJobId);
}

super();

// Close form after TimeOut
this.setTimeOut(identifierstr(close),TimeOut);
}



Monday, 28 April 2008

Inside Microsoft Dynamics AX 4.0 free e-book

Harish Mohanbabu was kind enough - per proxy qua his blog - to bring to my attention that MS has release a free e-book edition of Inside Microsoft Dynamics AX 4.0 here as a pdf. I quite like the book as it serves both as an introduction to general X++ development and as a reference guide for more specific programming problems.

Friday, 18 April 2008

Applying agile software development to Dynamics AX development part I

Ever since I wrote my thesis at university, I've pondered the fine art of software development methodologies. During my last year at the University of Southern Denmark I "shopped around" and followed a myriad of software related courses, e.g. Agile software development, User-centered software development, and other iterative and waterfall based software development processes. These development methodologies all have ther merits and flaws, which will be well known to any software developer and the process of merging business processes and software development processes is notoriously difficult, though it is of the utmost importance in order to achieve the best results, business- and softwarewise.

The courses I followed at university were mainly concered with the whole development process(es) from early conceptualization to post-installation maintenance, including GUI-development and Business Intelligence reports. Therefore when I started developing (or should I say customizing -a point to which I will return later) Dynamics AX for customers, my craze - User-Centered Design - slowly fell to the background. Is customizing an ERP-programme, such as Dynamics AX, merely a question of replicating exsisting business processes, with some optimization, and merging them into a new ERP-application or is the development of an ERP-solution an almost god given chance to take a critical bird's eye view of the whole organization and try to optimize business processes all the way r0und? The latter would seem the obvious answer but this again begs another question, viz.: can business processes be optimized isolated from the software development process, when the software has a central place in today's organizations? No. Of course it cannot.

All to rarely is there any substantial software development theory included in the business development plan for the implementation of a ERP-system. Traditional user-experience studies / examinations are left behind, because the UI is developed for us, as part of the standard application in the Dynamics-series, and it is 'just' (I know I'm a bit hard here - but I'm trying to get my point through) a question of rearranging data-presentation, based on the customer's prior ERP-system or an external system. All too often does the customer say something like 'that's not the way it was in the other system' when confronted with an newer version of, lets say Dynamics AX.

So the big question is: how do we - as software developers and business consultants - merge the two worlds and come-up with a process which will lead to sound business optimization and software development integrity?

Tuesday, 8 April 2008

Import items into InventTable and associated tables

Yesterday I needed to import item data into a company for testing purposes, so I wrote a small job which reads an csv-file containing itemId and itemName and creates the posts in InventTable and its associated tables, InventTableModule and InventItemLocation

static void InventTableImport(Args _args)

{
//
//Author : Steffen Denize
//Purpose : Demonstration for importing InventTable into Dynamics AX
//
InventTable inventTable;
CommaIO inFile;
Filename filename;
Dialog dialog;
DialogField dialogField;
ItemId itemId;
int counter;
InventTableModule inventTableModuleBuf;
InventItemLocation inventItemLocationBuf;
ItemName itemName;
;

//
// Note - In this example, I have used 'Dialog' & DialogField classes
// as a tool for me to select the file that has to be imported.
//
dialog = new Dialog("Demo of import of items into a blank InvenTable");
dialogfield = dialog.addField(typeid(Filenameopen), "File Name");
dialog.run();

if (dialog.run())
{
filename = (dialogfield.value());
}

//
// Note - In this example, I have used CommaIO class. But you can also use
// AsciiIO class as well. Basically all these classes (AsciiIO, CommaIO,
// Comma7Io etc) derives from 'Io' base class. For more info, please
// refer to Io class.
//
inFile = new CommaIO (filename, 'R');

if (!inFile || infile.status() != IO_Status::Ok )
{
//strfmt - function for formatting text string
throw error (strfmt("@SYS19312",filename));
}
ttsbegin;

// Set the delimiters
infile.inFieldDelimiter(';');
infile.inRecordDelimiter('|');

//Checking status of last operation
while (infile.status() == IO_status::Ok)
{
// Setting container according to datatypes
[itemId, itemName] = infile.read();
if (itemId)
{
if(!InventTable::find(itemId).RecId)
{
inventTable.initValue();
inventTable.ItemId = itemId;
inventTable.ItemName = itemName;
// These values must be set on their respective tables.
// Here the value are hard-coded into the import as the import
// serves a demo purpose only
inventTable.ItemGroupId = 'TST';
inventTable.ModelGroupId = 'TST';
inventTable.DimGroupId = 'TST';
inventTable.Insert();

// Values must be setup in inventTableModule, which in Dynamics AX 4.0SP2 has three valid arrayelements
// purch, sales, invent (DEL_smmQuotation is not included in this job)
for(counter = 0; counter <= 2; counter++)
{
inventTableModuleBuf.ItemId = inventTable.ItemId;
inventTableModuleBuf.ModuleType = counter;
inventTableModuleBuf.insert();
}

InventItemLocationBuf.ItemId = inventTable.ItemId;
InventItemLocationBuf.inventDimId = InventDim::inventDimIdBlank();
InventItemLocationBuf.insert();
}
}
}
ttscommit;
}

Please notice that the posting is provided "as is" with no warranties and confers no rights

Friday, 28 March 2008

First impressions of Dynamics AX 2009 CTP

Well, I had my first experiences with the CTP of the upcoming version of Dynamics AX - the 2009 edition - and I must say that if you found the changes from 3.0 to 4.0 hard to adapt to, then this upgrade is going to blow your shoes off. The user-interface is brand new, and the consolidation of user experience across the whole range of Microsoft products is beginning to shows its value. Many hings users know and are accustomed to in other products are now present in Dynamics AX 2009, among other things the ribbon, known from Office 2007, and the navigation pane.

As a system engineer, I naturally looked for new things on the developer side of the upcoming version. On of the things I really missed in 4.0 was a build-in version control option. I know you had the option of installing a VSS-server to take care of Version Control for your installation, but the installation process was cumbersome, in my opinion; especially if you only required version control for a single installaion. In the CTP of Dynamics AX 2009 you have no less than four different option of Version Control at your finger-tips.
This will really ease the use of version control as the development team can chose exactly the type of version control which suit their needs. The MorphX VCS is a local, application integrated version control, which does not require any further software installation, which makes it perfect for smaller development teams, which might not have a use for the Team Foundation Server or a Visual SourceSafe. The MorphX allows the development team to check whole projects or single/multiple items from the AOT and has the option of adding descriptions.


Another nifty feature is the export to Excel-button, which pretty much exports the current records to an Excel-spreadsheet. This is an easier and faster way to extract simple data, which most likely will come in handy for a large number of users.


These are just some of the changes in the upcoming version of Dynamics AX 2009 and my first impressions are that the consolidation of user-interfaces across other MS products will ease the transition from previous version of Dynamics AX to upcoming 2009-ed.

Wednesday, 26 March 2008

Dynamics AX 2009 CTP3 release

Here it is - the first widely distributed prerelease of the upcoming version of Microsoft Dynamics AX 2009.

It's available for download from PartnerSource (requires a PartnerSource login).

One of the many exciting new features is the Role centers and the new integration with Microsoft Project Server. I'm personally really looking forward to getting my hands on this CTP3 and experiencing many of the new features which this upcoming version has to offer.
You can find a comprehensive description of the features in the Dynamics AX 2009 on PartnerSource from the What's New in Dynamics AX 2009 (requires a PartnerSource login).

Hope you find the CTP3 as exciting as I do.

Tuesday, 16 October 2007

Faster data import in Dynamics AX

So here it comes - my first real post. I've been having some difficulties when importing data into an exsisting application. It takes forever, especially with tables CustTrans and LedgerTrans, so I browsed the net and found this tip.

Notice that you will lose audittrail of the transactions.

The tip is as follows :
Go into Class SysDataImport, and into the method : updateTransactionId()

Make it return early as possible from this method, and everything goes quick.
Just create it like this :

private void updateTransactionId(TableId _tableId, CreatedTransactionId _oldCreatedTransId, ModifiedTransactionId _oldModifiedTransId)
{
CreatedTransactionId newTransId = 0;
;
// Return as early as possible to increase import speed
return;
if (!hasTransIdSupport)
{
return;
}

if (hasCreatedTransId[tableIds[_tableId]])
{
.
.
.
}


Do likewise with method updateTransactionIdReference().



This posting is provided "AS IS" with no warranties, and confers no rights.