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