Sunday, 19 December 2010

Override the event methods on dialog controls in Dynamics AX

In generally most of the Form control events (Modifying Field, Cursor movements, Focusing events, etc...) can override using standard AX method. But in dialog control events are not as straight forward as it is on form controls. Today I’m going to show how we can override Dialog controls events.

Step 1: Create a Class extends by RunBaseBatch class & declare main variables. In my example I have extended by RunBaseBatch Class.

class Test_DialogField extends RunBasebatch
{
    CustAccount     CustId;
    DialogField     dialogCustId;
    DialogField     dialoglName;
    Dialog          dialog;

    #define.CurrentVersion(1)

    #localmacro.CurrentList
        CustId
    #endmacro
}

Step 2: Add Pack() & Unpack() methods. Here I have not written code to store & retrieve stored data. But I added those methods to avoid compiling errors.

public container pack()
{
    return connull();
}

public boolean unpack(container packedClass)
{
    return true;
}

Step 3: Add Main() method to Execute class.

static void main(Args args)
{
    Test_DialogField tmpDialogField = new Test_DialogField();
    ;

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

Step 4: The dialogPostRun() method should override like below. This will allow calling to the event methods.

public void dialogPostRun(DialogRunbase tmpdialog)
{
    super(tmpdialog);
    tmpdialog.dialogForm().formRun().controlMethodOverload(true);
    tmpdialog.dialogForm().formRun().controlMethodOverloadObject(this);
}


Step 5: Add code to display dialog fields.

protected Object dialog(DialogRunbase tmpdialog, boolean forceOnClient)
{
    ;
    dialog = super(tmpdialog,forceOnClient);
    dialogCustId  = dialog.addFieldValue(typeid(CustAccount),"Customer", "Customer");
    dialoglName  = dialog.addFieldValue(typeid(Name),"Name", "Name");

    return dialog;
}

Step 6: When we have used Dialog field in the class, that Dialog field name in the System will appear with a different format. Its look like: fld<ID>_1. This ID value can be changed according to number of dialog filed which we have used. By using following step we can get exact Field ID & system Name.

·        Run the class which you created
·        Right Click on the Customer field & select “Setup”
·        You will get below form. I have coloured Dialog Filed System name by RED Colour. In my example System name of the Customer Dialog Field is Fld1_1.


This System Name we should use to write our “modified” method. Then it will call whenever a value of the dialog control with ID 1 is modified. In our case it is Customer ID field.

public boolean fld1_1_modified()
{
    FormStringControl control = dialog.formRun().controlCallingMethod();
    boolean isFieldModified;
    ;
    isFieldModified = control.modified();

    if(isFieldModified)
    {
    dialoglName.value(custTable::find(control.text()).Name);
    }
    return isFieldModified;
}

When you execute the class & select a customer Id, then above method will call & return the customer Name to other dialog box.

Hope you got an idea about overriding the Dialog Field methods in Dynamics AX... Enjoy in Dynamics AX World.


Wednesday, 15 December 2010

How to open TIF Image files in Dynamics AX

Today I’m going to discuss about one of another important feature in Dynamics AX. As well as the Other Programming languages, Axapta is supporting ActiveX object handling.
ActiveX control is a small program, which contains set of instruction & functions. Sometimes it’s called as add-ons.

Generally we can create an image viewer using this ActiveX object. In standard AX is coming with “Microsoft Web Browser” class for handling the Image Viewer ActiveX Control. But this viewer is accepting limited image file formats such as .JPG, GIF…

So I’m going to explain, powerful image viewer ActiveX control which supports a lot of popular image file extension, including TIFF, MNG, JNG,  BMP, GIF, ICO, JPEG,  PCX, PNG, PSD, WMF, WBMP, TGA, PGX, RAS, PNM.

That image Viewer ActiveX Control & Type Library is coming with Microsoft Office Package. That Is called “Microsoft Office Document Imaging 2003 (MODI)” model.

Step 1: When ActiveX control is placed in your PC, we have to get those files in to the Axapta using Wrapper Class. That can be done as follows,

Tools \ Development Tools \ Wizards \ COM Class Wrapper Wizard & go “Next”

Step 2:  select the “Microsoft Office Document Imaging 12.0 Type Library”. & click “Next”

Step 3: Enter an element mask. That will be appended to the front of the all elements generated by Wizard. In my example I’ve chosen “INDMODI”. & click “Next”.

Step 4: Create a new form & add ActiveX Control by right click on the design
In the ActiveX browser select the “Microsoft Office Document Imaging Viewer Control 12.0”.

Step 5: we need to specify the image path to open the file. For that add following code to the form


//Declaring Variable
public class FormRun extends ObjectRun
{
    INDMODIDocument    modiDocument;
}

//Initialize the Image path
public void init()
{
   ;
    super();
    activex.filename("Z:\\Images\\TestImage.gfd");
}


public void run()
{
    try
    {
        if(activeX.document())
        {
            modiDocument = new UKMODIDocument(activeX.document());
            super();
        }
    }
    catch (Exception::Error)
    {
        activeX.filename('');
    }
}


//Clear the Memory & Buffer
public void close()
{
    super();
    modiDocument.Close();
    activex.filename('');
}


Wednesday, 8 December 2010

Retrieve External Data using ODBC connection in Dynamics AX

When I’m flying in Dynamics AX world, I found most of the AX users are struggling to handle data from out source (External source such as MS-Access Database, Oracle Database, etc....).

In below I’m going to explain, how we can connect to the External Database using ODBC(Open Database Connectivity) Connection & retrieve data from that DB.

First we have to create a ODBC Datasource which has connected our Database. In my Example i have used DS as my Datasource name.

server static void GetShippingTrans(CustTable custTable)
{

     // Variable Declaration
LoginProperty lP;
OdbcConnection con;
Statement st;
ResultSet rS;
Str sqlS;
str databaseName = "Test"; 
MyShippingTrans trans;
SqlStatementExecutePermission sqlPermission;
;

// Initialize new Login Property
lP= new LoginProperty();

// Set DSN to the Login Property
lP.setDSN(DS);

//Set the correct DataBase to retrieve Data (May have more than one Database in that DSN)
lP.setDatabase(databaseName);

try
{

 //Create ODBC Connection by using Login Property
con= new OdbcConnection(lP);
st= con.createStatement();

//SQL Statement to select the Records from the Table
sqlS = StrFmt("SELECT %1, %2, %3 FROM Customer WHERE " +
"Customer.id = '%4',"Name", "DOB", "Height", custTable.CustId );

//Create a permission to execute SQL Statement
sqlPermission = new SQLStatementExecutePermission(sqlS);
sqlPermission.assert();

//Execute SQL Statement & retrieve the result set
            rS = st.executeQuery(sqlS);

while (rs.next())
{
            //Manipulate retrieved data.......
                     info(strFmt("Cust Name :%1    DOB : %2    Hieght : %3 "
                     ,rs.getString(1), rs.getDate(2), rs.getReal(3)));
}
CodeAccessPermission::revertAssert();
}
catch (Exception::Error)
{
            error(strFmt("Error accessing Customer database"));
}
}


I hope, now everyone has an idea about retrieving data from external data base & manipulating those fetched data.

Friday, 3 December 2010

Microsoft SQL Shedule Backup

Step 1: Open Object explorer in SQL and select “Management” ---> Maintenance Plans

Step 2: Create a new maintenance plan for Shedule Backup

Step 3: A new window pops up and asking for the name of the plan.


Step 4: Once entered, another new window opens


Step 5:  On the Top Left corner (Marked by red color box), from the Maintenance Plan Tasks, select “Back up Database Task”.


Step 6: Drag and drop “Back up Database Task” to Design part


Step 7:  Double click the Box and a window opens as follows:


Step 8: Select the Database to be taken back up


Step 9: Select the folder where the database has to be taken back up  and also enter the frequency when the database back up has to take place.

How to Manipulate String function in Dynamics AX

1.) Convert first charector in to Capital [str2Capital()]
        static void Job99(Args _args)
        {
            str source,desti;
            ;
            source  = 'dyanamics ax';
            desti   = str2Capital(source);
            info(strfmt("%1 : %2",source,desti));
        }
    Using str2CapitalWord() method can convert all first cherectors of the words in Sentence.
   
2.) Concatenate the word or sentence from specified charector. [str2Con()]
        static void Job99(Args _args)
        {
            str         source,desti;
            container   Con;
            int         i;
            ;
            source  = 'dyana,mic,s ax';
            Con   = str2Con(source,',');
            for (i = 1; i <= conlen(Con); i++)
            {
                info(strfmt("%1",conpeek(Con,i)));
            }
        }

