Friday, 30 May 2014

,

Pass The Parameters to Class

To pass the parameter from the form selected record to class

1.Create a class as following code.
2.Add this class to Actions MenuItem.
3.In form add this MenuItemButton.
Open the form Select a record in the grid and click the button.
That record passed to the Main method. in info you will Vendor id get 2 times.
Cause New Method is calling and Post method is calling.
public class EmplProcess
{
VendTable _VendTable;
}
-
public void new(Common vTable)
{
_VendTable = vTable;
this.post();
}
-
public void post()
{
info(_VendTable.AccountNum);
}
-
public static void main(Args args)
{
Common _common;
EmplProcess _EmplProcess;
_common = args.record(); //getting the record from the form
_EmplProcess = new EmplProcess(_common);//passing the above record to the new method
_EmplProcess.post();// calling the post method
}
__________________________________________________________________________________–
While creating Object for class we can pass the parameter.
ex:
Class1 cls;
;
cls = new Class(VendTable);// this is Data Source name in Vend Table form
//in class override the new method and assign the Parameter.
public void new(VendTable vTable)
{
_VendTable = vTable;
}
Read more →
,

Passing Parameters to a Report in Dynamics AX

Creating reports in AX is generally ‘a walk in the park’ even for the new developers not fully acquaint with the syntax of X++. However, it sometimes becomes challenging to understand how the parameters could be passed to a report when you want to initiate that report from a form.
Let’s look at an example where you may want to create a ‘Purchase Requisition Report’ that the users could generate to see the status of each purchase requisition and the associated workflow entries for that Purchase Requisition.
I will not go into the details of how to develop this report, but you should know that such a report do not exist in the out-of-the-box functionality within AX 2009.
So let’s say that you have developed this report and now when you generate this report you can pass on the required ‘Purchase Requisition ID’ in the ‘Parameter Prompt’ of the report to view the particular PR details accordingly.
However, now in the next step you want to call this report from the ‘Purchase Requisition Form’ (i.e PurchReqTable). To do this, you should first create a ‘Button’ within the ButtonGroup on the form.
Now right-click on the ‘Methods’ node within the newly created button and choose ‘Override Method –> clicked’
Within the clicked function, you should write the following code;
void clicked()
{
Args args = new args();
ReportRun reportRun;
;
args.parm(PurchReqTable.PurchReqId);
args.name(reportstr(PurchRequisitionDetails));
reportRun = classFactory.reportRunClass(args);
reportRun.init();
reportrun.run();
//hello
super();
}
The above code calls the args() system class. This class is used to pass arguments to a class-constructor. You can pass information such as name, caller, and parameters to a new class. This code passes the relevant Purchase Requisition ID (which is currently selected by the user on the form) to the report ‘PurchRequisitionDetails’ in the above code.
Now, you need to go to the report (which in this case is PurchRequisitionDetails). Right-Click on the methods node of the Report and click on ‘Override Method –> init’
In this init method, you need to enter the following code to allow the report to read the parameters from the form.
public void init()
{
;
try
{
if(element.args().parm())
{
this.query().dataSourceTable(tablenum(PurchReqTable))
.addRange(fieldnum(PurchReqTable, PurchReqId)).value(element.args().parm());
this.query().userUpdate(false);
this.query().interactive(false);
super();
}
}
catch(exception::Error)
{
info(“Error in init method”);
}
}
Once you have got the above code correctly entered, you should now be able to generate your report directly from the form.
Read more →
,

passing parameters between forms in AX

In dynamics AX, working with forms, there are times when you need to pass some information from current form to the opened form, so the question arrived is that what’s the best way to open the new form and pass information.

Answer: It depends upon the information that is needed in the new form; there is Args class that plays an important role to pass the information. Let’s take a look on some of the important methods of that class
Args class (Argument)
“The Args class is used to pass arguments such as a name, a caller, and parameters between application objects”
Some important methods are
Caller
Gets or sets the instance of the object that created this instance of the Args class.
name
Gets and sets the name of the application object to call.
parm
Gets or sets a string that specifies miscellaneous information for the called object.
parmEnum
Gets or sets the enumeration value of the enumeration type that is specified in the parmEnumType method.
parmEnmType
Gets or sets the ID value of any enumeration type.
ParmObject
Gets or sets an instance of any object to pass to the called object.
record
Gets and sets the record from the table on which the caller object is working.
There are four methods that can be used to pass extra information to the new class:
  1. The parm method – to pass strings
  2. The parmEnum and parmEnumType method – to pass enumeration values
  3. The parmObject method – to pass an object of any type.
