Tuesday, October 20, 2015

Management Reporter Roles

The following tables shows the roles of AX which are transformed in Management reporter when data mart synchronizes.


Tuesday, September 29, 2015

Changing report design via code SSRS

It is one of the normal development requirements you may came across where you want to change the report design name on the basis of some logic. The following example shows you how to achieve this.

The modification is done in Controller class "outputReport" method, before "super" call you need to set the updated design name based on some condition and its done.

/// <summary>
///    Executes the report for the print management setting that is currently loaded.
/// </summary>
/// <remarks>
///    The <c>outReports</c> method loops over print management settings and calls this method for each
///    print management setting loaded.
/// </remarks>
/// <exception cref="M:Exception::Error">
///    The print management object has not been initialized.
/// </exception>
public void outputReport()
{
    reportDesign = 'MyReport.Report_DesignA';
    this.parmReportName(reportDesign);
    this.parmReportContract().parmReportName(reportDesign);
    formLetterReport.parmReportRun().settingDetail().parmReportFormatName(reportDesign);
    super();
}

Tuesday, September 22, 2015

Restoring missing DirPartyLocation info

I came into issue on one of the environment where somehow records of Vendor Contacts data was deleted from DirPartyLocation table and we need to restore the data without backup database as the backup database was way old to recover.

By looking into GAB framework which was introduced in AX 2012, I come to know that DirPartyTable  maintains Primary contacts and address information in the following fields.

  • PrimaryAddressLocation
  • PrimaryContactEmail
  • PrimaryContactFax
  • PrimaryContactPhone
  • PrimaryContactTelex
  • PrimaryContactURL

Friday, May 15, 2015

SSRS Reports Excel merge cell issue

I found various blogs and forums discussing the Excel merging cells issue while exporting SSRS report to Excel. I found a simple and logical reason behind the issue.


In the above design consider Report Header Textbox with Grid in the details part. If Header Textbox does not align with Grid columns, Excel will start merging the difference of columns which is shown by red line in the picture. However, if you get it align with Grid column Excel will start a new column as there will be no difference in columns indicated by green line.

Thursday, May 7, 2015

Cheque modification in AX 2012

Cheque modification is a most common requirements in Dynamics AX world. In this post I will discuss the values which are prepared before these values are dumped in SSRS Report framework. All cheque values including Recipient name and address, Amount in words, Date, Slip transactions etc.

The class which needs to be modify in order to customize the values is "CustVendCheque".

CustVendCheque class methods are generally modified to get the cheque values customized:
  • getSlipText or (fillSlipTxt which is obsolete in AX 2012)
  • output

getSlipText method is responsible for most of the data that is printed on the check slip lines; the key point here is that it is sent as a single block of text which leaves the developer very little room to actually modify the cheque without getting into a stream of circular reference errors. So, whatever we need to do as far as Text formatting (for check stubs) goes, we should get it done before this text (‘chequeSlipTxt’) leaves the class.

Friday, May 1, 2015

Financial dimension lookup

While developing in AX "lookups" are the most common requirements you may come across. However, sometimes you may have to link your customized lookup to non-conventional datasets such as "Financial Dimensions". 
This post will show you how to create custom lookup listing one of "Financial Dimension" on report dialog. For this requirement it requires "UI Builder" class.

This customized lookup function will be using "DimensionDefaultingLookup" from.

Contract Class declaration : 

[
    DataContractAttribute,  SysOperationContractProcessingAttribute(classStr(xxxxReportUIBuilder))    
]
public class xxxxReportContract
{
    Name    dimensionValue;
}

Contract parameter :

[
    DataMemberAttribute(identifierStr(dimensionValue)),
    SysOperationLabelAttribute(literalstr('@SYS3794')),
    SysOperationDisplayOrderAttribute('1')
]
public Name parmFinDimLocation(Name _dimensionValue = dimensionValue)
{
    dimensionValue = _dimensionValue;
    return dimensionValue;
}

Thursday, April 30, 2015

Reading excel file with progress bar