3.) Format string type Date & return as Date type [str2Date()]
        static void Job99(Args _args)
        {
            str         input;
            Date        output
            ;
            input  = '05/30/2010';
            output  = str2Date(input,213);
            info(strfmt("%1",output));
        }
        123 : DMY
        213 : MDY
   
        Output will give as DMY format.
       
4.) Check a string which conatin integer value [strIntOk()]
   
        static void Job99(Args _args)
        {
            str         input;
            boolean     output;
            ;
            input   = '1294';
            output  = str2IntOk(input);
            if(output)
                info(strfmt("Integer Value"));
            else
                info(strfmt("Not a Integer Value"));
        }

5.) Check whether end charectors are matching or not [strEndsWith()]
   
        static void Job99(Args _args)
        {
            str         input1,input2;
            boolean     output;
            ;
            input1  = 'dyanmics ax';
            input2  = 'ax';
            output  = strEndsWith(input1,input2);
            if(output)
                info(strfmt("OK"));
            else
                info(strfmt("Not OK"));
        }
       
6.) Concatanate string from Left side with fix no. of charectors [strLFix()]
   
        static void Job99(Args _args)
        {
            str         input;
            str         output;
            ;
            input  = 'dyanmics ax';
            output  = strLfix(input,5);
            info(strfmt("%1",output));
        }