Examples:
1.      If you need a data from the parent form main data source for the current record, so you don’t need to do anything in parent, just create a display menu item and give the form name that needs to be opened, create a menuItem button and assign the newly created menu item.
Override the Init method on opened form
And you get the parent dataset records as
element.args().record()
2.      Need to pass any object/string/Enum
Use the same approach for creating the button
Parent form
void clicked()
{
Args args;
FormRun formRun;super();
args = new Args(formstr(FormName));
 // To pass any string value
args.parm( value>);
 // To pass any object
args.parmObject(<object>);
 // To pass any Enum
       args.parmEnum( EnumValue);
args.parmEnumType( EnumNum( <EnumName>) );
 formRun = classFactory.FormRunClass(args);
formRun.init();
formRun.run();
formRun.wait();
formRun.detach();
parenttable_ds.refresh(); // Refreshing parent table DataSourceTable
parenttable_ds.executeQuery(); // Refreshing Parent DataSourceTable
}
Child Form
void init()
{
args = element.args();
    // get string parameter
<string> = args.parm();
    // get object parameter
    <object> = args.parmObject();
    // get enum parameter
if( element.args().parmEnumType() == EnumNum( <EnumName>) )
{
<enum contol/variable>  =( element.args().parmEnum() );
}
}3.      There are many parameters that you need to pass to the child form.
               In that scenario, you need to create an extra class (parameter/contract class), you can first set the parameters in the init method for that class, use the parmObject for setting and gets the object on the child form
=======================================================================================

Argument Passing between Forms in Dynamics Ax 2009

Here a sample code to pass argument to one form to another form and using of Args() class.
Steps:
1) Create two Forms named FormA and FormB
2)Use the EmplTable as the Datasource of both forms
3)Design FormA with one Grid and add 4 data fields to the Grid(EmplId,DEL_Name,Grade,EmplStatus…..)
4)Assign the datasource for the grid and the data fields
5)Add a Button in FormA
6)Override the Clicked() method and write the below code:
void Clicked()
{
Args    _args;
FormRun _formRun;
EmplId   _empId;
;
_empId = EmplTable.EmplId;  // Selected employee id in the Grid is assigned to the variable which is pass to the next form
_args = new Args(); // creating a object for args class
_args.name(formstr(VA_FormB));  // Form Menuitem
_args.caller(this);  // Form Caller(Current Form is mentioned as this)
_args.parm(_empId); // Employee Number is passed to next form[but parm() is not a best practise]
_args.record(EmplTable); // Table name is passed
_formRun = ClassFactory.formRunClass(_args); //new FormRun(_args);   // Creating object for FormRun
_formRun.init();   // Form Initialization for Load
_formRun.run();  // Form Run for process
_formRun.wait(); // Form Wait for Display
}
7) Open the Second Form – FormB
8) Add one Grid Control and set the Data Source is EmplTable
9) Add 4 data fields as same in the Form A
10)Now Override the Init() of Form
public void init()
{
parmid      _parmId;
EmplTable   _EmplTable;
//     DictTable   _dictTable;    FormBuildDataSource   _ds;    FormBuildGridControl frmGrid; // These are for dynamicForm creation so leave it
_parmId =  element.args().parm(); // Getting the argument value from the Caller
//info(int2str(element.args().record().TableId));
if(!element.args().caller())   // Check the form is called by caller or directly, if directly it throw error
throw error(“Cant Run Directly”);
if(element.args().record().TableId == tablenum(EmplTable))   // check if the sent Table and the Current form table are equal or not
{
//        _EmplTable = element.args().record();  // Assign the Received Table name to Local Variable
//_dictTable = new DictTable(element.args().record().TableId);  // leave it , is used for Dynamic Form Creation
//_ds = form.addDataSource(_dictTable.name());  // leave it , is used for Dynamic Form Creation
//_ds.table(_dictTable.id());   // leave it , is used for Dynamic Form Creation
//frmGrid = form.addControl(FormControlType::Grid, “Grid”);   // leave it , is used for Dynamic Form Creation
//frmGrid.dataSource(_ds.name());   // leave it , is used for Dynamic Form Creation
//info(strfmt(“%1     %2″,_EmplTable.EmplId,_EmplTable.DEL_Name));
//frmGrid.addDataField(_ds.id(),fieldnum(EmplTable, DEL_Name));  // leave it , is used for Dynamic Form Creation
//        EmplTable_EmplId.dataSource(_EmplTable);   // leave it , is used for Dynamic Form Creation
//        EmplTable_EmplId.dataField(fieldnum(EmplTable,EmplID));   // leave it , is used for Dynamic Form Creation
//        EmplTable_DEL_Name.dataSource(_EmplTable);   // leave it , is used for Dynamic Form Creation
//        EmplTable_DEL_Name.dataField(fieldnum(EmplTable,EmplId));  // leave it , is used for Dynamic Form Creation
//        EmplTable_DEL_Email.dataSource(_EmplTable);   // leave it , is used for Dynamic Form Creation
//        EmplTable_DEL_Email.dataField(fieldnum(EmplTable,EmplId));   // leave it , is used for Dynamic Form Creation
super();  // Form Initialization
}
else
{
info(“DataSet Not Received”);  // throw error
}
}
11)Override the Init() of the DataSource
public void init()
{
switch(element.args().dataset())// get the table id sent by caller
{
case tablenum(EmplTable):  // check the table if matches with this tableid
{
_EmplID  =   element.args().parm();  // get the argument value
query   = new Query();            queryBuildRangeProj =                                          query.addDataSource(tablenum(EmplTable)).addRange(fieldnum(EmplTable,EmplId));          // query build for the form to display
queryBuildRangeProj.value(_emplId); // Criteria for the form
EmplTable_ds.query(query); // execution of the query
break;
}
}
super(); //datasource  initialization on the form based on the criteria
}
12) Save it, and create two menu items for each.
13) It is important to change the runon property of the FormB as CalledFrom.
14)Run the FormA and select an Employee Record and click the button.
15)The FormB opens with the Related information of the Selected Employee on form.
===========================================================================

