Friday, November 30, 2012

AX 2012 Financial dimension update

Here are 2 ways to update a financial dimension, while keeping the other dims. The result should be the same, just use whatever you prefer

To use those two method proceed like so:

  purchTable = purchTable::find('PURCHID', true);  
  purchTable.DefaultDimension = getNewDefaultDimension(purchTable.DefaultDimension, "COSTCENTER", "YOURVALUE");  
  purchTable.update();  

METHOD NUMBER 1:

 static RecId getNewDefaultDimension(RecId defaultDimension, Name dimName, str 255 dimValue)  
 {  
   DimensionAttributeValueSetStorage  dimStorage;  
   Counter               i;  
   DimensionAttribute         dimAttributeCostCenter;  
   DimensionAttributeValue       dimAttributeValue;  
   dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);  
   dimAttributeCostCenter = DimensionAttribute::findByName(dimName);  
   if(dimValue)  
   {  
     dimAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttributeCostCenter, dimValue, true, true);  
     dimStorage.addItem(dimAttributeValue);  
   }  
   else  
     dimStorage.removeDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);  
   return dimStorage.save();  
 }  


METHOD NUMBER 2:

 static RecId getNewDefaultDimension(RecId defaultDimension, Name dimName, str 255 dimValue)  
 {  
   container c;  
   RecId   newdefaultDimension;  
   int    i;  
   c = AxdDimensionUtil::getDimensionAttributeValueSetValue(defaultDimension);  
   i = conFind(c, dimName);      
   if(!i && !dimValue)  
     return defaultDimension;  
   if(i)  
   {      
     c = conDel(c, i+1, 1);   
     c = conDel(c, i, 1);    
   }  
   if(dimValue)  
   {  
     c += dimName;  
     c += dimValue;  
   }  
   c = conDel(c, 1, 1);  
   c = conIns(c, 1, conLen(c) / 2);  
   newdefaultDimension = AxdDimensionUtil::getDimensionAttributeValueSetId(c);  
   return newdefaultDimension;  
 }  

To get the current value of a financial dimension:

 static str 255 getDimensionValue(RecId defaultDimension, Name dimName)  
 {  
   DimensionAttributeValueSetStorage  dimStorage;  
   Counter               i;  
   DimensionAttribute         dimAttributeCostCenter;  
   DimensionAttributeValue       dimAttributeValue;  
    dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);  
   return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);  
 }  

Monday, November 05, 2012

Enable SalesInvoice report on Enterprise Portal

Continuing the series of articles in SSRS, here I explain how to print the salesInvoice (or any other custom report) in Enterprise Portal.

Despite Packing Slip, this report is not supported in the standard Enterprise portal installation (you don't have the button to print an invoice on the EP invoices list page)

That's because Sales Invoice use a report controller that has not been implemented for the use in EP.

The solution I propose here is a little tricky, but it works pretty well :)

The key is to modify the class EPDocuGet that manages the download of reports or attachments from EP.

In that class you can write some code to print the SalesInvoice PDF to a temporary directory (how to do that is explained in a post before) and then write out the data in HTTP response of the Web request

So in the method run you can do something like:


 void run(Args args = null)  
 {  
   IISResponse       response = new IISResponse();  
 ;  
   // Transition to a server function to avoid  
   // Security problems  
   if (args)  
   {  
     if (args.record().TableId == tableNum(DocuRef))  
     {  
       EPDocuGet::runDocument(args.record().data(), response);  
     }  
     // Begin change  
     // Description:  
     else if (args.record().TableId == tableNum(CustInvoiceJour))  
     {  
       EPDocuGet::DWrunReportSalesInvoice(args.record().data(), response);  
     }  
     // End  
     else  
     {  
       EPDocuGet::runReport(args.record().data(), response);  
     }  
   }  
 }  

