Monday 31 March 2014

Workflow Email notification in ax 2009

public void insert()
{
    UserId      useridcheck;
    ;
    super();
   if(this.TrackingContext == WorkflowTrackingContext::WorkItem
        &&  this.TrackingType   ==  WorkflowTrackingType::Creation
        && this.EmailSent == NoYes::No)
       // && this.User == useridcheck)
    {
        this.emailnotification();
    }
}

void emailnotification()
{
    SysMailer  mailer ;
    str ToAddress ;
    str FromAddress = "axadmin@dhanushinfotech.net";
    str Subject;
    str B1 ;
    str B2      =   "<p>Dhanush Team</p> <p>Note: *** This is a system generated email, please do not reply ***</p>";
    str Body;
    InteropPermission permission = new InteropPermission(InteropKind::ComInterop);
    SysCompanyUserInfo  sysCompanyUserInfo;
    SysUserInfo sysUserInfo;
    Purchtable  purchtable;
    PurchLine   purchline;
    LedgerJournalTable LedgerJournalTable;
    WorkFlowTrackingTable wftrackingtable;
    DataArea    dataArea;
    ;

    select purchtable
        where purchtable.RecId    ==  this.ContextRecId;

    select LedgerJournalTable where LedgerJournalTable.RecId == this.ContextRecId;
    if(purchtable)
    {
        //Select firstonly purchline
          //  where purchline.PurchId == purchtable.PurchId
           // &&  (purchline.ProjCategoryId == "CAT_0001" ||  purchline.ProjCategoryId == "CAT_0002" ||
           //      purchline.ProjCategoryId == "CAT_0003" ||  purchline.ProjCategoryId == "CAT_0007" ||
           //      purchline.ProjCategoryId == "CAT_0008" ||  purchline.ProjCategoryId == "CAT_0009");
        //if(purchline)
        //{
            Subject =   "Purchase order waiting for approval.";
            B1  =   "<p>Dear Sir/Madam,</p> <p>Please Approve the purchase order %1 in the company %2(%3).</p> <p>Regards,</p>";
            Body    =   B1+B2;
            select dataArea
                where dataArea.id == curext();
            ToAddress   =   sysUserInfo::find(this.User).Email;
            CodeAccessPermission::revertAssert();
            permission.assert();
            mailer    = new SysMailer();
            CodeAccessPermission::revertAssert();
            mailer.quickSend(fromaddress,toaddress,subject,strfmt(Body,purchtable.PurchId,dataArea.name,dataArea.id));
            ttsbegin;
            select forupdate wftrackingtable where wftrackingtable.RecId == this.RecId;
            wftrackingtable.EmailSent = NoYES::Yes;
            wftrackingtable.doUpdate();
            ttscommit;
        //}
    }
     if(LedgerJournalTable)
    {
            if(LedgerJournalTable.JournalType == LedgerJournalType::Payment)
            {
                    Subject =   "Vendor Payment Journal waiting for approval.";
                    B1  =   "<p>Dear Sir/Madam,</p> <p>Please Approve the Vendor Payment Journal %1 in the company %2(%3).</p> <p>Regards,</p>";
                    Body    =   B1+B2;
                    select dataArea
                        where dataArea.id == curext();
                    ToAddress   =   sysUserInfo::find(this.User).Email;
                    CodeAccessPermission::revertAssert();
                    permission.assert();
                    mailer    = new SysMailer();
                    CodeAccessPermission::revertAssert();
                    mailer.quickSend(fromaddress,toaddress,subject,strfmt(Body,LedgerJournalTable.JournalNum,dataArea.name,dataArea.id));
                    ttsbegin;
                    select forupdate wftrackingtable where wftrackingtable.RecId == this.RecId;
                    wftrackingtable.EmailSent = NoYES::Yes;
                    wftrackingtable.doUpdate();
                    ttscommit;
            }

            if(LedgerJournalTable.JournalType == LedgerJournalType::Daily)
            {
                    Subject =   "General Journal waiting for approval.";
                    B1  =   "<p>Dear Sir/Madam,</p> <p>Please Approve the General Journal %1 in the company %2(%3).</p> <p>Regards,</p>";
                    Body    =   B1+B2;
                    select dataArea
                        where dataArea.id == curext();
                    ToAddress   =   sysUserInfo::find(this.User).Email;
                    CodeAccessPermission::revertAssert();
                    permission.assert();
                    mailer    = new SysMailer();
                    CodeAccessPermission::revertAssert();
                    mailer.quickSend(fromaddress,toaddress,subject,strfmt(Body,LedgerJournalTable.JournalNum,dataArea.name,dataArea.id));
                    ttsbegin;
                    select forupdate wftrackingtable where wftrackingtable.RecId == this.RecId;
                    wftrackingtable.EmailSent = NoYES::Yes;
                    wftrackingtable.doUpdate();
                    ttscommit;
            }

    }



}

Workflow PurchReq most Recent Comment in ax 2009

//PurchReqmostRecentComment EDT is used for recent comment.
display PurchReqmostRecentComment mostRecentComment()
{
    WorkflowTrackingCommentTable        workflowTrackingCommentTable;
    WorkflowWorkItemTable               workflowWorkItemTable;
    WorkflowTrackingTable               workflowTrackingTable;
    DirPartyTable                       dirPartyTable;
    EmplTable                           emplTable;
    PurchReqMostRecentComment           comment;
    EmplId                              emplId;
    UserInfo                            userInfo;
    Name                                name;
    ;
    select firstonly workflowWorkItemTable
        order by CreatedDateTime desc where
        workflowWorkItemTable.RefTableId == this.TableId &&
        workflowWorkItemTable.RefRecId == this.RecId &&
        workflowWorkItemTable.CompanyId == this.DataAreaId &&
        workflowWorkItemTable.Status == WorkflowWorkItemStatus::Completed;

        workflowTrackingTable = Workflow::findLastTrackingRecordForWorkItem (workflowWorkItemTable);
        workflowTrackingCommentTable = WorkflowTrackingCommentTable::find (workflowTrackingTable.TrackingId);
        emplId = SysCompanyUserInfo::find(workflowTrackingTable.User).EmplId;
        if (emplId)
        {
            select firstonly Name from dirPartyTable
            exists join emplTable
            where dirPartyTable.PartyId == emplTable.PartyId &&
            emplTable.EmplId == emplId;
            name = dirPartyTable.Name + ' (' + emplId + ') : ';
        }
        else
        {
            select firstonly userInfo where userInfo.Id == workflowTrackingTable.User;
            name = userInfo.Name + ' (' + workflowTrackingTable.User + ') : ';
        }
        comment = strfmt("%1",DateTimeUtil::applyTimeZoneOffset (workflowTrackingCommentTable.CreatedDateTime, DateTimeUtil::getUserPreferredTimeZone())) + ' ';
        comment += name;
        comment += workflowTrackingCommentTable.Comment;
    return comment;
}


