Showing posts with label ax. Show all posts
Showing posts with label ax. Show all posts

Saturday, 27 May 2017

Accessing page numbers in SSRS report body

This post demonstrate how to access page numbers in SSRS report body AX 2012/AX 7/ Dynamics 365. 


1. Goto Report à Report Properties à Code in Visual studio

2. Write the below logic in code

Public Function PageNumber() as String
     Dim str as String
     str = Me.Report.Globals!PageNumber.ToString()
     Return str
End Function

Public Function TotalPages() as String
     Dim str as String
     str = Me.Report.Globals!TotalPages.ToString()
     Return str
End Function

3.  Create a text box and the below expression

=Cstr(Code.PageNumber()) & Space(2) & Labels!@SYS26401 & space(2) & Cstr(Code.TotalPages())


4. Example output 1 of 4

Saturday, 22 April 2017

Display or edit methods in Dynamics 365 or AX7

New Display or Edit method need to write in extension class.

In the below code is the example for display method in CustTable extension.

[ExtensionOf(tablestr(CustTable))]
final class CustTableEventHandlers_Extension
{
    [SysClientCacheDataMethodAttribute(true)]
    display RetailLoyaltyCardNumber primaryLoyaltyNumber()
    {
        RetailLoyaltyCard   retailLoyaltyCard;

        select firstonly CardNumber from retailLoyaltyCard
            where retailLoyaltyCard.Party == this.party
                && retailLoyaltyCard.Primary == NoYes::Yes;

        return retailLoyaltyCard.CardNumber;
    }
}

After writing logic we need to assign this method to the control in Form.

Set control properties "data method" in the below format

ExtensionClassName::MethodName



Saturday, 15 April 2017

Lookups in Dynamics 365 or AX7

Lookups are almost same as AX 2012 but need to write in extension class. Need to copy the event handler and paste in Class and write the same logic as AX 2012.

https://ranjithdax.blogspot.in/2015/01/creation-of-sys-look-in-microsoft.html (AX 2012)

Will get different lookup scenarios one of the scenario is
Scenario: How to filter lookup based on one field value in Dynamics 365.

So 1st  need to get the value of the field value to pass as a range, for that need to get the control value from FORM.

The below code is used to get the filtered lookup based on the other field value.



  [FormControlEventHandler(formControlStr(RetailLoyaltyCards, RetailLoyaltyCard_AuthorizedUser), FormControlEventType::Lookup)]
    public static void RetailLoyaltyCard_AuthorizedUser_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(DirPartyPostalAddressView), sender);
        QueryBuildDataSource            queryBuildDataSource;
        Query                           query;
        FormRun                         formRun;
        FormControl                     formCtrl;
       
        formRun = sender.formRun();

        formCtrl = formRun.design().controlName(formControlStr(RetailLoyaltyCards, RetailLoyaltyCard_Party2));

        sysTableLookup.addLookupfield(fieldNum(DirPartyPostalAddressView, LocationName), true);
        query = new Query();
        queryBuildDataSource = query.addDataSource(tableNum(DirPartyPostalAddressView));
        queryBuildDataSource.addRange(fieldNum(DirPartyPostalAddressView, Party)).value(SysQuery::value(str2Int64(formCtrl.valueStr())));
          
        sysTableLookup.parmQuery(query);
        sysTableLookup.performFormLookup();
    }




Saturday, 30 April 2016

Phone number validation in Microsoft dynamics AX 2012

The below code is used to validate the Phone number.

public boolean validateField(FieldId _fieldIdToCheck)
{
    boolean ret;
    Str         phonePattern = @"[0-9]";
 
    System.Text.RegularExpressions.Match  myMatch;

    ret = super(_fieldIdToCheck);

    if (_fieldIdToCheck == fieldNum(PracticeDemo, PhoneMobile))
    {
        myMatch = System.Text.RegularExpressions.Regex::Match(this.PhoneMobile, phonePattern);
         
        if (strLen(this.PhoneMobile)<10 || strLen(this.PhoneMobile)>10)
        {
            ret = checkFailed(strFmt("%1 please enter 10 digit mobile number", this.PhoneMobile));
        }
         
        if (!myMatch.get_Success())
        {
            ret = checkFailed(strFmt("%1 is not an valid phone number", this.PhoneMobile));
}
    }

    return ret;
}

Saturday, 21 November 2015

Department name using default dimension value in AX 2012

We can get the department name in different ways using default dimension value.


1st Way: Using Views.


