Wednesday, August 26, 2015

Creation of .txt/.csv files with AX 2009

Requirement: Export database log to a .csv/.txt file in AX 2009
Process:
Step 1: Create a class with name “exportDataBaseLog” and methods. Create an action menu item with name “exportDataBaseLog” and lebel “Export to csv”
Step 2: Add action menu item (exportDataBaseLog) in form “Database log” (path: Administration> Inquiry> Database log) 












On click of button “Export to csv” a dialog will open for asking name of file















When we click on browse we will get a screen asking for file and location














On “Save” again we will see same dialog with name of file















On click Ok an info log will appear for location and file.























Elaborated technical approach
Step 1:  Create a class with name “exportDataBaseLog” and methods(for .txt we can replace .csv by .txt)
class exportDataBaseLog extends RunBaseBatch
{
    // Packed variables
    FileNameSave            filename;
    System.Exception    e;
    QueryRun            queryRun;
    //str                 filename;

    // Dialog fields
    DialogField     dlgFileName;

    #define.CurrentVersion(1)
    #define.Version1(1)
    #localmacro.CurrentList
        filename
    #endmacro
}
public Object dialog()
{
    DialogRunbase       dialog = super();
    #resAppl
;
    dialog.filenameLookupFilter(["csv  files","*.csv"]);
    dlgFileName = dialog.addFieldValue(typeid(FileNameSave),filename);

    return dialog;
}
public boolean getFromDialog()
{
    ;
    filename   = dlgFileName.value();
    return super();
}
void createLogInCSV()
{
    TextIO                  file;
    FileIOPermission        fileIOPermission;
    container               line,header,header2;
    SysDataBaseLog          dataBaseLog;
    List                    modifiedFieldValueList;
    ListEnumerator          enumerator;
    Map                     OldValue, newValue;
    container               tmp;
    FormListItem            item;
    fieldId                 fieldId;

    #File
    ;
    new FileIOPermission(this.fileName()+'.csv','w').assert();
    file = new TextIO(this.fileName()+'.csv',#io_write,1250);

    file.outFieldDelimiter(',');
    header = ['Database Log export'];
    header2 = ['Name of table','Record Identification','Type of change','Created date and time','created by','Field name','Value','Previous value'];
    file.write(header);
    file.write(header2);
    while select dataBaseLog order by CreatedDateTime desc
    {
        line = connull();
        modifiedFieldValueList = dataBaseLog.getDataAslist();
        enumerator = modifiedFieldValueList.getEnumerator();
        while (enumerator.moveNext())
        {
            tmp = enumerator.current();
            fieldId = conpeek(tmp, 1);
            line= [TableId2pName(dataBaseLog.table),
strReplace(dataBaseLog.Description,',',';'),
enum2str(dataBaseLog.LogType),                    datetime2str(dataBaseLog.createdDateTime),
dataBaseLog.createdBy,
FieldId2Name(dataBaseLog.table,fieldId),
strrem(dataBaseLog.contents2Str(conpeek(tmp, 2),fieldId),','),
strrem(dataBaseLog.contents2Str(conpeek(tmp, 3),fieldId),',')];
            file.write(line);
        }
    }
   
info(strfmt("Please check log excel in path %1", filename));

}
public void run()
{
    #OCCRetryCount

    try
    {
        ttsbegin;
        this.createLogInCSV();
        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;
        }
    }

}
public container pack()
{
    return [#CurrentVersion,#CurrentList];
}
public boolean unpack(container packedClass)
{
    Version version = RunBase::getVersion(packedClass);
;
    switch (version)
    {
        case #CurrentVersion:
            [version,#CurrentList] = packedClass;
            break;
        default:
            return false;
    }

    return true;
}
static void main(Args args)
{
    exportDataBaseLog    dataBaseDetailedLogExtract;
;
    dataBaseDetailedLogExtract = exportDataBaseLog::construct();

    if (dataBaseDetailedLogExtract.prompt())
        dataBaseDetailedLogExtract.run();
}

Result: TestCSVFile.csv
 


Tuesday, August 25, 2015

Create .doc file from template in AX 2009

Requirement: Create a probationary complete letter (.doc file) on click of check box “Probation completed” from employee details.
Process:
Step 1: Create template and save it to location name: “D:\TestDocTemplate\ProbationaryCompleteTemplate.dotx” with few book marks


 Step 2: Create a field (Boolean: NoYes) in EmplTable and added to field group “Administration”
                Label: Probation completed
On click of check box a doc file will open with info log of file location and name

Technical approach:
Create a class with name CreateProbationLetter with below methods
public class CreateProbationLetter
{

    EmplTable   emplTable;

    FileName    template;
    FileName    probationLetter;

    str         DocumentDate;

    COM         word;//Application
    COM         wordDocuments;
    COM         document;
    COM         bookmarks;

    #define.word('Word.Application')

}
public static CreateProbationLetter construct()
{
    CreateProbationLetter  createProbationLetter;
;
createProbationLetter = new CreateProbationLetter();
    return createProbationLetter;
}
EmplTable parmEmplTable(EmplTable _emplTable = emplTable)
{
    ;
    emplTable = _emplTable;

    return  emplTable;
}
FileName parmTemplateName(FileName _template = template)
{
    ;
    template = _template;
    return template;
}
void openWord()
{
    COM documents;
    ;
    try
    {
        word = new COM(#Word);
    }
    catch (Exception::Internal)
    {
        if (word == null)
        {
            throw error("Microsoft Word is not installed.");
        }
    }
    documents = word.documents();
    document = documents.add(template);
}
void processBookmark(str _name, anytype _value)
{
    COM bookmark;
    COM range;
    ;
    if(!bookmarks.exists(_name))
    {
        return;
    }
    bookmark = bookmarks.item(_name);
    range = bookmark.range();
    range.insertAfter(_value);

}
str setDocumentDate()
{
    str day, mth,yr, rptDate;
    ;
    //----- Date display------ begin
    day = int2str(dayOfMth(systemdateget()));
    yr = int2str(year(systemdateget()));
    //----- Date display------ end

    DocumentDate = day+' '+mthName(mthOfyr(systemdateget()))+' '+yr;
    return DocumentDate;
}
FileName setfileName()
{
    container fileNameContainer;
    ;
    fileNameContainer = Global::fileNameSplit(template);
    probationLetter = conpeek(fileNameContainer,1)+
DirPartyTable::find(emplTable.PartyId).FirstName+
DirPartyTable::find(emplTable.PartyId).MiddleName+
'_ProbationCompletionConfirmation_'+
this.setDocumentDate()+
'.doc';
    return probationLetter;
}
void run()
{
    ;
    this.openWord();
    bookmarks = document.bookmarks();
    this.processBookmark('EMPLOYEETITLE',emplTable.Title);
    this.processBookmark('CompanyName',CompanyInfo::find().Name);
    this.processBookmark('DocumentDate',this.setDocumentDate());
    this.processBookmark('EmployeeFirstName',' '+DirPartyTable::find(emplTable.PartyId).FirstName);
    this.processBookmark('EmployeeFullName',DirPartyTable::find(emplTable.PartyId).Name);
    word.visible(true);
    wordDocuments = word.Documents();
    document.saveas(this.setfileName());
    document.save();
    //document.close();
    //word.quit();
    info(strfmt('Please check file at: %1',this.setfileName()));
}

From EmplTable: create a method with name: createProbationLetter and call this new method in modified field for newly created Boolean field “smlProbationCompleted
//Created by HS for probation complete letter generation
void createProbationLetter()
{
    CreateProbationLetter  createProbationLetter = new CreateProbationLetter();
    ;
    createProbationLetter.parmEmplTable(this);
    createProbationLetter.parmTemplateName(@D:\TestDocTemplate\ProbationaryCompleteTemplate.dotx ');
    createProbationLetter.run();
}
/// <summary>
///    When fields are modified this method is called. The fields are updated using the AxEmplTable class. Note: super-method is never called.
///    The map HRMPersonNameMap is used to update name fields in
///    HRMApplicantTable.
/// </summary>
/// <param name="_fieldId">
///    Id of the field being modified.
/// </param>
public void modifiedField(fieldId _fieldId)
{
    AxEmplTable     axEmplTable;
    Object          formDataSource;
    ;

    super(_fieldId);

    if (this.isFormDataSource())
    {
        if (formDataSourceHasMethod(this.dataSource(),classstr(AxEmplTable)))
        {
            formDataSource  = this.dataSource();
            axEmplTable     = formDataSource.axEmplTable();
        }
    }
    else
    {
        axEmplTable = this.axEmplTable();
    }

    if (axEmplTable)
    {
        axEmplTable.setFieldAsTouched(_fieldId);
        axEmplTable.modify();
    }
    else
    {
        // HRM-start
        switch(_fieldId)
        {
            case fieldnum(EmplTable, PartyId) :
                this.initFromDirParty(DirParty::constructFromPartyId(this.PartyId));
                break;
            //Created by Harshita on 21stAugust 2015- begin
            case fieldnum( EmplTable, smlProbationCompleted):
                            if(this.smlProbationCompleted == Noyes::Yes)
                                this.createProbationLetter();
            break;
            //Created by Harshita on 21stAugust 2015- end
        }
        // HRM-end

    }
}

Result:
On click of the check box “Probation completed” a doc file will generate based on template with info log
Info log:
File: Name “Charlie_ProbationCompletionConfirmation_25 August 2015.doc”

Sunday, July 19, 2015

Calling report design based on parameter selected without knowing contract class for AX 2012

Requirement: Calling report design based on parameter selected without knowing contract class.
Brief Steps:
1. Create a method in controller class linked with report which will select report design based on selected parameters.
2. Fetch report name in override method ‘preRunModifyContract’ with the help of method wrote in step 1 and frame report name to its contract class.
[Note: Before use any method for selecting report name we have to specify a report name in main method of controller class for default value.]
Elaborated steps:
Step 1: Create a method in controller class linked with report which will select report design based on selected parameters: 
Here, we have to pick report name based on selected inventory dimensions; below code is returning report design name ssrsReportStr(InventJournalTrans, Report_WL) when only ‘location’ and ‘warehouse’ was ticked at runtime and if any other is also ticked or if not match with this combination then, code is returning report design name ssrsReportStr(InventJournalTrans, Report)
private str getReportName()
{
    str reportNameLocal;

    if( this.parmReportContract().parmRdlContract().getValue('InventLocationId') && this.parmReportContract().parmRdlContract().getValue('WMSLocationId')       &&
        !(this.parmReportContract().parmRdlContract().getValue('ConfigId')       || this.parmReportContract().parmRdlContract().getValue('InventSiteId')        ||
        this.parmReportContract().parmRdlContract().getValue('InventSizeId')    || this.parmReportContract().parmRdlContract().getValue('InventColorId')        ||
        this.parmReportContract().parmRdlContract().getValue('InventStyleId')   || this.parmReportContract().parmRdlContract().getValue('InventProfileId_RU')   ||
        this.parmReportContract().parmRdlContract().getValue('InventOwnerId_RU')|| this.parmReportContract().parmRdlContract().getValue('InventBatchId')        ||
        this.parmReportContract().parmRdlContract().getValue('WMSPalletId')     || this.parmReportContract().parmRdlContract().getValue('InventSerialId')       ||
        this.parmReportContract().parmRdlContract().getValue('InventGTDId_RU')))
    {
        reportNameLocal =ssrsReportStr(InventJournalTrans, Report_WL);
    }
    else
    {
         reportNameLocal = ssrsReportStr(InventJournalTrans, Report);
    }
    return reportNameLocal;
}

Step 2: Fetch report name in override method ‘preRunModifyContract’ with the help of method wrote in step 1 and frame report name to its contract class.

/// <summary>
/// Changes the report contract before it runs the report.
/// </summary>
public void preRunModifyContract()
{
    boolean showLog = false;

    showLog = this.parmReportContract().parmRdlContract().getParameter(#ParameterShowLog).getValueTyped();
    this.processReportParameters(this.parmReportContract().parmQueryContracts().lookup(this.getFirstQueryContractKey()),
        showLog);
    // <GEELV>
    if (isInventJournalTrans_LV)
    {
        this.parmReportContract().parmReportName(ssrsReportStr(InventJournalTrans, Report_LV));
    }
    // </GEELV>
    // <GEERU>
    this.parmReportContract().parmRdlContract().getParameter(#parmISOCode).setValueTyped(SysCountryRegionCode::countryInfo());
    // </GEERU>

    this.parmReportContract().parmReportName(this.getReportName()); // Calling method and framing to its contract class
}