// PurchReqRequiredActionDueDateStr EDT is used for requiredactionduedate
display PurchReqRequiredActionDueDateStr requiredActionDueDate()
{
    WorkflowWorkItemTable               workflowWorkItemTable;
    PurchReqRequiredActionDueDateStr    dueDateStr;
    ;
    select firstonly DueDateTime from workflowWorkItemTable
        where workflowWorkItemTable.RefTableId == this.TableId &&
        workflowWorkItemTable.RefRecId == this.RecId &&
        workflowWorkItemTable.CompanyId == this.DataAreaId &&
        workflowWorkItemTable.UserId == curuserid() &&
        workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending;
        if (workflowWorkItemTable.DueDateTime != DateTimeUtil::minValue())
        {
            dueDateStr = strfmt("%1",DateTimeUtil::applyTimeZoneOffset (workflowWorkItemTable.DueDateTime, DateTimeUtil::getUserPreferredTimeZone()));
        }
    return dueDateStr;
}


// purchreqRequiredAction EDT is used for required action.
display purchreqRequiredAction requiredAction()
{
    WorkflowWorkItemTable       workflowWorkItemTable;
    PurchReqRequiredAction      text;
    ;
    select firstonly workflowWorkItemTable
        where workflowWorkItemTable.RefTableId == this.TableId &&
        workflowWorkItemTable.RefRecId == this.RecId &&
        workflowWorkItemTable.CompanyId == this.DataAreaId &&
        workflowWorkItemTable.UserId == curuserid() &&
        workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending;
        if (workflowWorkItemTable.RecId)
        {
            switch (this.WorkflowState)
            {
                case WorkflowState::ChangeRequest :
                text = "@SYS109048";
                break;
                case WorkflowState::PendingApproval :
                text = "@SYS109902";
                break;
                case WorkflowState::PendingComplete :
                text = "@SYS112063";
                break;
            }
        }
    return text;
}

Workflow last approved by in ax 2009

display WorkflowUser  user()
{
    WorkflowWorkItemTable workflowWorkItemTable;
    WorkflowTrackingTable workflowTrackingTable;
    EmplId emplId;
    ;
    select firstonly workflowWorkItemTable where
    workflowWorkItemTable.RefTableId == this.TableId &&
    workflowWorkItemTable.RefRecId == this.RecId &&
    workflowWorkItemTable.CompanyId == this.DataAreaId &&
    workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending;

    workflowTrackingTable = Workflow::findLastTrackingRecordForWorkItem (workflowWorkItemTable);
    emplId = SysCompanyUserInfo::find(workflowTrackingTable.User).UserId;

    return emplId;

}

display Emplid LastApprovedby()
{
    EmplId emplId;
    WorkflowTrackingTable  workflowtrackingtable;
    ;

    select firstonly reverse workflowtrackingtable order by recid asc
    where workflowtrackingtable.ContextRecId == this.RecId
    && workflowtrackingtable.TrackingContext == workflowtrackingcontext::WorkItem
    && workflowtrackingtable.TrackingType == workflowtrackingtype::Approval;
    if (workflowtrackingtable)
    {
       emplId = SysCompanyUserInfo::find(workflowTrackingTable.User).UserId;
    }
    return emplId;
}

static void Workflow_Approver(Args _args)
{
    LedgerJournalTable      tab;
    WorkflowTrackingTable   WorkFlowtab, WorkFlowtab1;
    UserInfo                userinfo;
    ;

    select tab where tab.JournalNum == '';

    While select tab
        join WorkFlowtab
        where WorkFlowtab.ContextRecId      == 5637302079
        && WorkFlowtab.TrackingContext      == WorkflowTrackingContext::WorkItem
    {

        Select firstonly WorkFlowtab1
            where WorkFlowtab1.TrackingType         == WorkflowTrackingType::Approval
            && WorkFlowtab1.ContextRecId            == WorkFlowtab.ContextRecId;
        if (!WorkFlowtab1)
        {
            Select UserInfo
                where UserInfo.id       == WorkFlowtab.User;
            if (UserInfo)
            info(strfmt("%1|%2",tab.JournalNum, UserInfo.name));
        }

    }

}

static void Workflow_Approver_pendingFromaUser(Args _args)
{
    LedgerJournalTable      tab;
    WorkflowTrackingTable   WorkFlowtab, WorkFlowtab1;
    UserInfo                userinfo;
    ;



    While select  WorkFlowtab order by WorkFlowtab.Recid desc
        where WorkFlowtab.ContextTableId    == tablenum(LedgerjournalTable)
        && WorkFlowtab.TrackingContext      == WorkflowTrackingContext::WorkItem
        && WorkFlowtab.TrackingType         == WorkflowTrackingType::Approval
        && WorkFlowtab.User == 'Raj'

    {
        select tab where tab.RecId ==
        info();
    }

}



Fetch the userid who approved the workflow:

In AX 2012:

Below code fetches the user id’s who approved the PO workflow.

select firstonly workflowtrackingstatustable
 join workflowtrackingtable
 where workflowtrackingstatustable .ContextRecId == purchtable.recid
 && workflowtrackingtable.TrackingContext == workflowtrackingcontext::WorkItem
 && workflowtrackingtable.TrackingType == workflowtrackingtype::Approval
 && workflowtrackingtable.WorkflowTrackingStatusTable == workflowtrackingstatustable .recid;
 {
 approvername = workflowtrackingtable.User;
 }

this code might help you to get a PO approver(in the same way you can get the approver name of any order/ journal
 by passing the approved record id as context rec id).
 Note:
 In case there are multiple approvers use While to select multiple approver user id’s from workflowtrackingstatustable.

In AX 2009:

Below code fetches the user id’s who approved the PO workflow.

select firstonly workflowtrackingtable order by recid asc
 where workflowtrackingtable.ContextRecId == purchtable.recid
 && workflowtrackingtable.TrackingContext == workflowtrackingcontext::WorkItem
 && workflowtrackingtable.TrackingType == workflowtrackingtype::Approval;
 if (workflowtrackingtable)
 {
 approvername = workflowtrackingtable.User;
 }

this code might help you to get a PO approver(in the same way you can get the approver name of any order/ journal
 by passing the approved record id as context rec id).
 Note:
 In case there are multiple approvers use While to select multiple approver user id’s from workflowtrackingtable.

Monday 24 March 2014

ShowListOfPrinters in ax 2009