static void DepartmentName(Args _args)
{
    DefaultDimensionView        defaultDimensionView;
    DimAttributeOMDepartment    dimAttributeOMDepartment;

   //DefaultDimension  =  5637151660
    select DisplayValue from defaultDimensionView
        where defaultDimensionView.DefaultDimension == 5637151660
            && defaultDimensionView.name == 'Department'
        join dimAttributeOMDepartment
            where dimAttributeOMDepartment.Value == defaultDimensionView.DisplayValue;

    info(dimAttributeOMDepartment.Name);
}


2nd Way: Using Tables.


static void getDepartmentName(Args _args)
{
str                                                       name;
DimensionAttributeValueSetItem      valueSetItem; 
DimensionAttribute                           dimAttribute; 
DimensionAttributeValue                 dimAttributeValue;

//Get the Department name for '5637151660' default dimension.
select DimensionAttributeValueSet from valueSetItem 
where valueSetItem.DimensionAttributeValueSet == 5637151660
            join RecId from dimAttributeValue 
                where valueSetItem.DimensionAttributeValue == dimAttributeValue.RecId 
            join RecId from dimAttribute 
                where dimAttributeValue.DimensionAttribute == dimAttribute.RecId 
                   && dimAttribute.Name == enum2str(sysdimension::Department);
       
         name = DimensionAttributeValue::find(dimAttributeValue.RecId).getName();
        
        info(name);
 }




Thursday, 12 March 2015

Adding Customer Address through x++ Coding



The Below code used to update or create address for an existing customer


static void BRR_Address(Args _args)
{
        CustTable                                  custTable;
        DirParty                                     DirParty;
        LogisticsPostalAddress             address;
        DirPartyPostalAddressView      addressView;
        LogisticsLocationRole               roles;


        custtable = Custtable::find("1304");

        address.Street     =   "DLF,";
        address.ZipCode    =   "500006";
        address.City       =   "CyberCity,";
        address.State      =   "TG";
        address.CountryRegionId = "IND";

        addressView.Party = custtable.Party;
        addressview.initFromPostalAddress(address);

        DirParty = DirParty::constructFromPartyRecId(CustTable.Party);
        roles = LogisticsLocationRole::findBytype(LogisticsLocationRoleType::Delivery);
        DirParty.createOrUpdatePostalAddress(addressView);
}

Wednesday, 11 March 2015

Inserting Customer's Financial Dimensions through X++ code


The Below code is used for Inserting Financial Dimensions for a particular Customer through code.

static void BRR_Finance(Args _args)
{
  CustTable custTable;
  Struct struct = new Struct();
  container ledgerDimension;
  DimensionDefault DimensionDefault;
  ;
  //set the values
  struct.add("CostCenter", "OU_4740");
  struct.add("BusinessUnit","00000005");
  struct.add("Department","OU_4771");  
  struct.add("ExpensePurpose","Training");
  ledgerDimension += struct.fields();
  ledgerDimension += struct.fieldName(1);
  ledgerDimension += struct.valueIndex(1);
  ledgerDimension += struct.fieldName(2);
  ledgerDimension += struct.valueIndex(2);
  ledgerDimension += struct.fieldName(3);
  ledgerDimension += struct.valueIndex(3);
  ledgerDimension += struct.fieldName(4);
  ledgerDimension += struct.valueIndex(4);
   ttsBegin;
  DimensionDefault = AxdDimensionUtil::getDimensionAttributeValueSetId(ledgerDimension);
    //Select the Customer
  custTable = CustTable::find("2003",true);
  custTable.DefaultDimension = DimensionDefault;
  custTable.update();
  ttsCommit;
}

Saturday, 7 March 2015

Finding Ledger Dimension by using MainAccount Number in X++



static void getLedgerDimension(Args _args)
{
DimensionAttributeValueCombination     dimensionAttributeValueCombination;
MainAccount                                             mainAccount;
;
select RecId,MainAccount from dimensionAttributeValueCombination
                join RecId from mainAccount
                  where dimensionAttributeValueCombination.DisplayValue == "1010"
                     && mainAccount.RecId == dimensionAttributeValueCombination.MainAccount;

info(strFmt("Ledger Dimension - %1",dimensionAttributeValueCombination.RecId));
}


                                                or 

we can find by using the method "getDefaultAccountForMainAccountNum()" which is available in DimensionStorage


static void getLedgerDimension(Args _args)
{
   DimensionStorage::getDefaultAccountForMainAccountNum("1010");
}

Tuesday, 24 February 2015

How to open web site pages on AX Forms

Today I will demonstrate you that how you can show any webpage on your AX Forms.

