Screencast updates on Dynamics AX Business Intelligence
Microsoft again did a fantastic job by providing us yet another platform. This contains a very focused information over SSRS and AX. Don’t wait! Click here.
6 steps to take backup of all the objects from ‘user’ layer
While working on client side with lot of customizations, someone must take the backup of all the changes which already have done in an application. A very short way of taking backup from a selected layer is as follows; 1. Create a new project and open it. 2. Click on the Advance filter/Sort for this project, it will open the following screen Note: Make sure the above options should be selected for this scenario. 3. Click on ‘Select’ button. 4. Remove all the ranges from this query form and add only one range. The form will now looks like this; 5. Press OK, form will be closed 6. Press OK The new project will contains the entire objects, group by their consecutive groups.
Microsoft Dynamics AX Recorded Webcasts
It’s like a dream to have a bulk of videos over Dynamics AX at one place. Advance System Integration did it for us and I am glad to share it with you here Webcast Title Topic Area Recorded Date Microsoft Dynamics AX 2009General Functional Overview Demo General AX October 23, 2008 – Video Microsoft Dynamics AX 2009General Technical Overview Demo General AX November 6, 2008 – Video Live Webcast: Upgrading to Microsoft Dynamics AX 2009 General AX November 4, 2009 – Video Microsoft Dynamics AX 2009Financial Module Demo Finance November 20, 2008 – Video Microsoft Dynamics AX 2009Project Accounting ModuleDemo Accounting January 14, 2009 – Video Microsoft Dynamics AX 2009CRM Module Demo CRM June 2, 2010 – Video Microsoft Dynamics AX 2009CRM Module Demo CRM February 25, 2009 – Video Live Webcast: Microsoft Dynamics AX 2009Inventory Management Trade & Logistics October 21, 2009 – Video Live Webcast: Microsoft Dynamics AX 2009Enterprise Portal Enterprise Portal November 18, 2009 – Video Learn More about Inventory II: A Powerful Extension of the Standard Microsoft Dynamics AX Inventory Module AX Extension-Inventory Management April 1, 2009 – VideoMarch 31, 2010 –Video Learn More about Inventory II: Another look at Inventory II: A Powerful Extension of the Standard Microsoft Dynamics AX Inventory Module from a Financial Users’ Perspective AX Extension-Inventory Management May 5, 2010 – Video AX-SMART Graphical Planning and Scheduling:An integrated drag and drop based planning and scheduling extension for AX production and project modules AX Extension-Inventory Management June 23, 2009 –VideoJanuary 13, 2010 –Video June 16, 2010 – Video Learn More about TARGITBusiness Intelligence Software AX Extension – BI July 15, 2009 – Video Better and faster decision making is only clicks away in Microsoft Dynamics AX with ASi’s Complete Business Intelligence Suite (Powered by timeXtender) AX Extension – BI May 21, 2010 – VideoJuly 23, 2010 – Video
Filter datasources of same table on Tab Pages
I had a requirement to show the filtered data of one table on different tabs within a form. The standard filter functionality in AX forms is a powerful feature. Using this filter functionality in your code is something you’ll definitely use at some point in time as a programmer. Let me explain it with an example; we have a currency table with multiple currencies e.g. EUR and USD. I have two different tabs named ‘EUR’ and ‘USD’ and these will show the respective filtered data from the currency table i.e. EUR tab will show the EUR currency and USD will show the USD currency data. Add two datasources (CurrencyEUR and CurrencyUSD) on the form of the same table (Currency), after assigning these datasources to the tabpages. You just need to follow the following 3 steps. Step 1: Declare a class variableIn the ClassDeclaration method of the form, define a range.QueryBuildRange CurrencyQBREUR;QueryBuildRange CurrencyQBRUSD; Step 2: Instantiate the new range.In the init() method on the datasource of the form, you assign the range to a specific field (after the super call). DataSource: CurrencyEURpublic void init(){ super(); CurrencyQBREUR = this.query().dataSourceName(‘Currency’).addRange(fieldnum(Currency, CurrencyCode));} DataSource: CurrencyUSDpublic void init(){ super(); CurrencyQBRUSD = this.query().dataSourceName(‘Currency’).addRange(fieldnum(Currency, CurrencyCode));} Step 3: In the last step, you assign a value to the range.This is done in the executeQuery method on the same datasource of the form. Before the super call. Like this: DataSource: CurrencyEURpublic void executeQuery(){ ; CurrencyQBREUR.value(queryvalue(‘EUR’)); super();} DataSource: CurrencyUSDpublic void executeQuery(){ ; CurrencyQBRUSD.value(queryvalue(‘USD’)); super();} This can be done in one line of code as well. In the init() method of the form datasource, after the super call, place this code:this.query().dataSourceName(‘Currency’).addRange(fieldnum(‘Currency’,CurrencyCode)).value(queryvalue(‘USD’)); But this way, it’s fixed. If you choose the 3 step method, you could for example use a variable in the range value. The way to go would be to place an input field on your form. Get the value from it and supply it in the executeQuery() method. For example like this: public void executeQuery(){ ; CurrencyQBRUSD.value(queryvalue(MyInputField.text())); super();} Just make sure the executeQuery method is executed, thus applying the desired filter (maybe be using a button on your form to activate it).
Suppress the scaling message on AX Reports
While working on AX reports, I got a very powerful and useful feature of AX. When a report doesn’t fit on a page, depending on its properties Ax will resize the report. Now AX will inform you that the report has been rescaled (Report is scaled xx percent to fit to page) and this message is generally not well received by users. Users are annoyed by the message, they get it every time they run the report, they cannot do anything about it, and they have to click to close the infolog. In order to get rid of this message on a particular report you can just modify the init() method of that report and add this line of code. this.printJobSettings().suppressScalingMessage(true); How about to cut the roots of this message and just change on one place then you can get rid of this message on all the reports rather than to go on each report and modify its init() method. Go to class SysReportRun, in the Run method, place following code before the call to super:if(this.printJobSettings())this.printJobSettings().suppressScalingMessage(true); Now we don’t have to modify each and every report and our users are happy. Note that you can still override the settings in your report. In some reports this is done by default, like SalesInvoice and SalesConfirm.
Pack/Unpack Mechanism to reduce the RPC Count for Temporary Table
Many a times it’s becomes our need to use the temporary tables while displaying data either on the forms or dialog forms. We all are aware of how to use temp table in AX and also with this fact that there is always being a performance impact (chattiness between client & server) to insert data in temp table. We can use pack/unpack mechanism to reduce this chattiness and pack the whole temp table data once on client and use it on the server. You can use this mechanism like below, Create a temporary table like in my case I created it with name “ProjTmpBudgetDisplay” Create a class like in my case I created it with name “ClassTmpBudgetDisplay” Create a form and override its init() method
Delete Actions
Sometimes its rare to have all the information about DELETE actions on the table and we read books and google it. This post will really helpful in describing how to create delete actions on tables and which Delete action should be used and when? There are two purposes to define the delete actions on the table level; § Restrict the deletion of a record based on related records in another table § Cascade the deletion of a record to related tables to ensure data-consistency How can I add delete actions in table? Delete actions are added in the AOT, by right-clicking on the DeleteActions node of a Table AOT element. Select New DeleteAction and then select the table on which this delete action will be based. There are three different types of delete actions 1. Cascade 2. Restricted 3. Cascade + Restricted What are the basic types of Delete action? Cascade A cascading deletion action will delete all records in the related table, where the foreign key is equivalent to the primary key of the current table. That is, deleting the parent record will also delete the child record(s) in the related table. This cascading will take place whether the deletion is performed in code or directly by a user through the user interface. Restricted A restricting delete action will raise an error message if the user tries to delete a record, where records exist in the related table where the foreign key is equivalent to the primary key of the current table. This error will only appear if the deletion is performed through the user interface. A deletion from X++ code will be allowed to proceed and will not be cascaded to the related table. In this case the programmer should call .validateDelete() themselves prior to the call to .delete() Cascade + Restricted The delete action performs a restricted, if the record of the table will be deleted directly and performs a cascade, if the record of the table will be deleted through a cascade delete action of a other table. For example: When a record of SalesOrder table will be deleted, the restricted part of the deleteaction will be performed. The record of SalesOrder can only be deleted, if no record in SalesLine exist for the record in SalesOrder. (The SalesOrder can only be deleted, if no SalesLine exist for the SalesOrder). A record in Customer will be deleted, so the cascade deleteaction to SalesOrder will be performed. In this case, the cascade part of the deleteaction to SalesLine will be performed. (When a Customer will be deleted, the SalesOrders and SalesLines will also be deleted)
Round() function for SEAL and FLOOR values in X++
static void SealORFloorValues(Args _args) { AmountMst amount; amount = 2.4; print round(amount, 1); pause; } // if value is 2.5 then it will print 3 // if value if 2.4 then it will pront 2
Financial Dimensions
Here are some useful videos which I found from Sunrise Consultants site: Financial Dimensions Overview: Definition of financial dimensions within Microsoft Dynamics AX Financial Dimensions Processing: Using the financial dimensions in Microsoft Dynamics AX Financial Dimensions Reporting: Reading financial dimensions in a report from Microsoft Dynamics AX Financial Dimensions Setup: Setting up the parameters of financial dimensions in Microsoft Dynamics AX
Debugging X++ code in Dynamics AX
When you are developing X++ code for Dynamics AX over the time you will run into a situation where the below Tips & Tricks can make your debugging live easier. The informations are very rare to find at one place. Since I was also once in the situation needing to find them, I thought it maybe a good idea to collect the most useful ones I’m using day to day… The most oblivious one: Interrupting the code execution When you have written some code that is causing an endless loop (or a very long execution) and you want to know what code is currently keeping the client busy. The easiest way is pressing [Ctrl] + [Break] on the keyboard. This will stop the code execution and show up a message box: Are you sure that you want to cancel this operation? If you hold down the [Shift] button on the keyboard while you click at the No button of the message box, the AX Debugger will be launched exactly at the line of code that was about to be executed. From here you can continue to step over / into line by line and try to identify the cause of your endless loop. The breakpoint is sometimes not hit? Sometimes it happens that a breakpoint is not hit although you are sure the respective code was executed. For example if you want to debug code behind User Controls like Form buttons this can happen. Here instead of putting a breakpoint at a line of code insert the breakpoint keyword. public void executeQuery(){;breakpoint;super();} Please note that using breakpoint has a serious side effect: The breakpoint will be hit by all user sessions! This is definitely something you don’t want to do in a live environment. How can I see the call stack that resulted in X++ exception? When you run into an exception that is showing up in the InfoLog usually double clicking at the error brings you to the line of code where the error was raised. Sometimes knowing the line of code where the error was raised is however not good enough as the individual call stack is what you need to know. Putting a breakpoint at the line of code where the exception was raised is helpful, what however if you are in a loop and you don’t know what loop iteration results in the error especially if the error is random? Instead of putting the breakpoint at the line of code where the exception might be raised, put a breakpoint in the addmethod of the Info class, e.g. at the line switch (logLevel). Exception add(// …;switch (logLevel)// … Info::add is always called when something is written to the InfoLog and since an exception shows up in the InfoLog as soon as the exception was raised the Info::add method is called and here you will hit your breakpoint. How can I get the current X++ call stack? The static method xppCallStack() of the xSession Kernel class returns the current X++ call stack: //…Info(con2str( xSession::xppCallStack() ));//… The function funcname() returns the name of the method where it has been called. public void executeQuery(){;Info( funcname() ); //In this case “executeQuery” will show up in the InfoLog super();} How can I see the SQL query that the Dynamics AX Kernel is generating for my Form? When you are debugging your solution, sometimes you might want to see the SQL Query the Dynamics AX Kernel has generated for your Form. While you can of course trace this directly at your Database Server, you also can do this in X++ using the QueryBuildDataSource class. Let’s imagine you have a Form that has PurchTable as Data Source. You have to override the executeQuery method of the PurchTable Data Source and add the following code: public void executeQuery(){Query q;QueryBuildDataSource qbds;;q = this.query();qbds = q.dataSourceName(“PurchTable“); //Replace with the current Tableinfo( qbds.toString() ); super();}