static void ShowListOfPrinters(Args _args)
{
    printJobSettings printJobSettings;
    sysPrintOptions sysPrintOptions;
    map printerMap;
    mapIterator mapIterator;
    ;
    printJobSettings =
    SysPrintOptions::newPrintJobSettingsOnServer();
    sysPrintOptions = new sysPrintOptions();
    sysPrintOptions.setPrintJobSettings(printJobSettings);
    sysPrintOptions.buildPrinterMap();
    printerMap = sysPrintOptions.getPrinterMap();
    mapIterator = new mapIterator(printerMap);
    mapIterator.begin();
    while (mapIterator.more())
    {
        info(mapIterator.value());
        mapIterator.next();
    }
}

Sunday 23 March 2014

SSRS UI Builder through process in ax 2012

UI Builder Class Overview

User Interface (UI) Builder Class is used to define the layout of the parameter dialog box that opens before a report is run in Microsoft Dynamics AX. It is used to add the customizations as well as additional fields in the dialog.
Following are the scenarios where UI Builder Class can be used:
Grouping dialog fields
Overriding dialog field events
Adding a customized lookup to a dialog field
Binding dialog fields with Report contract parameters
Changing the layout of the dialog
Adding custom controls to the dialog
To create a UI builder class, extend it with SrsReportDataContractUIBuilder.

UI Builder Class helps you to add run time lookups and other controls on the dialog form.

class SimpleDemoUIBuilder extends SrsReportDataContractUIBuilder
{
    DialogField dialogEmplId;
    SimpleDemoContract contract;
}

public void build()
{
contract = this.dataContractObject();
dialogEmplId = this.addDialogField(methodStr(SimpleDemoContract, parmEmplId),contract);

}

private void emplIdLookup(FormStringControl emplIdlookup)
{
    Query query = new Query();
    QueryBuildDataSource qbds_EmplTable;
    SysTableLookup sysTableLookup;

    // Create an instance of SysTableLookup with the current calling form control.
    sysTableLookup = SysTableLookup::newParameters(tableNum(CustTable), emplIdlookup);
    // Add fields to be shown in the lookup form.
    sysTableLookup.addLookupfield(fieldNum(CustTable,AccountNum));
    qbds_EmplTable = query.addDataSource(tableNum(CustTable));
    sysTableLookup.parmQuery(query);
    // Perform the lookup
    sysTableLookup.performFormLookup();
}

public void getFromDialog()
{
contract = this.dataContractObject();
super();
}

public void initializeFields()
{
contract = this.dataContractObject();
}

public void postBuild()
{
super();
dialogEmplId = this.bindInfo().getDialogField(this.dataContractObject(),methodStr(SimpleDemoContract,parmEmplId));
dialogEmplId.registerOverrideMethod(methodStr(FormStringControl, lookup),methodStr(SimpleDemoUIBuilder,emplIdLookup), this);
//dialogEmplId.lookupButton(2);
}

2.Create the new class :-
[DataContractAttribute,SysOperationContractProcessingAttribute(classstr(SimpleDemoUIBuilder))]
//example of the contract class validation and initialization "HcmBirthdayContract"
public class SimpleDemoContract implements SysOperationValidatable, SysOperationInitializable
{
     EmplId emplId;
   
}

public void initialize()
{
    this.parmEmplId('');
}

[DataMemberAttribute("EmplId"),
SysOperationLabelAttribute('EMPLID')
]
public EmplId parmEmplId(EmplId _emplId = emplId)
{
    emplId = _emplId;
    return emplId;
}

/// <summary>
///    Validates the SSRS report parameters.
/// </summary>
/// <returns>
///    true if successful; otherwise, false.
/// </returns>
public boolean validate()
{
    boolean ret = true;
    if (!emplId)
    {
        ret = checkFailed("Please select the emplid");
    }
    return ret;
}

3.Create the new class :-
[
SRSReportQueryAttribute(queryStr(cust)),
SRSReportParameterAttribute(classstr(SimpleDemoContract))

]
class SimpleDemoDemoDP extends SRSReportDataProviderBase
{
    SimpleDemoTmp SimpleDemoTmp;
    Custtable     custtable;
}

[SRSReportDataSetAttribute("SimpleDemoTmp")]
public SimpleDemoTmp getSimpleDemoTmp()
{
    select * from SimpleDemoTmp;
    return SimpleDemoTmp;
}

public void insertTmpTable()
{
    SimpleDemoTmp.EmplId = custtable.AccountNum;
    SimpleDemoTmp.insert();
}

[SysEntryPointAttribute(false)]
public void ProcessReport()
{
EmplId emplId;
SimpleDemoContract contract;
;
contract = this.parmDataContract() as SimpleDemoContract;
emplId = contract.parmEmplId();

select * from custtable where custtable.AccountNum== emplId;
this.insertTmpTable();


}
//Or 

------------------------------------------------------------------------------------------
[SRSReportQueryAttribute(querystr(CustTransQuery))]
 public class CustTransdemoDP extends SRSReportDataProviderBase
 {
 CustTransDemoTmp custTransDemoTmp;
 CustTable custTable;
 CustTrans custTrans;
 AmountCur amountCur;
 Voucher voucher;
 CustGroupId custGroup;
 TransDate transDate;
 }
 =================
 [SRSReportDataSetAttribute(tableStr(CustTransDemoTmp))]
 private CustTransDemoTmp getCustTransTmp()
 {
 select custTransDemoTmp;
 return custTransDemoTmp;
 }
 ======================
 private void inserrtIntoCustTransTmp()
 {
 custTransDemoTmp.CustGroup = custTable.CustGroup;
 custTransDemoTmp.AmountCur = custTrans.AmountCur;
 custTransDemoTmp.Voucher = custTrans.Voucher;
 custTransDemoTmp.TransDate = custTrans.TransDate;
 custTransDemoTmp.insert();
 }
 =======================
 [SysEntryPointAttribute]
 public void processReport()
 {
 QueryRun queryRun;
 queryRun = new QueryRun(this.parmQuery());
 while (queryRun.next())
 {
 custTable = queryRun.get(tablenum(CustTable));
 custTrans = queryRun.get(tablenum(CustTrans));
 amountCur = custTrans.AmountCur;
 voucher = custTrans.Voucher;
 custGroup = custTable.CustGroup;
 transDate = custTrans.TransDate;
 this.inserrtIntoCustTransTmp();
 }
 }
http://www.dynamics101.com/2014/04/using-ui-builder-class-to-develop-ssrs-reports-microsoft-dynamics-ax-2012/

 controller class :-
/// <summary>
///    The <c>HcmADARequirementController</c> class is a controller class for the <c>HcmADARequirement</c>
///    report.
/// </summary>
class StockTransferController extends SrsReportRunController
{
    InventTransferShipmentContract          inventTransferContract;
    InventTransferId                            transferId;
    Voucher                                     voucher;
    InventTransferJour                          transferJour;

    #define.ReportName('StockTransferShipment.PrecisionDesign1')
    #define.TransferId('ShipmentDs_TransferId')
    #define.VoucherId('ShipmentDs_Voucher')
}