1. Create New Form.
2. Right click the Design node of form and add ActiveX control.
3. Select Microsoft Web Browser from AciveX control window list.
4. Go to method node of form and override Init method of form.
5. Add below line of code
           
    ActiveX.Navigate("www.google.com");

Note: - ActiveX is the name of control which we have added in the form previously.


6. Now run your form and check the output

Saturday, 21 February 2015

Finding the mandatory fields on table by using X++ code.


The below code is used to get the mandatory fields on table using X++.


static void CheckMandatoryFieldsOnTable(Args _args)
{
    DictTable   dictTable;
    DictField    dictField;
    int               i;
   //Pass the table name
    TableId       tableId = tablenum(SalesTable);
    ;

    dictTable = new DictTable(tableId);
    for (i=1 ; i<=dictTable.fieldCnt() ; i++)
    {
        dictField = new DictField(tableId, dictTable.fieldCnt2Id(i));

        if (dictField.mandatory())
        {
            info(dictField.name());
        }

    }
}


output :


Friday, 9 January 2015

Query based SSRS Reports.

Overview

There are a multiple of methods to develop SSRS reports in Dynamics AX. This tutorial will guide you through the process of developing SSRS reports using an AOT query.

Pre-requisites

  1. Microsoft Dynamics AX 2012
  2. Visual studio 2012
  3. SQL Server report server must be configured
  4. Reporting services extensions must be installed in Dynamics AX

Steps

  1. First of all we need an AOT query which will fetch data from AX and display it in a report. For this tutorial, I am using an existing query in AX which displays a list of customers.
  2. CustTableListPage query will be used in this tutorial. To find this query, open AOT àQueriesàCustTableListPage.
  3. The development of the SSRS report is done in Visual studio. So a new project needs to be created in Visual studio.
  4. Open Visual studio. Go to File à New à Project.
  5. In the section Installed templates select Microsoft Dynamics AX and then select Report Model in the right pane. Name the project “QueryBasedDemo“. Press OK.


  6. A new project will be created as shown below:


  7. Now add a new report in the project by right clicking on the project QueryBaseDemo à Add à Report.



    1. A report will be added to the project with the name “Report1″. Rename the report toQueryBasedDemo.
    2. Now double click the report to open it.

  8. The description of the individual node is given below:
    1. Datasets: Datasets retrieve data from the AOT query. It acts as a bridge between AX and the SSRS report. Only the fields added in the datasets can be used in a report.
    2. Designs: It defines the layout of the report.
    3. Images: It contains the images that you want to display in the SSRS report.
    4. Data Methods: It contains the business logic which can then be used in the report.
    5. Parameters: It is used to apply filtering to the data in a report.
  9. First of all, we will create a dataset. Right click Datasets àAdd Dataset to create a new Dataset. Name it “CustTable”.



  10. Select the data source and open the properties window. Make sure the Data Source Type is set toQuery. Then select the Query field. An ellipse button appears. Click it to open a dialog.


  11. This dialog lists all the queries present in the AOT. Select CustTableListPage and press Next.

  12. Select the fields you want to display in the report and press OK. Only the selected fields in this dialog can be shown in the report.

  13. There are two types of designs that can be created in a SSRS report:
    1. Auto Design: Visual studio automatically creates a design based on the dataset provided. Auto design is the preferred method because it is easy and usually fulfills the requirements for the majority of scenarios.
    2. Precision Design: It is used when you need custom placement of fields or the layout of the report is too complex.
  14. In this demo we will use Auto Design. Now right click the Designs nodeàAdd àAuto Design. A new design is added. Rename it to Design. It is recommended that you set the name of the Design to either ‘Design’ or ‘Report’

  15. Now drag CustTable form the Datasets node and drop it on the Design node. A table will be created which contain all the fields present in the data set. These fields will appear in the same order in the report. So if you want to arrange the fields, right click the field and select either move up or move down.
  16. The final design will look as shown below



  17. Now we have to define the layout of the report. Visual studio provides built in templates. Select the Design and open the properties window. Select ReportLayoutStyleTemplate in the LayoutTemplatefield. Give a suitable title to the report.

  18. Select the CustTableTable under the Design node and open the properties window. SelectTableStyleAlternatingRowsTemplate in the Style Template field.


  19. Report is now completed can be viewed. To preview the report, select the Design node, right click it and select preview. A preview window opens.


  20. Select Report tab. The report appears as shown below:



  21. To view this report from AX, it needs to be added in the AOT and deployed at the report server.
  22. Open the solution explorer and right click the project. Select Add QueryBasedDemo to AOT. This will add the report to the AOT. It will also add the project in the AOT with same name so if you want to modify the report in future, you can use that project.


  23. Now open AOT in AX. Go to SSRS reports à Reports à QueryBasedDemo. Right click the QueryBasedDemo Report and select Deploy Element

  24. A success message will appear if the report is successfully deployed.
  25. To open the report in AX, a menu item is required. Create a menu item that will open the report from AX.
  26. Go to Menu items à Output. Right click Output and select New Menu Item

  27. Set the following properties on the menu item as shown below.

  28. Right click the newly created menu item and select Open to view the report

  29. A parameter form will open. If you want to add parameters to report, you can add it by clicking Select. Press Ok to continue.

  30. The report is displayed as shown below.