So if you got a CustInvoiceJour record you run your custom code. The method DWrunReportSalesInvoice is a copy of the runDocument method, a little bit modified:

 #define.BUFFER_SIZE(4096)  
 #File  
 client static void DWrunReportSalesInvoice(Common callerRecord, IISResponse response)  
 {  
   Query          query = new Query();  
   QueryBuildDataSource  qbds;  
   QueryRun        queryRun;  
   //EPSendDocument     document;  
   BinData         binData;  
   str           fileName;  
   int           fileOffset;  
   DictTable        table = new DictTable(callerRecord.TableId);  
   str           tempFileName;  
   boolean         emptyReport;  
   CustInvoiceJour     custInvoiceJour = callerRecord;  
   ;  
   if (EPDocuGet::hasTableAccess(callerRecord.TableId))  
   {  
     qbds = query.addDataSource(callerRecord.TableId);  
     if (callerRecord && callerRecord.TableId != tableNum(DocuRef))  
     {  
       // Requery the record to test record level security  
       qbds.addRange(table.fieldName2Id('RecId')).value(SysQuery::value(callerRecord.RecId));  
       query.recordLevelSecurity(true);  
       queryRun = new QueryRun(query);  
       if (queryRun.next())  
       {  
         //document = new EPSendDocument(callerRecord);  
         tempFileName = System.IO.Path::GetTempFileName();  
         EPDocuGet::DWPrintInvoicePdf(callerRecord, tempFileName);  
         infolog.clear();  
         //document.parmOriginal(true);  
         //document.parmFileName(tempFileName);  
         // Make document will run the report and send it to a PDF file with  
         // the path specified in tempFileName  
         //document.makeDocument();  
         fileName = custInvoiceJour.InvoiceId + ".pdf";  
         // remove all ';' from the filename. These are treated as delimiters by Ie  
         fileName = strReplace(fileName, ';', '_');  
         emptyReport = (WinAPI::fileSize(tempFileName) == 0);  
         response.clear();  
         binData = new BinData();  
         if (emptyReport)  
         {  
           response.contentType('application/Octet-Stream');  
           response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #txt + '"');  
           response.writeTxt(strFmt("@SYS58533", fileName));  
         }  
         else  
         {  
           response.contentType('application/pdf');  
           response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #pdf + '"');  
           // Loop over the stored file and chunk it down to the client  
           fileOffset = 0;  
           // Assert permission and get the temp filename  
           new FileIOPermission(tempFileName, #io_read).assert();  
           while(true)  
           {  
             // BP Deviation Documented  
             if (!binData.loadFile(tempFileName, fileOffset, #BUFFER_SIZE))  
             {  
               break;  
             }  
             fileOffset += #BUFFER_SIZE;  
             response.binaryWrite(binData.getVariant());  
           }  
           CodeAccessPermission::revertAssert();  
         }  
         binData = null;  
         WinAPI::deleteFile(tempFileName);  
       }  
     }  
   }  
 }  

And here is the method to print the invoice in PDF:

 client static void DWPrintInvoicePdf(Common _record, Filename filename)  
 {  
   args args = new args();  
   CustInvoiceJour custInvoiceJour = _record;  
   SRSPrintDestinationSettings printSettings;  
   SalesInvoiceController controller = new SalesInvoiceController();  
   str pdfPath = filename;  
   args.record(_record);  
   //pdfPath = WinAPI::getTempPath() + custInvoiceJour.InvoiceId + ".pdf";  
   // imposta nome report  
   controller.parmReportName(ssrsReportStr(SalesInvoice, Report));  
   // get print settings from contract  
   printSettings = controller.parmReportContract().parmPrintSettings();  
   // set print medium  
   printSettings.printMediumType(SRSPrintMediumType::File);  
   printSettings.fileFormat(SRSReportFileFormat::PDF);  
   printSettings.overwriteFile(true);  
   printSettings.fileName(pdfPath);  
   // forzo che non vengano cambiati i parametri di stampa che gli passo io  
   controller.DEVparmLockDestinationProperties(true);  
   // suppress the parameter dialog  
   controller.parmShowDialog(false);  
   controller.parmArgs(args);  
   // start operation  
   controller.startOperation();  
 }  


At this point, all you have to do is to create an Output Menu Item with the value "EPDocuGet" in the property "WebMenuItemName" and add this menu item to the EPCustInvoiceListPage form or whatever form you like.

Monday, October 29, 2012

Printing footer on report last page without reserving white space in all pages (AX 2009)

AX 2009 (and prior versions) always had a problem in printing report's footer.

If you want a footer to be printed only in the last page of the report, in the bottom part of the page, you have to condition the last page print by code.

This works pretty well, except that the footer space is reserved in all of the pages, leaving a white space hole in all the pages!

That's a problem in report like Invoices, where you have a big footer with totals and so on.

Normally you would make the footer appear in all pages, so the white space hole will be filled, but that's not a proper solution for some customers.

I found a way to bypass this problem, and is also easy to implement.

The key is to programmatically compute where you are in the page, and how much space will need the footer, so you can move it down or eventually create a new page.

So, here the steps to accomplish that:
  1. Create a programmable section in the report to act as your page footer. Place in this programmable section all the controls that you want to render as the last page footer
  2. Create an empty footer section below the body that fetch your report data, and place an empy "Static text control" inside this footer (otherwise nothing will be rendered)
  3.  Override the method executeSection of the footer with the code below

 public void executeSection()  
 {  
   int pageHeight, currentPos, i;  
   super();  
   if(!CustTable_1)  
   {    
     pageHeight = element.mm100PageHeight();  
     currentPos = element.currentYmm100();  
     if(pageHeight < currentPos + ProgrammableSection.height100mm())  
     {  
       element.newPage();  
     }  
     element.gotoYmm100(pageHeight - ProgrammableSection.height100mm());  
     element.execute(1);  
   }  
 }  

What I'm doing here is, if I ended up printing report data (in this case CustTable is empty) I compute the page height, where I am in the page, and how much space will need the footer.

Then you can print the footer in the proper position, or previously go to a new page if the space needed is not sufficient.



HERE  attached you find an XPO with a sample report


P.S.: My colleagues says that this problem belong also to SSRS reporting on AX 2012. I haven't seen it yet there, if you find a solution feel free to drop a line!



Friday, October 12, 2012

Enhanced table browser

If you find it hard to find fields on the Ax Table Browser, this tool may help you.

It will simply show the visible fields on the right, and you can check/uncheck those that you want to see.

If you experience some problem after installation, clear Usage data for the form



XPO download HERE

Thursday, October 11, 2012

Create custom Alert for AX with Go to Source support

To create an Alert in AX, you can use the class EventNotification and its derivates

I got some problems using these standard classes, particularly in making the button "Go to source" work.

To avoid those problem, here is some code that may help:

 public static void CreateAlert(str message,  
               str subject,  
               UserId userId = curUserId(),  
               NoYes showPopup = NoYes::Yes,  
               NoYes sendEmail = NoYes::No,  
               Common record = null,  
               str dataSourcename = '',  
               MenuFunction menuFunction = null)  
 {  
   EventInbox inbox;  
   DictTable table;  
   EventContextInformation eci;  
   EventInboxData inboxData;  
   Args args = new Args();  
   List list;  
   EventInboxId inboxId = EventInbox::nextEventId();  
   FormRun formRun;  
   WorkflowRecordCaptionGenerator recordCaptionGenerator;  
   UserInfo userInfo;  
   inboxId = EventInbox::nextEventId();  
   inbox.initValue();  
   inbox.ShowPopup      = showPopup;  
   inbox.Subject       = subject;  
   inbox.Message       = message;  
   inbox.SendEmail      = sendEmail;  
   inbox.EmailRecipient    = SysUserInfo::find().Email;  
   inbox.UserId        = userId;  
   inbox.InboxId       = inboxId;  
   inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();  
   if (record)  
   {  
     table = new DictTable(record.TableId);  
     eci = new EventContextInformation();  
     if (!menuFunction)  
     {  
       menuFunction = new MenuFunction(table.formRef(),MenuItemType::Display);  
       if (!menuFunction)  
         throw error(strFmt("@SYS104114",table.formRef()));  
     }  
     //Build the data to drill down to from the notification  
     args.menuItemName(menuFunction.name());  
     args.menuItemType(MenuItemType::Display);  
     args.name(menuFunction.object());  
     eci.parmPackedArgs(args);  
     eci.parmAlertBuffer(record);  
     eci.parmAlertFormDsName(dataSourceName);  
     //eci.parmDontUseFormRunFromMenuItem(true);  
     inboxData.InboxId = inboxId;  
     inboxData.DataType = EventInboxDataType::Context;  
     inboxData.Data = eci.pack();  
     inboxData.insert();  
     inbox.AlertTableId = table.id();  
     inbox.ParentTableId = table.id();  
     recordCaptionGenerator = WorkflowRecordCaptionGenerator::construct(record);  
     inbox.AlertedFor = recordCaptionGenerator.caption();  
     list = SysDictTable::getUniqueIndexFields(table.id());  
     if (list)  
     {  
       inbox.keyFieldList(list.pack());  
       inbox.keyFieldData(SysDictTable::mapFieldIds2Values(list,record).pack());  
     }  
     inbox.CompanyId = record.company();  
   }  
   inbox.insert();  
 }  

To use this code
 static void Job155(Args _args)  
 {  
   InventTable inventTable;  
   select firstOnly inventTable;  
   DEVUtils::CreateAlert("message", "subject", curUserId(), true, false, inventTable, "InventTable", new MenuFunction(menuitemDisplayStr(EcoResProductDetailsExtended), MenuItemType::Display));  
 }  

Sending PEC (Certified E-mail) with AX

A PEC (Certified E-mail) is not very different from a usual e-mail.

You just have to use SSL to secure the connection while sending the mail.

Usually I use the class System.Net.Mail to send mails with Ax, and this one has a useful property named EnableSsl that could work. But with a PEC, no, this isn't working.

That's because, to send a PEC you need an Implicit SSL, while System.Net.Mail only supports “Explicit SSL”.

 Reference: HERE

 And, as stated in the MSDN:

The EnableSsl property specifies whether SSL is used to access the specified SMTP mail server.
The default value for this property can also be set in a machine or application configuration file. Any changes made to the EnableSsl property override the configuration file settings.
The SmtpClient class only supports the SMTP Service Extension for Secure SMTP over Transport Layer Security as defined in RFC 3207. In this mode, the SMTP session begins on an unencrypted channel, then a STARTTLS command is issued by the client to the server to switch to secure communication using SSL. See RFC 3207 published by the Internet Engineering Task Force (IETF) for more information.
An alternate connection method is where an SSL session is established up front before any protocol commands are sent. This connection method is sometimes called SMTP/SSL, SMTP over SSL, or SMTPS and by default uses port 465. This alternate connection method using SSL is not currently supported.

So, if you want to send a mail with Implicit SSL, you have to use a deprecated class from the old 2.0 .NET Framework, that is System.Web.Mail

Using this class is not difficult, and you can find a working sample down here:


 static void SendPECMail(Args _args)  
 {  
   System.Web.Mail.MailMessage  newMail;  
   System.Collections.IDictionary fields;  
   System.Collections.IList    attachementCollection;  
   System.Web.Mail.MailAttachment attachment;  
   try  
   {  
     new InteropPermission(InteropKind::ClrInterop).assert();  
     newMail = new System.Web.Mail.MailMessage();  
     fields = newMail.get_Fields();  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver", "smtps.pec.aruba.it");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", "465");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing", "2");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", "lmattiuzzo@pec.it");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", "password");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");  
     newMail.set_From("lmattiuzzo@pec.it");  
     newMail.set_To("santa@klaus.com");  
     newMail.set_Subject("subject");  
     newMail.set_BodyFormat(System.Web.Mail.MailFormat::Html);  
     newMail.set_Body("body of your message");  
     newMail.set_Priority(System.Web.Mail.MailPriority::High);  
     attachementCollection = newMail.get_Attachments();  
     attachment = new System.Web.Mail.MailAttachment(@"c:\file.pdf");  
     attachementCollection.Add(attachment);  
     System.Web.Mail.SmtpMail::set_SmtpServer("smtps.pec.aruba.it:465");  
     System.Web.Mail.SmtpMail::Send(newMail);  
     CodeAccessPermission::revertAssert();  
   }  
   catch( Exception::CLRError )  
   {  
     throw error(AifUtil::DEVgetClrErrorMessage());  
   }  
 }  