Create a Report using Temporary Table

Here I have showed how to create a dynamics AX report using Temporary Table. My temporary table name is "HOLProfitLossSummaryTmp" which contain five fields called ItemCategoryId, bfpStructureID, Name, CostAmount, SecondaryAmount. This report grouped by Item category ID and Structure ID. Finally it has showed the Total value according to the Group.
//Declare a variable to store values
public class ReportRun extends ObjectRun
{
//For User Selection
DialogGroup dialogGroupPeriodCode;
DialogField dialogFromDate;
DialogField dialogToDate;
DialogField dialogStructureID;
DialogField dialogItemCategoryID;
DialogField dialogDepartment;
DialogField dialogSelect;
IssueReturn USelection;
str Selection;
TransDate fromDate;
TransDate toDate;
ItemCategoryId UCategoryId;
str UCatogory;
bfpStructureId UStructureId;
Dimension UDepartment;
str Department1;

//For Data Filling to tempory Table
str StructureID;
ItemCategoryId CategoryID;
real LocalAmount,SecondaryAmount;
real LocalTotal,SecondaryTotal,LocalGrandTotal,SecondaryGrandTotal;
HOLProfitLossSummaryTmp HOLProfitLossSummaryTmp;
}
//Show dialog Fields in Parameter Form to user Selection
public Object dialog(Object _dialog)
{
DialogRunbase dialog = _dialog;
;
dialogGroupPeriodCode = dialog.addGroup("Parameter");
dialogItemCategoryID= dialog.addFieldValue(typeid(ItemCategoryId), UCategoryId,"Item Category ID", "Item Category ID");
dialogStructureID= dialog.addFieldValue(typeid(bfpStructureId), UStructureId,"Structure ID", "Structure ID");
dialogGroupPeriodCode = dialog.addGroup("Date Interval");
dialogFromDate = dialog.addFieldValue(typeid(TransDate),fromDate, "From Date", "From Date");
dialogToDate = dialog.addFieldValue(typeid(TransDate),toDate, "To date","To date");
dialogGroupPeriodCode = dialog.addGroup("Transaction Type");
dialogSelect = dialog.addFieldValue(typeid(IssueReturn), USelection,"Transaction Type", "Transaction Type");
return dialog;
}