Passing values between forms

For passing parameters from one form to another a special class Args is usually used.
Example:
The code of button click event of FormA which calls FormB and passes some parameters to that form.
void clicked()
{
    // Args class is usually used in Axapta for passing parameters between forms
    Args            args;
    FormRun         formRun;
    // Our custom made class for passing complex set of parameters
    FormBParams     formBParams = new FormBParams();
    Array           items = new Array( Types::String );
    int         i;
    ;

    args = new args();

    // Our values which we want to pass to FormB
    // If we want pass just simple string we can use 'parm' method of 'Args' class
    args.parm( strValue.text() );
    // We also can pass enum value to FormB
    args.parmEnum( NoYesEnumValue.selection() );
    args.parmEnumType( EnumNum( NoYes ) );
    // and also can pass a cursor pointing to some record (in our case it is EmplTable )
    args.record( EmplTable );

    // If we want pass more complex set of parameters we can develop our own class
    // just for passing our parameters.
    formBParams.parmSomeDate( someDate.dateValue() );
    formBParams.parmSomeTime( someTime.value() );
    for( i=0; i<ListBox.items(); i++ )
    {
        items.value( i+1,  ListBox.getText( i ) );
    }
    formBParams.parmItems( items );
    // Pass our object to FormB
    args.parmObject( formBParams );

    // Run FormB
    args.name( formstr( FormB ) );
    formRun = classFactory.formRunClass( Args );
    formRun.init();
    formrun.run();
    formrun.wait();

    if( formrun.closedOk() )
    {
        answerFromFormB.text( args.parm() );
    }
    super();
}
The code of init method of FormB
public void init()
{
    EmplTable       emplTableRecord;
    FormBParams     formBParams;
    Array           items;
    int             i;
    ;
    super();

    // Check for passed arguments
    if( element.args() )
    {
        // get string parameter
        strValue.text( element.args().parm() );

        // get enum parameter
        if( element.args().parmEnumType() == EnumNum( NoYes ) )
        {
            NoYesEnumValue.selection( element.args().parmEnum() );
        }
        // get object parameter
        if( element.args().parmObject() )
        {
            formBParams = element.args().parmObject();
            items       = formBParams.parmItems();
            for( i=1; i<=items.lastIndex(); i++ )
            {
                ListBox.add( items.value(i) );
            }
            someDate.dateValue( formBParams.parmSomeDate() );
            someTime.value( formBParams.parmSomeTime() );
        }
        // get record parameter
        if( element.args().record() && element.args().record().TableId == TableNum( EmplTable ) )
        {
            emplTableRecord =  element.args().record();
            emplName.text( emplTableRecord.Name );
        }
    }
}
The code of ok button click event of FromB
void clicked()
{
    super();
    element.args().parm( strAnswer.text() );
    element.closeOk();
}
The above code is cut out from a demo which you can download here.
===========================================================================
For passing parameters from one form to another a special class Args is usually used.
Example:
The code of button click event of FormA which calls FormB and passes some parameters to that form.
void clicked()
{
    // Args class is usually used in Axapta for passing parameters between forms
    Args            args;
    FormRun         formRun;
    // Our custom made class for passing complex set of parameters
    FormBParams     formBParams = new FormBParams();
    Array           items = new Array( Types::String );
    int         i;
    ;

    args = new args();

    // Our values which we want to pass to FormB
    // If we want pass just simple string we can use 'parm' method of 'Args' class
    args.parm( strValue.text() );
    // We also can pass enum value to FormB
    args.parmEnum( NoYesEnumValue.selection() );
    args.parmEnumType( EnumNum( NoYes ) );
    // and also can pass a cursor pointing to some record (in our case it is EmplTable )
    args.record( EmplTable );

    // If we want pass more complex set of parameters we can develop our own class
    // just for passing our parameters.
    formBParams.parmSomeDate( someDate.dateValue() );
    formBParams.parmSomeTime( someTime.value() );
    for( i=0; i<ListBox.items(); i++ )
    {
        items.value( i+1,  ListBox.getText( i ) );
    }
    formBParams.parmItems( items );
    // Pass our object to FormB
    args.parmObject( formBParams );

    // Run FormB
    args.name( formstr( FormB ) );
    formRun = classFactory.formRunClass( Args );
    formRun.init();
    formrun.run();
    formrun.wait();

    if( formrun.closedOk() )
    {
        answerFromFormB.text( args.parm() );
    }
    super();
}
The code of init method of FormB
public void init()
{
    EmplTable       emplTableRecord;
    FormBParams     formBParams;
    Array           items;
    int             i;
    ;
    super();

    // Check for passed arguments
    if( element.args() )
    {
        // get string parameter
        strValue.text( element.args().parm() );

        // get enum parameter
        if( element.args().parmEnumType() == EnumNum( NoYes ) )
        {
            NoYesEnumValue.selection( element.args().parmEnum() );
        }
        // get object parameter
        if( element.args().parmObject() )
        {
            formBParams = element.args().parmObject();
            items       = formBParams.parmItems();
            for( i=1; i<=items.lastIndex(); i++ )
            {
                ListBox.add( items.value(i) );
            }
            someDate.dateValue( formBParams.parmSomeDate() );
            someTime.value( formBParams.parmSomeTime() );
        }
        // get record parameter
        if( element.args().record() && element.args().record().TableId == TableNum( EmplTable ) )
        {
            emplTableRecord =  element.args().record();
            emplName.text( emplTableRecord.Name );
        }
    }
}
The code of ok button click event of FromB
void clicked()
{
    super();
    element.args().parm( strAnswer.text() );
    element.closeOk();
}