Reading an excel is most common requirement you may come across while developing in Axapta world. This post will show the code for reading an excel file with progress bar indicator.

static void excelReadWithProgressBarJob(Args _args)
{
    SysExcelApplication     application;
    SysExcelWorkbooks       workbooks;
    SysExcelWorkbook        workbook;
    SysExcelWorksheets      worksheets;
    SysExcelWorksheet       worksheet;
    SysExcelCells           cells;
    COMVariantType          type;
    int                     row, totalRowCount;
    int                     numberOfRecordsCleaned;
    int                     numberOfRecordsNotFound;
    Dialog                  dialog;
    DialogField             dialogField;
    Filename                filename;
    SysExcelRange           range;
    SysOperationProgress    progress = new SysOperationProgress();
    #Excel
    #AviFiles
    #define.Star('*')
    #define.Space(' ')
    
    VendAccount             vendAccount;
    VendTable               vendTableLocal;
    
    dialog = new Dialog("Caption of Dialog");
    dialogfield = dialog.addField(extendedTypeStr(FilenameOpen), "Excel file");
    dialog.filenameLookupFilter(["@SYS28576", #XLSX, "@SYS28576", "*.xls"]);
    
    if (dialog.run())
    {
        filename = (dialogfield.value());
    }
    else
    {
        return;
    }
    progress.setCaption("Caption for progress bar");
    progress.setAnimation(#AviUpdate);    
    
    application = SysExcelApplication::construct();
    workbooks = application.workbooks();
    
    try
    {
        workbooks.open(filename);
    }
    catch (Exception::Error)
    {
        throw error("File cannot be opened.");
    }
    
    workbook = workbooks.item(1);
    worksheets = workbook.worksheets();
    worksheet = worksheets.itemFromNum(1);
    cells = worksheet.cells();
    range = cells.range(#ExcelTotalRange);
    
    try
    {
        // Finds the row where the first contents is found.
        range = range.find(#Star, null, #xlFormulas, #xlWhole, #xlByRows, #xlPrevious);
        totalRowCount = range.row();
        progress.setTotal(totalRowCount);
    }
    catch (Exception::Error)
    {
        error("@SYS59926");
        totalRowCount = 0;
        progress.setTotal(totalRowCount);
    }
    
    do
    {
        row++;
        //Vendor account
        switch(cells.item(row, 1).value().variantType())
        {
            case COMVariantType::VT_BSTR:
                vendAccount = strFmt("%1", cells.item(row, 1).value().bStr());
                break;
            case COMVariantType::VT_DECIMAL, COMVariantType::VT_R4, COMVariantType::VT_R8:
                vendAccount = strFmt("%1", num2str(cells.item(row, 1).value().double(), -1, 0, DecimalSeparator::Auto, ThousandSeparator::None));
                break;
            case COMVariantType::VT_I1, COMVariantType::VT_I2, COMVariantType::VT_I4:
                vendAccount = strFmt("%1", cells.item(row, 1).value().int());
                break;
            case COMVariantType::VT_UI1, COMVariantType::VT_UI2, COMVariantType::VT_UI4:
                vendAccount = strFmt("%1", cells.item(row, 1).value().uLong());
                break;
             case COMVariantType::VT_EMPTY:
                vendAccount = '';
                break;
            default:
                 throw error(strfmt('Unhandled variant type (%1).', cells.item(row, 3).value().variantType()));
        }
        vendTableLocal = VendTable::find(vendAccount);
        if (vendTableLocal)
        {
            numberOfRecordsCleaned++;
        }
        else
        {
            numberOfRecordsNotFound++;
        }
        type = cells.item(row + 1, 1).value().variantType();
        progress.setText(strfmt("Vendor : %1 (%2 / %3)", vendAccount, row, totalRowCount));
        progress.setCount(row, 1);
    }
    while (type != COMVariantType::VT_EMPTY);
    application.quit();
    info(strFmt('%1 / %2 number of records found', numberOfRecordsCleaned, row));
    info(strFmt('%1 / %2 number of records not found', numberOfRecordsNotFound, row));
}