//Getting Values from User
public boolean getFromDialog()
{
;
fromDate = dialogFromDate .value();
toDate = dialogToDate .value();
UCatogory = dialogItemCategoryID.value();
UStructureId = dialogStructureID.value();
Selection = dialogSelect.value();
return true;
}

//Return Exchange Rate according to the Date & Company
AmountMST ExchangeValue(TransDate TranDate)
{
CompanyInfo CompanyInfo;
HOLExchRates HOLExchRates;
;
HOLExchRates=new HOLExchRates();
select CompanyInfo where CompanyInfo.dataAreaId==InventJournalTrans.dataAreaId;
Return HOLExchRates.find2(CompanyInfo.SecondaryCurrencyCode,TranDate);
}
//Send filtered data to the report using Temporary Table
public boolean fetch()
{
boolean ret=false;
QueryRun qr;
InventTable InventTable1;
InventJournalTrans InventJournalTrans1;
Boolean isReportEmpty;
ExchRate Ex;
;

//Initialize Variables
CategoryId=0;
StructureID='';
LocalAmount=0;
SecondaryAmount=0;
LocalTotal=0;
SecondaryTotal=0;
LocalGrandTotal=0;
SecondaryGrandTotal=0;
isReportEmpty=true;

//Filterring Query according to the User Selection
qr = new Queryrun(element.query());
//Structure ID
if (UStructureId!="")
qr.query().dataSourceTable(tablenum(InventTable)).addRange(fieldnum(InventTable,bfpStructureId)).value(UStructureId);
//Item Category
if (UCatogory!='0')
qr.query().dataSourceTable(tablenum(InventTable)).addRange(fieldnum(InventTable,ItemCategoryId)).value(UCatogory);
//Date Range
if (fromDate || toDate)
qr.query().dataSourceTable(tablenum(InventJournalTrans)).addRange(fieldnum(InventJournalTrans,TransDate)).value(queryRange(fromDate, toDate));
//Transaction Type (Selection=0 : "Issue" , Selection=1 : "Return" ,Selection=2 : "All" )
if (Selection=='0')
qr.query().dataSourceTable(tablenum(InventJournalTrans)).addRange(fieldnum(InventJournalTrans,Qty)).value('<0');
else if (Selection=="1")
qr.query().dataSourceTable(tablenum(InventJournalTrans)).addRange(fieldnum(InventJournalTrans,Qty)).value('>0');
element.queryRun(qr);

while (qr.next())
{
InventTable1=qr.get(tablenum(InventTable));
InventJournalTrans1=qr.get(tablenum(InventJournalTrans));
//If Category Id Change print Totals & new Category ID
if ((CategoryId!=InventTable1.ItemCategoryId) && (InventTable1.ItemCategoryId!=0))
{
if (CategoryId!=0)
{
HOLProfitLossSummaryTmp.CostAmount=LocalAmount;
HOLProfitLossSummaryTmp.SecondaryAmount=SecondaryAmount;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
//Send Item Category Total to the report
HOLProfitLossSummaryTmp.TotalLocalAmount=LocalTotal;
HOLProfitLossSummaryTmp.TotalSecondaryAmount=SecondaryTotal;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
LocalGrandTotal+=LocalTotal;
SecondaryGrandTotal+=SecondaryTotal;
LocalAmount=0;
LocalTotal=0;
SecondaryAmount=0;
SecondaryTotal=0;
StructureID='';
}
CategoryId=InventTable1.ItemCategoryId;
HOLProfitLossSummaryTmp.ItemCategoryId=CategoryId;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
}
//If Structure Id Change print Totals & new Structure Details
if ((StructureID!=InventTable1.bfpStructureId) && (InventTable1.ItemCategoryId!=0))
{
if (StructureID!='')
{
HOLProfitLossSummaryTmp.CostAmount=LocalAmount;
HOLProfitLossSummaryTmp.SecondaryAmount=SecondaryAmount;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
LocalAmount=0;
SecondaryAmount=0;
}
StructureID=InventTable1.bfpStructureId;
HOLProfitLossSummaryTmp.bfpStructureId=StructureID;
HOLProfitLossSummaryTmp.Name=this.StructureName();
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
}
//Calculate Primary & Secondary Values
if ( (CategoryId!=0) && (StructureID!=''))
{
LocalAmount+=InventJournalTrans1.CostAmount;
LocalTotal+=InventJournalTrans1.CostAmount;
Ex=this.ExchangeValue(InventJournalTrans1.TransDate);
if (Ex>0)
{
SecondaryAmount+=(InventJournalTrans1.CostAmount/Ex);
SecondaryTotal+=(InventJournalTrans1.CostAmount/Ex);
}
}
}

LocalGrandTotal+=LocalTotal;
SecondaryGrandTotal+=SecondaryTotal;
//Set Report is empty or Not
if (LocalGrandTotal!=0)
isReportEmpty=false;
//Print Grand Values
if (!isReportEmpty)
{
HOLProfitLossSummaryTmp.CostAmount=LocalAmount;
HOLProfitLossSummaryTmp.SecondaryAmount=SecondaryAmount;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();

HOLProfitLossSummaryTmp.TotalLocalAmount=LocalTotal;
HOLProfitLossSummaryTmp.TotalSecondaryAmount=SecondaryTotal;
this.send(HOLProfitLossSummaryTmp);
HOLProfitLossSummaryTmp.clear();
this.send(HOLProfitLossSummaryTmp);
this.send(HOLProfitLossSummaryTmp);
//Print Grand Total
element.execute(1);
}
super();
return true;
}