Thursday, July 26, 2012

Print a SalesInvoice, PackingSlip or similar report to PDF in AX 2012

Printing a report in PDF in AX 2012 is pretty simple, but SalesInvoice report, or packing slip and similar seems not to work with the standard way.

That's because even if you pass printSettings parameters those are overriden by the controller class.

In AX 2009 there was a useful method called LockDestinationProperties in printSettings parameters that solve this problem, but this is gone in AX 2012.

So, If you want to reenable this feature, you have to do this:

Open the class SrsPrintMgmtFormLetterController and change those methods:


 void public abstract class SrsPrintMgmtFormLetterController extends SrsPrintMgmtController
{
    FormLetterReport formLetterReport;

    // Begin - Modify by lmattiuz on 27/06/2012
    boolean DEVLockDestinationProperties;
    SRSPrintDestinationSettings DEVfixedprintSettings;
    // End - Modify by lmattiuz
}

// Begin - Modify by lmattiuz on 27/06/2012 - Project: 120301_DevopmentTools_DEV
public Boolean DEVparmLockDestinationProperties(Boolean _DEVLockDestinationProperties = DEVLockDestinationProperties)
{
    DEVLockDestinationProperties = _DEVLockDestinationProperties;

    return DEVLockDestinationProperties;
}

protected void outputReport()
{
    // Begin - Modify by lmattiuz on 27/06/2012 - Project: 120301_DevopmentTools_DEV
    // Description:
    if(DEVLockDestinationProperties)
        formLetterReport.getCurrentPrintSetting().parmPrintJobSettings(DEVfixedprintSettings);
    // End - Modify by lmattiuz

    // execute report.
    if(formLetterReport)
    {
        formLetterReport.execute();
    }
}