Saturday, 3 January 2015

Creation of Sys Lookup in Microsoft Dynamics AX


Steps to create a Sys Lookup :-

1. Create a Table with fields ( AccountName,Account,City).

2. Create a Form and use  DataSource as created Table.

3. Expand the Form DataSource and Expand Fields.

4. Override the Lookup() method  on the field where the lookup has to appear (Example Field -  Account).

5. Write the following code.

public void lookup(FormControl _formControl, str _filterStr)
{

    SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(CustTable),_formControl);
    Query query = new  Query();
    QueryBuildDataSource qbds = query.addDataSource(tableNum(CustTable));
     super(_formControl, _filterStr);
     sysTableLookup.addLookupfield(fieldNum(CustTable,AccountNum));
    sysTableLookup.addLookupfield(fieldNum(CustTable,Currency));
    sysTableLookup.parmQuery(query);
    sysTableLookup.performFormLookup();

}

T

Wednesday, 3 December 2014

Table inheritance in Ax 2012


Step-1 Create a table called 'BaseTable'
Step-2 Set table property 'supportInheritance' to 'Yes'
Step-3 Create a filed name called 'InstanceRelationType' extends 'RelationType'
Step-4 Set table property 'InstanceRelationType' to 'InstanceRelationType'
Step-5 Create two filed called Id and Name as shown below screen
Step-6 Create another table called 'ChildTable'
Step-7 Set table property 'supportInheritance' to 'Yes'
Step-8 Set table property 'Extends' to 'BaseTable'
Step-9 Write a job to access the base table fields given below

static void dataInsert_BaseTable(Args _args)
{
BaseTable bt;
ChildTable ct;

ct.Id = '1000';
ct.Name = 'Test';
ct.insert();
}

Tuesday, 2 December 2014

Collection Classes in Ax 2012

Array 
     Array's can hold values of any single data type and allows duplicate values and insertion of data is based on the location Specific. 


Static void Array_example(Args _args)

{
Int I;
Array arr=new Array(Types::String);
arr.value(1,”ABC”);
arr.value(2,”ABCD”);
arr.value(3,”ABCDE”);
for(i=1;i<=arr.lastindex();i++)
{
Info(strfmt(“Value is: %1”,arr.value(i)));
}
}



List   
 List Contains elements that are accessed sequentially. Unlike the Array class, the List class provides an addStart() method. As with the Set class, the List class provides methods getEnumerator() and getIterator(). You can use an iterator to insert and delete items from a List object. It allows duplicate values.