//Display Structure Name
Display Name StructureName()
{
bfpInventStructureId bfpInventStructureId;
select bfpInventStructureId where bfpInventStructureId.StructureId==HOLProfitLossSummaryTmp.bfpStructureId;
return bfpInventStructureId.Name;
}

//Display DatePage
//BP Deviation documented
display str 70 datePage()
{;
// Date %1 %2 Page %3
return strfmt(element.design().lookupLabel(literalstr("Date ")),element.startDate(),
time2str(element.startTime(),-1,-1),element.page());
}

//Display Company Logo
//BP Deviation documented
display Bitmap CompanyLogo()
{
CompanyInfo companyInfo = CompanyInfo::find();
;
return CompanyImage::find(companyInfo.DataAreaId, companyInfo.TableId,companyInfo.RecId).Image;
}

//Display Start Date
//BP Deviation documented
display PrintDate startDate()
{;
return element.startDate();
}

//Display Page No
//BP Deviation documented
display str 20 pageNum()
{;
//Page %1
return strfmt(element.design().lookupLabel(literalstr("Page ")), element.page());
}

//Display Company Name
//BP Deviation documented
display Name CompanyName()
{;
return CompanyInfo::name();
}

//Display Report Name
//BP Deviation documented
display Name reportName()
{;
return element.design().lookupCaption();
}

//Display Start Time
//BP Deviation documented
display timeOfDay startTime()
{;
return element.startTime();
}

//Display Grand Total from Secondary Currency
//BP Deviation documented
Display real GrandSecondary()
{
Return SecondaryGrandTotal;
}

//Display Grand Total from Primary Currency
//BP Deviation documented
Display real GrandLocal()
{
return LocalGrandTotal;
}