public SysOperationStartResult startOperation()
{
    // Begin - Modify by lmattiuz on 27/06/2012 - Project: lmat_120301_DevopmentTools_DEV
    // Description:
    if(DEVLockDestinationProperties)
        DEVfixedprintSettings = this.parmReportContract().parmPrintSettings();
    // End - Modify by lmattiuz

    this.init();

    return super();
}       

Then you can print reports in PDF as you usually do:


 protected void printReportPdf(Common _record)
{
    args args = new args();
    CustInvoiceJour custInvoiceJour = _record;
    SRSPrintDestinationSettings printSettings;
    SalesInvoiceController controller = new SalesInvoiceController();

    args.record(_record);

    pdfPath = WinAPI::getTempPath() + custInvoiceJour.InvoiceId + ".pdf";

    // imposta nome report
    controller.parmReportName(ssrsReportStr(SalesInvoice, Report));

    // get print settings from contract
    printSettings = controller.parmReportContract().parmPrintSettings();

    // set print medium
    printSettings.printMediumType(SRSPrintMediumType::File);
    printSettings.fileFormat(SRSReportFileFormat::PDF);
    printSettings.overwriteFile(true);
    printSettings.fileName(pdfPath);

    // forzo che non vengano cambiati i parametri di stampa che gli passo io
    controller.DEVparmLockDestinationProperties(true);

    // suppress the parameter dialog
    controller.parmShowDialog(false);
    controller.parmArgs(args);

    // start operation
    controller.startOperation();
}