Static void List_example(Args _args)
{
List l=new List (Types::Integer);
ListEnumerator lenum;
l.addEnd (20);
l.addEnd (24);
l.addStart (30);
l.addStart (25);
lenum= l.getEnumerator();
lenum.reset();
  While (lenum.movenext())
    {
             Info (strfmt(“Value is: %1”,lenum.current()));
     }


Map

 Map Associates a key value with another value. It doesn't allow duplicate Key values in Maps.

Static void Map_example(Args _args)
{
Map m=new Map (Types::String,Types::Integer);
MapEnumerator menum;
m.insert(“Vlaue1”, 20);
m.insert(“Vlaue2”, 30);
m.insert(“Vlaue3”, 60);
menum= m.getEnumerator();
While (menum.movenext())
{
Info (strfmt(“Value is: %1 || Key is: %2 ”,menum.currentValue(),menum.currentKey()));
}
}

Set
Holds values of any single type. Values are not stored in the sequence they are added. Instead, the Set object stores them in a manner that optimizes performance for the in() method. When you add a value to a Set object which is already storing that same value, the add attempt is ignored by the Set object.Unlike the Array class, the Set class provides the methods in() and remove().
Static void Set_example(Args _args)
{
Set s=new Map (Types::Integer);
SetEnumerator senum;
s.add( 20);
s.add( 25);
s.add( 60);
senum= s.getEnumerator();
While (senum.movenext())
  {
     Info (strfmt(“Value is: %1 “,senum.current()));
  }
}

Struct
Can contain values of more than one type. Used to group information about a specific entity.

Static void Struct_example(Args _args)
{
Int i;
Struct s=new Struct ();
s.add(“Name”,”ABC”);
s.add( “Age”, 34);
s.add( “Salary”,23000.00);
for(i=1;i<=s.fields();i++)
  {
    Info (strfmt(“Field Type: %1 || Field Name: %2 || Value      is:%3“,s.fieldType(i),s.fieldName(i),s.value(s.fieldName(i))));
  }
}

Friday, 28 November 2014

Args Class in Microsoft Dynamics Ax

                                        Args class

The Args system class is one of the most widely used classes in Axapta. Args is an abbreviation for arguments and an Args object is used to pass information from one object (caller) to another newly created object.


Using Args for object creation

//This Example explain about opening a Form through Args.

 Args    args = new Args("CustTable");
 FormRun formRun = ClassFactory.formRunClass(args);
 ; 
 formRun.init();
 formRun.run();
 formRun.wait();    or  formRun.detach();

Caller:

public Object caller( [Object _value] )

this method gets or sets the calling object. When creating an args object directly through code, the caller will not be automatically set, so you should set it yourself.

Record:

public Common record( [Common _value] )

this method gets or sets a table buffer (record) attached to the Args. A buffer of any table can be attached to an Args object using this method. Be aware when retrieving the buffer that there will be no compile-time check of table id. You should use the dataset method below to check the contents of the buffer.

If the caller and callee are on different tiers, then the applications will automatically copy the buffer to the target tier.

Dataset:

public tableId dataset()

this method gets the table Id of a table buffer (record) attached to the Args.
To safely retrieve an attached record from an Args object, use code similar to that shown below. This checks to ensure that there is an attached record, and that it is in fact a SalesTable record, before trying to assign it to the salesTable variable.

if (args.record() && args.dataset() == tableNum(SalesTable))
  salesTable = args.record();

parm:

public str parm( [str _value] )
parm is used to pass a string variable to the called object

parmEnum:

public anytype parmEnum( [int _value] )

parmEnumType:

public int parmEnumType( [int _value] )

parmEnum and parmEnumType are used together to pass a Base Enum value through to the called object. An example is shown below.

args.parmEnumType(EnumNum(AddressType));
args.parmEnum(AddressType::Delivery);

parmObject:

public Object parmObject( [Object _value] )
parmObject is used to pass a reference to any object to the called object. Be aware of client-server issues if the caller and callee are on different tiers.

menuItemName:

public final str menuItemName( [str _value] )

menuItemType:

public final MenuItemType menuItemType( [MenuItemType _value] )

A short tutorial on how to open a form in Dynamics Ax (Axapta) by code.

Just take a line of code:

new MenuFunction(MenuItemDisplayStr(CustTable),MenuItemType::Display).run();
The above code will open the CustTable form. That's all it takes.

Now if you want to supply some arguments to the opening form, this is also possible with the optional args parameter.

static void FormOpen()
{
Args args = new Args();
;
args.record(CustTable::find('1002'));
new MenuFunction(MenuItemDisplayStr(CustTable),MenuItemType::Display).run(Args);
}

This code will open the CustTable form and filter out the customer with accountnumber 1002.


Thursday, 20 November 2014

Link Type and Join Types in ax 2012

Link Type and Join Types in ax 2012


Link Type:-

1.      Active: - Parent and child- data source is updated immediately when a new record in the parent data source is selected. Continuous updates consume lots of resources consuming.

2. Delayed: - Parent and child - A pause is inserted before linked child data sources are updated. This     enables faster navigation in the parent data source because the records from child data sources are not updated immediately. For example, you can scroll a list of orders where you do not want to review the lines associated with the order until you stop scrolling.

3. Passive: - Parent and child - Linked child data sources are not updated automatically. Updates of the child data source must be programmed on the active method of the master data source.

Join Types:-

1. InnerJoin: - Combined data source – select the record from the main table that matches records in the joined table and vice versa.
There is one record for each match. Records without related records in the other data source are eliminated from the result.

2. Outer Join: - Combined data source – select the records from the main table. The records are retrieved whether they have matching records in the joined table

3. Exist Join: - Combined data source -The data source retrieves a record from the main table for each matching record in the joined table.
The differences between InnerJoin and ExistJoin are as follows:
·         When the join type is ExistJoin, the search ends after the first match has been found.
·         When the join type is InnerJoin, all matching records are searched for.

4. NotExistJoin: - Combined data source -Select records from the main table that do not have a match in the joined table.