Read more →
,

X++ Implementation of few SQL Keywords

As we already saw in the Previous post, In X++, we can directly use database related statements similar to any other code. Here, we will see and understand how to implement few well-known SQL keywords in X++.

Example(1): To print records in custTable in descending order.
while select custTable order by custTable.AccountNum desc
{
print(strfmt(“%1, %2″, custTable.accountNum, custTable.Address));
}
pause;
Output:
By using order by clause similar to the SQL queries with the keyword ‘desc’, we are able to achieve the expected output.
Example(2): To print Average of Amount from custTrans table.
while select avg(AmountMST) from custTrans
{
print(custTrans.AmountMST);
}
pause;
Output:
Here, we are using while select statement with the Aggregate keyword ‘avg’ on the required field to get the Average of all the values of AmountMST in the table.
Also note that to print the output, You can get the result from the same field, i.e, custTrans.AmountMST.
The below are Details, Syntax and an AX Example respectively for few well-known SQL keywords:
KeywordExample
ascSet the sorting order to ascending. All selects are default fetching data ascending.
Syntax: select custTable order by accountNum asc;
descSet the sorting order to descending. Used in combination with order by or group by.
Syntax: select custTable order by name desc;
AX Example: See table method CustTable.lastPayment().
avgSelect uses aggregate keyword (avg) using only one call to the database calculating a result based on multiple records
Syntax: select avg(amountMST) from custTrans;
AX Example: See class method KMKnowledgeCollectorStatisticsExecute.runQuery().
countAggregate keyword used to count the number of records fetched.
Syntax: select count(recId) from custTrans;
AX Example: See class method KMKnowledgeCollectorStatisticsExecute.runQuery().
sumAggregate keyword used to sum values of a field fetched.
Syntax: select sum(amountMST) from custTrans;
AX Example: See class method KMKnowledgeCollectorStatisticsExecute.runQuery().
maxofAggregate keyword used to return the highest field value fetched
Syntax: select maxOf(amountMST) from custTrans;
AX Example: See class method KMKnowledgeCollectorStatisticsExecute.runQuery().
minofAggregate keyword used to return the lowest field value fetched.
Syntax: select minOf(amountMST) from custTrans;
AX Example: See class method KMKnowledgeCollectorStatisticsExecute.runQuery().
delete_fromWill delete multiple records in one call to the database.
Syntax: delete_from myTable where myTable.amountMST <=’1000′;
AX Example: See class method InventCostCleanUp.updateDelSettlement().
exists joinExists join is used to fetch records where at least one record in the secondary table matches the join expression.
No records will be fetched from the secondary table using exists join.
Syntax: while select custTable exists join custTrans
where custTable.accountNum == custTrans.accountNum
AX Example: See class method InventAdj_Cancel.cancelInventSettlements().
notexists joinOpposite of exists join. Will fetch records from the primary table, where no records in the secondary table match the join expression.
Syntax: while select custTable notexists join custTrans
where custTable.accountNum == custTrans.accountNum
AX Example: See class methodInventConsistencyCheck_Trans.run().
outer joinOuter join will select records from both tables regardless if there are any records in the secondary table matching the join expression.
Syntax: while select custTable outer join custTrans
AX Example: See class method SysHelpStatistics.doTeams().
joinJoin will fetch Records matching the join expressionfrom both tables. (innerjoin)
Syntax: while select custTable join custTrans
where custTable.accountNum == custTrans.accountNum
AX Example: See table method SalesTable.LastConfirm().
firstfastInstruct to select the first record faster. used in situations where only one record is shown, like in a dialog.
Syntax: select firstfast custTable order by accountNum;
AX Example: See class method ProjPeriodCreatePeriod.dialog().
firstonlyFirst record will be selected. Firstonly should always be used when not using while in selects.
Syntax: select firstonly custTable where custTable.AccountNum == _custAccount (variable)
AX Example: See Table method CustTable.find().
forupdateUsed If records in a select are to be updated
Syntax: while select forupdate reqTransBOM where reqTransBOM.ReqPlanId     == this.ReqPlanId
AX Example: See Table method ReqTrans.deleteExplosionCoverage().
fromDefault all fields of a table is selected. From is used to select only the fields specified.
Use it for optimization only, as it makes the code more complex.
Syntax: select accountNum, name from custTable;
group bySort the fetched data group by the fields specified. Only the fields specified in the group by will be fetched.
Syntax: while select custTable group by custGroup;
AX Example: See class method InventStatisticsUS.calcTotals().
indexUsed to set the sorting order of the fetched data. The kernel will convert the keyword index to an order by using the fields from the index.
Index should only be used if the fetched data must be sorted in a specific way, as the database will choose a proper index.
Syntax: while select custTable index accountIdx.
index hintIndex hint will force the database to use the specified index.
Syntax: while select custTable index hint accountIdx.
AX Example: See Table method ReqTrans.deleteExplosionCoverage().
insert_recordsetUsed to insert multiple records in a table. Insert_recordset is useful when copying data from one table to another as it only requires one call to the database
Syntax: insert_recordset myTable (myNum,mySum)
select myNum, sum(myValue) from anotherTable group by myNum where myNum <= 100;
AX Example: See class method SysLicenseCodeReadFile.handleDomainLicenseChanges().
update_recordsetUsed  to update multiple records in one database call. Useful to initialize fields in a fast way.
The fields updated are specified after thekeyword setting.
Syntax: update_recordset myTable setting field1 = myTable.field1 * 1.10;
AX Example: See class method ProdUpdHistoricalCost.postScrap().
Read more →