AX Enterprise Portal 2012 - Modify AxGridView lookup

If you want to filter or modify visualized fields on a Lookup inside an Axgridview, here is how you can do it:

Add this method to the field you want to change your lookup, in your ax Dataset. (the method is not listed in the override methods)

 void void dataSetLookup(SysDataSetLookup sysDataSetLookup)
{
    Query q = new Query();
    List list = new List(Types::String);
 
    list.addEnd(fieldStr(InventTable, ItemId));
    list.addEnd(fieldStr(InventTable , NameAlias));
 
    q.addDataSource(tableNum( InventTable ));
    q.dataSourceNo(1).addRange(fieldNum( InventTable , ItemId)).value('000001');
     
    sysDataSetLookup.parmQuery(q);
 
    sysDataSetLookup.parmLookupFields(list);        
}


Friday, May 18, 2012

AxUtil GUI

If you find that the AXUtil tool for importing models is not so pratical, here's the tool for you.


I've extended the functionality of the standard "Installed models" form inside Tools -> Models Management to let you Import, Export, Move or Delete models directly from AX. How it works: With a little of reverse engineering i found that AxUtil.exe simply uses a DLL named AXUtil.dll. This DLL is already referenced in AX, so you can use it directly from X++.

Here's a sample to export a model. The code is pretty straightforward, I just pass in the name of the DB, the path where to export the file and some other params, and then I get my model saved/imported/moved/deleted.