public client static void main(Args _args)
{
    StockTransferController controller = new StockTransferController();
    controller.parmReportName(#ReportName);
    controller.parmLoadFromSysLastValue(false);
    controller.parmArgs(_args);
    controller.parmShowDialog(false);
    controller.startOperation();
}

/// <summary>
///    Opens the report if the record context is not null.
/// </summary>
/// <returns>
///    true if the record context is not empty; otherwise, false.
/// </returns>
/// <remarks>
///    The report will get executed if the record context is not null.
/// </remarks>
public boolean processReportParameters()
{
    if (this.parmArgs() && this.parmArgs().record())
    {
        transferJour = this.parmArgs().record();
        transferId = transferJour.TransferId;
        voucher = transferJour.VoucherId;
        return false;
    }
    else
    {
        checkFailed("@SYS22539");
        return false;
    }
}

/// <summary>
///    Override this method to change the report contract before you run the report.
/// </summary>
public void preRunModifyContract()
{
    SrsReportRdlDataContract    rdlContractInfo;

    rdlContractInfo = this.parmReportContract().parmRdlContract();
    inventTransferContract = this.parmReportContract().parmRdpContract() as InventTransferShipmentContract;

    //inventTransferContract.parmJourId(transferJour.TransferId);
    //inventTransferContract.parmVoucher(transferJOur.VoucherId);


    rdlContractInfo.setValue(#TransferId, transferJour.TransferId);
    rdlContractInfo.setValue(#VoucherId, transferJour.VoucherId);

}

/// <summary>
/// The <c>InventTransferShipmentContract</c> class is the <c>Invent shipment contract</c> report
/// </summary>
/// <remarks>
///
/// </remarks>
[
    DataContractAttribute
]
public class InventTransferShipmentContract implements SysOperationValidatable
{
    InventTransferId    transferId;
    Voucher             voucher;
}


[
    DataMemberAttribute('TransferId'),
    SysOperationLabelAttribute('Transfer Id')
]
public InventTransferId parmJourId(InventTransferId _transferId = transferId)
{
    transferId = _transferId;
    return transferId;
}


[
DataMemberAttribute('Voucher')
]
public Voucher parmVoucher(voucher _voucher = voucher)
{
    voucher = _voucher;
    return voucher;
}

public boolean validate()
{
    boolean ret = true;
    /*
    if (! voucher || ! transferId)
    {
        ret = checkFailed("Filters must be supplied");
    }
    */
    return ret;
}

[
SRSReportParameterAttribute(classStr(InventTransferShipmentContract))]
public class InventTransferShipDP extends SrsReportDataProviderBase
//SrsReportDataProviderPreProcess
{
    InventTransferCommon_Tmp    inventShipment;
    InventTransferId                transferId;
    Voucher                         voucher;

}
[
    SRSReportDataSetAttribute(tablestr(InventTransferCommon_Tmp))
]
public InventTransferCommon_Tmp getInventTransferCommon_Tmp()
{
    select inventShipment;
    return inventShipment;
}


[SysEntryPointAttribute]
public void processReport()
{
    InventTransferJour                      transferJour;
    InventTransferJourLine                  jourLine;
    InventTransferShipmentContract      contract = this.parmDataContract() as InventTransferShipmentContract;
    InventSiteId                            inventSiteId;
    InventTransferTable                     transferTable;
    InventTable                             inventTable;


    super();
    //Parameters -- initialization
    transferId      = contract.parmJourId();
    voucher         = contract.parmVoucher();
    //End
    while select jourLine
            join transferJour
                where transferJour.TransferId   == jourLine.TransferId
                   && transferJour.VoucherId    == jourLine.VoucherId
                   && transferJour.UpdateType   == InventTransferUpdateType::Shipment
                   && transferJour.TransferId   == transferId
                   && transferJour.VoucherId    == voucher
    {
        transferTable = transferJour.inventTransferTable();
        inventTable = inventTable::find(jourLine.ItemId);
        inventSiteId = InventLocation::find(transferJour.InventLocationIdFrom).InventSiteId;

        inventShipment.FirmName         = InventSite::find(inventSiteId).Name;
        inventShipment.FromWarehouse    = transferJour.InventLocationIdFrom;
        inventShipment.ToWarehouse      = transferJour.InventLocationIdTo;
        inventShipment.InventTransferId = transferJour.TransferId;
        inventShipment.DeliveryMode     = transferTable.DlvModeId;
        inventShipment.VehicleNum       = transferTable.VehicleNum;

        inventShipment.BPGroup          = inventTable.BPGroupName();
        inventShipment.ProductGroup     = inventTable.productGroupName();
        inventShipment.ItemName         = inventTable.itemName();
        inventShipment.ItemId           = inventTable.ItemId;
        inventShipment.ShipmentQty      = jourLine.QtyShipped;
        inventShipment.InventoryUnit    = jourLine.UnitId;
        inventShipment.insert();
    }


}

 

Refreshing form's datasource without affecting cursor position / How to retain cursor position? in AX

 Refreshing form's datasource without affecting cursor position / How to retain cursor position? in AX

WE can do in two ways
1.Just calling the Research method by passing true boolean value
 MyTable_ds.research(true); // boolean value retain the cursor position
 ------------
2.you can use method setPosition() and getPosotion()
 {
 int position;
 ;
 position= MyTable_ds.getPosition();
 MyTable_ds.research();
 MyTable_ds.setPosition(position);
 }

create new number sequence by x++ code in AX 2012

static void DemoNumberSeq(Args _args)
{
NumberSeq numberSeq;
Str salesId;

numberSeq = NumberSeq::newGetNum(SalesParameters::numRefSalesId());
salesId = numberSeq.num();
info(strFmt("%1",salesId));
}

How it works
1.NumberSeq Table act as master table for numberseq code , which stores
format to be generated , next sequence etc.
2.NumberSequenceReferences stores all the references and their corresponding
numberseq codes.
3.As shown in the above code , NumberSeq class needs numberseqreference ,
i,e "EDT. Unique Id for the Process " So first get the references by
passing an EDT as parameter to the findReference method of numberseqreference
class.Than you can call numberSeq.num() method to generate the number
for you.
4.Use NumberSeqFormHandler class if you want to use the numbersequencs on form.

RunBase batch for Dialog in ax 2009

class Runbase_Example extends RunBase
{
     TransDate fromDate,toDate;
     CustAccount custAccount;
     DialogField dlgFromDate,dlgToDate,custDldField;
     #define.CurrentVersion(1)
     #localmacro.CurrentList
     fromDate,toDate
     #endmacro
}
protected Object dialog()
{
    DialogRunbase dialog;
    ;
    dialog = super();
    dialog = super();
    custDldField = dialog.addFieldValue(typeid(CustAccount),CustAccount);
    dlgFromDate = dialog.addFieldValue(typeid(TransDate),fromDate);
    dlgToDate = dialog.addFieldValue(typeid(TransDate),toDate);
    // custDldField = dialog.addFieldValue(extendedTypeStr(CustAccount),custAccount);
    // dlgFromDate = dialog.addFieldValue(extendedTypeStr(TransDate),fromDate);
    // dlgToDate = dialog.addFieldValue(extendedTypeStr(TransDate),toDate);
    return dialog;
}
public boolean getFromDialog()
{
    boolean ret;
    ret = super();
    custAccount = custDldField.value();
    fromDate = dlgFromDate.value();
    toDate = dlgToDate.value();
    return ret;
}
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;
}
public static void main(Args args)
{
    Runbase_Example runb = new Runbase_Example();
    ;
    if(runb.prompt())
    {
        runb.run();
    }
}
public void run()
{
;
    info(custAccount);
}

Thursday 20 March 2014

Alerts through code in ax 2009

static void alerts(Args _args)
{
    EventInbox          inbox;
    ;
 info(strfmt("%1", syscompanyuserinfo::emplId2UserId('Rahul')));
    inbox.initValue();
    inbox.ShowPopup     = NoYes::Yes;
    inbox.Subject       = "This is the Alert subject";
    inbox.Message       = "This is the Alert message";
    inbox.AlertedFor    = "This alert is just information no links are available";
    inbox.SendEmail     = false;
    inbox.UserId        = curuserid();
    inbox.TypeId        = classnum(EventType);
    inbox.AlertTableId  = tablenum(Address);
    inbox.AlertFieldId  = fieldnum(Address, Name);
    inbox.TypeTrigger   = EventTypeTrigger::FieldChanged;
    inbox.CompanyId     = curext();
    inbox.InboxId       = EventInbox::nextEventId();
    inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();
    inbox.insert();
}

Through Code Alerts:-
1.smmActivities:-
  On the table Update method:-
  if (this.ResponsibleEmployee)
    SalesResponsibleAlerts::getAlerts(this.ResponsibleEmployee, this.RecId,this.TableId, fieldnum(SmmActivities, ResponsibleEmployee));
    ttscommit;
2.Create one class:-
class SalesResponsibleAlerts
{
}
Public Static void getAlerts(EmplId _emplId, RecId  _recId, TableId    _TableId, fieldId   _FieldId)
{
    EventInbox          inbox;
    smmleadtable        lead;
    CaseManagement      caseMgmt;
    smmOpportunityTable SmmOpp;
    smmActivities       SmmAct;
    ;
    inbox.initValue();
    inbox.ShowPopup     = NoYes::Yes;
    inbox.Subject       = strfmt("Field Responsible in table %1 has changed", tableid2name(_TableId));
    inbox.Message       = strfmt("Field Responsible in table %1 has changed", tableid2name(_TableId));
    if (_tableid == tablenum(smmleadtable))
    {
        Select firstonly lead
            where lead.RecId    == _recId;
        inbox.AlertedFor    = strfmt("Lead ID: %1, %2", lead.LeadId, lead.LeadDescription);
    }
    else if (_tableid == tablenum(TCC_CaseManagement))
    {
        Select firstonly caseMgmt
            where caseMgmt.RecId    == _recId;
        inbox.AlertedFor    = strfmt("Case ID: %1, %2", caseMgmt.CaseId, caseMgmt.CaseSubject);
    }
    else if (_tableid == tablenum(smmOpportunityTable))
    {
        Select firstonly SmmOpp
            where SmmOpp.RecId    == _recId;
        inbox.AlertedFor    = strfmt("Opportunity ID: %1, %2", SmmOpp.OpportunityId, SmmOpp.Subject);
    }
    else if (_tableid == tablenum(smmActivities))
    {
        Select firstonly SmmAct
            where SmmAct.RecId    == _recId;
        inbox.AlertedFor    = strfmt("Activity ID: %1, %2", SmmAct.ActivityNumber, SmmAct.Category);
    }
    inbox.SendEmail     = false;
    inbox.UserId        = syscompanyuserinfo::emplId2UserId(_emplId);
    inbox.TypeId        = classnum(EventType);
    inbox.AlertTableId  = _TableId;
    inbox.AlertFieldId  = _FieldId;
    inbox.TypeTrigger   = EventTypeTrigger::FieldChanged;
    inbox.CompanyId     = curext();
    inbox.InboxId       = EventInbox::nextEventId();
    inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();
    inbox.insert();
}

Wednesday 19 March 2014

FAILED TO LOG ON AX2012

Steps to be followed :
1. User must created in Active directory.
2.Login into the AX with Administrator account
3.Click on system administration
4.Select user and click on import and add the user from Active directory
5.Provide the proper roles to the user.
i.e System administration-->Users-->Import -->Select Active directory name and search user at display name field-->next-->Add roles to the user-->Finish

The number of messages exceeds the limit of the Infolog (10000.) warning

Regarding limit of infolog - this limit is defined as a macro (MaxErrors) under 'AOT -> Classes -> Info -> viewBuild'

In theory this limit can be increased. However this is not advisable as there could be significant performance implications.

http://my.safaribooksonline.com/book/operating-systems-and-server-administration/microsoft-dynamics-crm/9780735626454/the-xplusplus-programming-language/ch04lev1sec4

http://theaxapta.blogspot.in/2012_11_01_archive.html

Tuesday 18 March 2014

How to send Normal AX Reports as a PDF and User through Batch Process in Dynamics Ax 2009.

How to send Normal AX Reports as a PDF  and User through Batch Process in Dynamics Ax 2009.

Hi friends,
 Recently I got one requirements from my User, I.e. customer want to see ax reports in E-mail everyday once through batch process.
 its just like send mail from batch process only, But we need to work on how to send normal report.

1) write the class with below methods mandatory.
2)Here am going to post logic for how to convert ax report to PDF and how to send the email to user only.
// Saved the reports into particular location
static void Job10(Args _args)
{
    Args args;
    ReportRun rr;
    str reportName = "Custtable";
    str myPath,pdfFileName;
    ;
    args = new Args(reportName);
    args.caller(rr);
    rr = new reportRun(args);
    rr.query().interactive(false);
    rr.report().interactive(false);
    rr.setTarget(printMedium::File);
    rr.printJobSettings().setTarget(PrintMedium::File);
    rr.printJobSettings().preferredTarget(PrintMedium::File);
    rr.printJobSettings().format(PrintFormat::PDF);
    rr.printJobSettings().warnIfFileExists(false);
    rr.printJobSettings().suppressScalingMessage(true);
    pdfFileName = @"C:\Users\Desktop\DateWise\3192014\Report1.pdf";
    rr.printJobSettings().fileName(pdfFileName);
    rr.init();
    rr.run();
    info("Report hasbeen saved");
}

void SaveReport()
 {
    Args args;
    ReportRun rr;
    str reportName = "OpenPurchOrderLine_Vendor";
    str myPath;
    int i;
   ;
   i = 1;
  args = new Args(reportName);
  args.caller(rr);
  rr = new reportRun(args);
  rr.query().interactive(false);
  rr.report().interactive(false);
  rr.setTarget(printMedium::File);
  rr.printJobSettings().setTarget(PrintMedium::File);
  rr.printJobSettings().preferredTarget(PrintMedium::File);
  rr.printJobSettings().format(PrintFormat::PDF);
  rr.printJobSettings().warnIfFileExists(false);
  rr.printJobSettings().suppressScalingMessage(true);
  pdfFileName = @\\AXTESTDEV1\D$\Test\test.pdf; //@ is used for server\\ServerName\drive name$\Folder
  rr.printJobSettings().fileName(pdfFileName);
  rr.init();
  rr.run();
  info("Report has been saved");
}
 //Used to sending emails to particular users
 void EmailCheck()
 {
          //Set                     permissionSet2 = new Set(Types::Class);
          InteropPermission permission = new InteropPermission(InteropKind::ComInterop);
         ;
         CodeAccessPermission::revertAssert();
         info("After code access in EmailCheck()");
         permission.assert();
          mailer = new SysMailer();
          parameters = SysEmailParameters::find();
         if (parameters.SMTPRelayServerName)
        {
             mailer.SMTPRelayServer(parameters.SMTPRelayServerName,
             parameters.SMTPPortNumber,
             parameters.SMTPUserName,
             SysEmailParameters::password(),
             parameters.NTLM);
            info("if");
       }
       else
      {
        mailer.SMTPRelayServer(parameters.SMTPServerIPAddress,                                                                                                             parameters.SMTPPortNumber,
                                                parameters.SMTPUserName,
                                                SysEmailParameters::password(),
                                                parameters.NTLM);
             info("else");
       }
mailer.fromAddress('xyz@abc.com');
mailer.tos().appendAddress('abc@xyz.com');
mailer.tos().appendAddress('TEST@company.com');
mailer.htmlBody('Find the attachment.
<Br>\n NOTE:This is a System Generated Email. Please do not Reply.');
mailer.subject('Report Attached(Testing Mail)');
info(pdfFileName);
mailer.attachments().add("D:\\Test\\test.pdf");
mailer.sendMail();
CodeAccessPermission::revertAssert();
}
 Next Configure this class into batch Job User Form.....
 If any clarification or issues please comments to this..

Set query Range for Existing report in while running in class PrintMedium settings for Report in class
Method()
{
Args args;
ReportRun reportRun;
str reportName = "ReportNameTest";
str myPath;
int i;
TransDate td;
TransDate vd;
str rangeDate;
;
i = 1;
td = systemDateget();
args = new Args(reportName);
args.caller(reportRun);

reportRun = new reportRun(args);
reportRun.query().interactive(false);
reportRun.query().dataSourceTable(tablenum(TableNmae)).addRange(fieldNum(TableNmae,FeildNmae)).value(SysQuery::value(td));
reportRun.report().interactive(false);

reportRun.setTarget(printMedium::File);
reportRun.printJobSettings().setTarget(PrintMedium::File);
reportRun.printJobSettings().preferredTarget(PrintMedium::File);
reportRun.printJobSettings().format(PrintFormat::PDF);
reportRun.printJobSettings().warnIfFileExists(false);
reportRun.printJobSettings().suppressScalingMessage(true);
pdfFileName = @"\\AXTESTDEV1\D$\Demo\Test.pdf";
reportRun.printJobSettings().fileName(pdfFileName);

reportRun.init();
reportRun.run();
}

static void email(Args _args)
{
    // For email notification
    str                         messageBody;
    NWH_XmlImpErrorFlag         XmlImpErrorFlag;
    InteropPermission           permission = new InteropPermission(InteropKind::ComInterop);
    SysMailer                   mailer;
    str                         Body;
    str                         ToAddress;
    str                         FromAddress = "aslam.pasha@infotech.net";
    str                         Subject = "Integration Alerts";
    int                         x;
    H_IntegrationParameters   parameters;
    Container                   id;
    LedgerJournalTrans          ljt;
    date                        checkdate;
    Real                        CheckDr , CheckCr ;
    int i,j;
    ;
    try
    {
       info("In the 'try' block. (j1)");
       info("infolog!");
       throw warning("test warning");
       throw error("test error");
       info("infolog!");
       throw warning("test warning");
        //throw Exception::Error;
    }
    catch
    {

        for (i=1; i<=infolog.line(); i++)
        {
            messageBody = ":" + infolog.text(i);

        }
        parameters = H_IntegrationParameters::find();
        id = str2con(parameters.HSEmailId,",");
        for(x=1 ; x <= conlen(id); x++  )
        {
            toaddress   =  strRem(conpeek(id,x)," ");
            Body = strfmt("%1", messageBody) ;
            CodeAccessPermission::revertAssert();
            permission.assert();
            mailer = new SysMailer();
           // CodeAccessPermission::revertAssert();
            mailer.quickSend(fromaddress,toaddress,subject,Body);
        }

    }
}

Friday 14 March 2014

Move File from One Folder to Another Folder using X++ ax 2009

Today i’m going to share you that , how to move a File from One Folder to another folder using X++.
Here we can achieve this with the Help of WINAPI(Windows Application Programming Interface). Even though we can do Copy a file, delete a file, Create Directory, getting the file Size, etc. Refer more Details WINAPI

static void MoveFilesFromFoldertoAnotherFolder(Args _args)
{
FilenameOpen fileNameOpen;
DialogField dialogFileName;
Dialog dialog;
Filename filePath;
Filename fileName;
Filename fileType;
FileName DestinationPath;
#File

;
DestinationPath = @'C:\Users\saadullah\Desktop\Dest\'; // Define your Destination Path
dialog = new Dialog("Move Files");
// AX 2009
dialogFilename = dialog.addField(typeId(FileNameOpen));
// AX 2012
// dialogFileName = dialog.addField(extendedTypeStr(FileNameOpen));
dialog.filenameLookupFilter([#AllFilesType]);
dialog.filenameLookupTitle("Select File");
dialog.caption("Move File");
dialogFilename.value(fileName);
if(!dialog.run())
return;
filenameOpen = dialogFilename.value();
[filePath, fileName, fileType] = fileNameSplit(fileNameOpen);
// MoveFile - The Original File won't be available once it's moved into destination path
WinAPI::moveFile(fileNameOpen, DestinationPath+FileName+FileType);
// CopyFile - The Original File will be available even if it's moved into destination path
//WinAPI::copyFile(fileNameOpen, DestinationPath+FileName+FileType);
// DeleteFile - Delete the Selected File
//WinAPI::deleteFile(fileNameOpen);

// If u need to Use this in Form Take look in AOT > Forms > Tutorial_Form_File
}

static void moveFile(args _args)
{
    #File
    Set                 permissionSet;
    System.Exception    netExcepn;
    str FileName = 'Libraries\Pictures\Images.jpg';
    str NewFileName = 'C:\Images.jpg';
    ;
    try
    {
        permissionSet =  new Set(Types::Class);
        permissionSet.add(new FileIOPermission(fileName,#io_write));
        permissionSet.add(new InteropPermission(InteropKind::ClrInterop));
        CodeAccessPermission::assertMultiple(permissionSet);
        WINAPI::copyFile(fileName,newFileName,true);
        CodeAccessPermission::revertAssert();
    }
    catch (Exception::CLRError)
    {
        info("Caught 'Exception::CLRError'.");
        netExcepn = CLRInterop::getLastException();
        info(netExcepn.ToString());
    }
}
 

Thursday 13 March 2014

Based on division id filter in the Report and evey page get new Item in ax 2009

Based on division id filter:-
while select custTable group by FedDivisionId where                    
                                                        (((DivisionId)&&(custTable.DivisionId == DivisionId))||(!DivisionId))&&
                                                        (((SubDivId) && custTable.SubDivId == SubDivId ) ||(!SubDivId)) &&
                                                        (((SectionId1)&&(custTable.SectionId == SectionId1))||(!SectionId1))

 Report and next:-

 if(itemid &&  itemid!=vendPackingSlipTransGlobal.ItemId)
 {
    itemId = vendPackingSlipTransGlobal.ItemId;
    element.newPage();  
    i=0;
 }
 i++;
Image add in to the report use this :-
display Bitmap footerImage()
{
    return SysResource::getResourceNodeData(SysResource::getResourceNode(resourceStr(dhtml_right)));
}
static void DataDic_ChangeCompany(Args _args)
{
    DataArea dataArea;
    CustTable custTable;
    ;
    while select dataArea
    {
        if (!dataArea.isVirtual)
        {
            info(strfmt("Company: %1", dataArea.id));
            changeCompany(dataArea.id)
            {
                custTable = null;
                while select custTable
                {
                     info(strfmt("%1, %2", custTable.dataAreaId, custTable.accountNum));
                }
            }
        }
    }
}
static void AreaID(Args _args)
{
    dataarea    area;
    ;
    while select area
    {
        info(area.Id);
    }
}

static void BatchJobSchedule_NUmberSeqListDelete(Args _args)
{
    BatchHeader batHeader;
    BatchInfo batInfo;
    RunBaseBatch rbbTask;
    str sParmCaption = "Delete --- NumberSeqList";
    ;
    rbbTask = new NubersequenceList_delete();
     batInfo = rbbTask .batchInfo();
    batInfo .parmCaption(sParmCaption);

    batInfo .parmGroupId(" ");
    batHeader = BatchHeader ::construct();
    batHeader .addTask(rbbTask);
    batHeader .save();
    info(strFmt("'%1' batch has been scheduled.", sParmCaption));
}

static void customerReadExcel(Args _args)
{
    SysExcelApplication application;
    SysExcelWorkbooks workbooks;
    SysExcelWorkbook workbook;
    SysExcelWorksheets worksheets;
    SysExcelWorksheet worksheet;
    SysExcelCells cells;
    COMVariantType type;
    int row = 1,Counter;
    CustAccount Customeraccount;
    CustAccount MergedaccountCustomeraccount;
    str company;
    CustName Name;
    FileName filename;
    CustTable CustTableDelete;
    CustTable Custtable,Custtablelocal;
    SalesJournalAutoSummary autosummary,autosummarylocal;

    #avifiles
    SysOperationProgress simpleProgress=new SysOperationProgress();

    ;
    application = SysExcelApplication::construct();
    workbooks = application.workbooks();
    filename = "C:\\list1.xlsx";

    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();
//
    startLengthyOperation();
    do
    {
        row++;
        Counter++;
        type = cells.item(row+1, 2).value().variantType();
    } while (type != COMVariantType::VT_EMPTY);
    endLengthyOperation();

    simpleProgress.setCaption("Progress bar example…");
    simpleProgress.setAnimation(#AviUpdate);
    simpleProgress.setTotal(Counter);
    row =1;
     startLengthyOperation();
    do
    {
        row++;
        Customeraccount = cells.item(row, 1).value().bStr();
        Name = cells.item(row, 2).value().bStr();
        MergedaccountCustomeraccount = cells.item(row, 3).value().bStr();
        company = cells.item(row, 4).value().bStr();
        ttsBegin;
        delete_from autosummary
              where autosummary.CustAccount == cells.item(row, 1).value().bStr();
        select firstOnly forUpdate  CustTableDelete
              where CustTableDelete.AccountNum == cells.item(row, 1).value().bStr();
        select firstOnly forUpdate  Custtable
              where Custtable.AccountNum == cells.item(row, 3).value().bStr();
        CustTableDelete.merge(Custtable);
        Custtable.doUpdate();
        CustTableDelete.doDelete();
        ttsCommit;
        simpleProgress.setText(strfmt("The value of i is %1", row));
        simpleProgress.setCount(row, 1);
    type = cells.item(row+1, 1).value().variantType();
    }
    while (type != COMVariantType::VT_EMPTY);
    endLengthyOperation();
    application.quit();
    info('hi');
}
static void LedgerTrans_For_Account(Args _args)
{
    LedgerTrans lt;
    ;
    select sum(AmountMST) from lt where lt.AccountNum == '30-11-84'
        && lt.TransDate >= str2date("01-01-2014",123)
        && lt.TransDate <= str2date("31-01-2014",123)
       &&  lt.TransDate >= mkdate(01,07,2012)
       &&  lt.TransDate <= mkdate(31,08,2012);
        && lt.Dimension[1] == '003';
        info(strfmt("%1",lt.AmountMST));

}
Normal Report Dialog parameters:-
public class ReportRun extends ObjectRun
{
     DialogField FieldFromDate,FieldToDate;
     transdate    FromDate,ToDate;
     int  Centerid,i;
}

public Object dialog(Object _dialog)
{
    DialogRunbase dialog = _dialog;
    ;
    FieldFromDate       = dialog.addField((typeid(FromDate)),'From Date');
    FieldToDate         = dialog.addField(typeid(ToDate),'To Date');
    return dialog;
}

public boolean getFromDialog()
{
    boolean ret;
    ;

    FromDate       =  FieldFromDate.value();
    ToDate         =  FieldToDate.value();
    ret   =true;
    return ret;
}

display transdate ToDate()
{
    return ToDate;
}

display transdate FromDate()
{
    return FromDate;
}

Friday 7 March 2014

Create Progress bars in Dynamics AX [startlengthyoperation, SysOperationProgress,Animations ] in ax 2009

This post is again useful for those developers who are new to X++ programming and would like to use progress bars or Hour glass indicators while some business logic is running, hinting the user that something is happening in the background.
Use a progress indicator during operations that take more than 2 seconds.
Use an hourglass mouse pointer if the process takes 2-7 seconds.
Use a progress bar if the process takes 8 seconds or more.
There are many ways to display operations in progress
1) Hourglass Indicators
2) Progress Bars
3) Progress controls on the forms
4) Animate Controls
Hour Glass Indicators Example:
Use startlengthyoperation() and endlengthyoperation() between ur business logic
Example :

static void HourGlassMousePointer(Args _args)
{
int i;
str value;
;
startLengthyOperation();
for( i = 1; i <= 200000; i++)
{
value += int2str(i) + ','; // some business logic
}

endLengthyOperation();
}

Below is how the hourglass indicator looks

2) Use SysOperationProgress class to show the progress Bars
Initialize a SysOperationProgress variable.
Set a caption for the form by using the SysOperationProgress.setCaption method.
Set an animation to run while the operation is in progress by using the SysOperationProgress.setAnimation method.
A number of animations are provided with Microsoft Dynamics AX. To view them, run the Tutorial_ShowAVIFiles class. If you use one of these animation files, you need to declare the AviFiles macro at the top of your code.
Specify the total number of operation steps.
This is needed for the time-remaining calculation. If you do not set the total number of operation steps, the progress indicator is not shown. The total is often a count of the number of records, and may be time-consuming to calculate. Don't specify the total if the time is taken to calculate the records is comparable to the total time taken for the operation.
Perform the operation. For each step, specify a description and a step number.
During the execution, the progress indicator is updated accordingly. The estimated time remaining is calculated and displayed.
The default update interval is 3 seconds. If the task of updating the display takes more than 10% of the update interval due to latency on the network connection, the update interval is increased by 1 second.
Example :

static void operationProgress_progressBars(Args _args)
{
#AviFiles
SysOperationProgress progress = new SysOperationProgress();
int i;
;

progress.setCaption("Progress bar example…");
progress.setAnimation(#AviUpdate);
progress.setTotal(50000);
for (i = 1; i <= 50000; i++)
{
progress.setText(strfmt("The value of i is %1", i));
progress.setCount(i, 1);
}
}

Below is the output:

3) Use progress control on the form
Create a new progress control and change the autodeclaration property of the progress control to yes as shown in the figure.

In the init() or run() method of the form modify the code as shown below.
SysDictClass dictClass;
int i;
int classCount;
classId classId;
Dictionary dictionary;
;
super();
dictionary = new Dictionary();
classCount = dictionary.classCnt();
progress.rangeLo(1);
progress.rangeHi(classCount);
progress.pos(1);
progress.step(1);

for (i=1; i <= classCount; i++)
{
progress.pos(i);
dictClass = new SysDictClass(dictionary.classCnt2Id(i));
info(dictClass.name());
}

4. Finally Animations: we can use Animations to let the end users know that process is running at the back ground.
We can use Animate controls to show the progress. Create a new form and add a animate control as shown below. Change the autoDeclaration property of the animate control to Yes


Override the run() method and paste the below code
public void run()
{
int i;
#AviFiles
;
super();
for (i = 1 ; i <= 10000; i ++)
{
Animate.animateFile(#AviPrint);
Animate.play(); // autoplay(true);
}

Animate.visible(false);
}

Below is the output

Please note: Progress bars are inbuilt in runbase frameworks

Wednesday 5 March 2014

InventoryOnHand AX report with ItemName & Warehouse info in ax 2009

InventoryOnHand AX report with ItemName & Warehouse info.
Today we’ll create a report look like standard Dynamics AX 2009 “InventOnhand” report but with some modifications which are adding ItemName & Warehouse info.
First: Create new report:
  1. Open AOT from toolbar or by Ctrl+O.
  2. Right click on Reports, & choose new report.report3
Second: Data query:
  1. We need basic information from InventSum & InventDim tables.
  2. In AOT right click on Tables and choose New window.report7
  3. Drag InventSum table into report’s DataSource.
  4. Drag InvnetDim table into InventSum’s DataSource.
  5. Create relation between two tables by adding new relation under InventDim DataSource and choose new relation. report6
  6. In relation choose InventDimId column in two tables.report4
Now we had the same data in the standard report, but as requirement we need the ItemName & Warehouse info, we’ll do it by using Data Methods.
Third: Data Method:
We need to get the ItemName for the ItemId field in InventDim (make sure) table, so we’ll write some X++ code in data method, let’s start coding:
  1. Right click on Report’s Method node and choose New method. report8
  2. Rename method to ItemName, make it return str (String) value with size 40 and Display property.
  3. Inside method we’ll write code to get the ItemName from InventTable for the ItemId in InventSum table.
?
1
2
3
4
5
6
7
8
9
//Get Item Name
display str 40 ItemName()
{
    str result;
    InventTable inventTable = InventTable::find(InventSum.ItemId);
    ;
    result = inventTable.itemName();
    return result;
}
?
1
  
Syntax:
?
1
2
//ItemId from the InevntSum Table DataSource
TableClass tableObject = TableClass::find(InventSum.ItemId);
Then we need to get the Inventory ID and name for the InventLocationId field in InventDim (make sure) table, so we’ll write some X++ code in data method, let’s start coding:
  1. Right click on Report’s Method node and choose New method.
  2. Rename method to WarehouseName, make it return str (String) value with size 45 and Display property.
  3. Inside method we’ll write code to get the Inventory ID and name from InventLocation for the InventLocationId in InventDim table.
?
1
2
3
4
5
6
7
8
9
10
//Get Warehouse Id and Name
display str 45 WarehouseName()
{
    str result;
    ;
 
    result = inventDim.inventLocation().InventLocationId + " " + inventDim.inventLocation().Name;
 
    return result;
}
Note: in the code above I didn’t use TableClass::find() method to get information from InventLocation Table, because there are two methods implemented in InvenDim TableClass to get the warehouse information.
Fourth: Design:
  1. Right click on Design and choose new design. report2
  2. Right click on AutoDesignSpecs and choose Generate specs from Query.report5 
  3. Drag required field from DataSource & drop them on InventSum_Body.
  4. Right click on InventSum_Body New –> String, Give it name for example ItemName.
  5. Right click on ItemName and choose properties.
  6. In properties window add Label for the field “Item Name” & DataMethod = ItemName. report1
  7. Repeat steps 4,5, & 6 but for Warehouse; give it name “Warehouse”, Label = “Warehouse”, & DataMethod = WarehouseName.
  8. Save report and run it.
report9