Here you can find the project for the tool, this will work on every client (you don't need to be on the AOS to export/import models)



 private void exportModel(SysModelManifest _SysModelManifest, filePath path)  
 {  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtil        axutil      = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtil();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilContext     context     = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilContext();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilConfiguration  config     = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilConfiguration();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.ModelArgument     modelArgument;  
   int     modelId = _SysModelManifest.Model;  
   int     i;  
   Object ret;  
   ClrObject o; // = new ClrObject("System.Collections.Generic.List`1[System.String]");  
   ClrObject enumerator;  
   boolean hasErrors;  
   try  
   {  
     modelArgument = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.ModelArgument(modelId);  
     config.set_ExportFile(path + _SysModelManifest.Name);  
     config.set_ModelArgument(modelArgument);  
     config.set_Database(SysSQLSystemInfo::construct().getloginDatabase());  
     config.set_Server(SysSQLSystemInfo::construct().getLoginServer());  
     axutil.Export(context, config);  
     o = context.get_Errors();  
     enumerator = o.GetEnumerator();  
     while (enumerator.MoveNext())  
     {  
       error(enumerator.get_Current());  
     }  
     o = context.get_Warnings();  
     enumerator = o.GetEnumerator();  
     while (enumerator.MoveNext())  
     {  
       warning(enumerator.get_Current());  
     }  
     hasErrors = context.get_HasError();  
     if(!hasErrors)  
       info(strFmt("Esportato modello %1 nel file %2" , _SysModelManifest.Name, path + _SysModelManifest.Name));  
   }  
   catch ( Exception::CLRError )  
   {  
     error(AifUtil::getClrErrorMessage());  
     throw Exception::Error;  
   }  
 }  

Saturday, May 12, 2012

AX Project Finder Tool

Here's a small and handy tools that let you search for projects inside AX.

Just start typing something on the search bar and you will get a list of the projects found.


With a double click you can open the selected project

How it works:

with the call of:


projectListNode = SysTreeNode::getSharedProject(); 


you get the AOT node for the shared project. Then all the child of this node are looped, and the name is checked against the input text


treeNodeIterator = projectListNode.AOTiterator();  
   treeNode = treeNodeIterator.next();  
   while(treeNode)  
   { ... }  


 void FindProject()  
 {  
   ProjectSharedPrivate  projectType;  
   TreeNode treeNode;  
   ProjectListNode projectListNode;  
   TreeNodeIterator treeNodeIterator;  
   str aotName;  
   ;  
   ListboxResult.clear();  
   projectListNode = SysTreeNode::getSharedProject();  
   treeNodeIterator = projectListNode.AOTiterator();  
   treeNode = treeNodeIterator.next();  
   while(treeNode)  
   {  
     aotName = treeNode.AOTname();  
     //return;  
     if(DEVString::contains(aotName, projectName.text()))  
     {  
       ListboxResult.add(aotName);  
     }  
     treeNode = treeNodeIterator.next();  
   }  
 }  



Download link below

Friday, May 04, 2012

AX 2012 Create new project tool

Here's a port of the tool to create a new project template found on Axaptapedia.

This one will work on AX 2012, and has been entirely rewritten.

It support all the new nodes of the AOT made available with AX 2012


As usual, link to download is below

Friday, April 20, 2012

Static void main()

Hi guys, I'm an italian programmer working on Microsoft Dynamics AX and the .NET world for years.

In this blog I will give you tools and hints on the development world, with a special regard on Microsoft Dynamics AX.
You'll find also useful tips on the .NET world, Web Development, Mobile, Interfaces and maybe some tips on Android Java Games.
I hope to give something back to the community!

Ludovico Mattiuzzo