Sunday, July 12, 2015

Some string functions used in Axapta:

How to find a string in Ax:


int strFind(
    str _text,
    str _characters,
    int _position,
    int _number)

strFind(“abcdef”, “D”, 3, 02) //Returns 4.
  • strFind(“abcdef”, “Bf”, 3, -2) //Returns 2.
  • strFind(“abcdef”, “Z”, 3, 2) //Returns 0.
  • strFind("ABCDEFGHIJ","KHD",1,10); //Returns the value 4 (the position where "D" was found).
  • strFind("ABCDEFGHIJ","KHD",10,-10); //Returns the value 8 (the position where "H" was found).

  • How to search a specific character in String Ax:


    int strScan(   str _text1, str _text2,    int _position,    int _number)


    //find the current item
        workingItem = Tree.getItem(Tree.getSelection());
        objectId = workingItem.text(); //objectId = "OBJ-0000021: Object Test 1- OBJ"
        found = strscan(objectId, ":", found, strlen(objectId));
        If (found!=0)
            objectIdActual = subStr(objectId,1,found-1);
            select RecId from objectTable1
            Index ObjectIdx
                where objectTable1.ObjectID == objectIdActual;
            objectBOM.ValidTimeStateUpdateMode (ValidTimeStateUpdate::Correction);
            select forUpdate validTimeState(dateToday) * from objectBOM
                where objectBOM.RecId == element.args().record().RecId; //mroobject.RecId;
            objectBOM.Object = objectTable1.RecId;

    How to Retrieves part of a string in Ax:

    str subStr(str _text, int _position, int _number)


    subStr("ABCDEFGHIJ",3,5); //Returns the string “CDEFG”.
    subStr("ABCDEFGHIJ",7,-4); //Returns the string “DEFG”.
    subStr("abcdef"),2,99) //Returns the string "cdef".
    subStr("abcdef",2,3) //Returns the string "bcd".
    subStr("abcdef",2,-3); //Returns the string "ab".


    void test()
    str Name;
    str Result;
    info(strfmt("The original Name : %1,the sub string Result : %2",Name,Result));

    Find Starting and ending positions using TextBuffer Class for SubStr():

    int pos;
    TextBuffer textBuffer;

    textBuffer = new TextBuffer();
    textBuffer.setText("ABC DEF GHI JKL MNO ABC ABC");
    pos = 0;

    while (textBuffer.find("ABC",pos))
        print "String found at position: ", textBuffer.matchPos();
        pos = textBuffer.matchPos()+1;

    Regular Expressions in Ax:

    Tuesday, June 23, 2015

    OutLook integration code in Ax2012 - HR Module->Periodic-> Recruitment->Applicant interviews form.

    OutLook integration code in Ax2012 - HR Module->Periodic-> Recruitment->Applicant interviews form-> Schedule in Microsoft Outlook button.

    Classes-> HCMDiscussion2Outlook :

    Tuesday, March 3, 2015

    Microsoft Dynamics AX 2012 Data Import/Export Framework new version released

    What’s New :  Part of foundation layer in CU7.
    Key Features:

    •150  Entities out of the box ( 80+ new entities added)
    ◦Master Data
    ◦Reference Data
    ◦System Configuration data
    ◦Application configuration data – Parameters, Reference data, etc.
    •Support for creating custom entities using Custom entity creation wizard.
    •Import Entity data from multiple sources
    •Flat File – Delimited and Fixed Width
    ◦XML – XML file
    ◦Excel – Excel file
    ◦ODBC – external data bases , Excel files , etc.
    •Export Entity data from AX 2012 to 
    ◦Other AX 2012 environments
    ◦Flat File , XML File and Excel file
    •New Retail specific entities
    •Copy entity data across companies
    •Support for exporting data in multiple formats – delimited, fixed width, XML and excel for bulk data.
    •Enhancements to custom entity creation
    •Compare and Copy Entity data across Legal entities
    •Entity types – Entity, composite entity and flat table.
    •Mapper control
    •Parallel execution support from staging to target using Task Bundling
    •Folder as input for running periodic import  - with  functionality to move files to different folders (In Process, Error and Completed)
    •Error handling  - skipping error rows , etc.
    •Set based support for staging to target
    •Default value Support
    •Number sequence Support
    •External Key mapping Support
    •·         Source to Target in single step
    •·         Multiple AOS support
    •Role based security and privacy extension for Entities and Processing Group
    •Securing Processing group by company.
    .. and lot more.

    Wednesday, February 4, 2015

    Dynamics Ax Internals: Default dimension storage in Ax 2012

    X++ code to retrieve default dimensions (via individual selects)
    Obviously this isn't a particularly efficient approach - it's expanded out like this for the sake of demonstration. In picture-form it may look similar to the following. Note the main tables involved, and the relationships between them:
    That's a lot of tables! Whereas before we would just reference the elements of the Dimension array, we now have to go through multiple joins to get the same information. The reason for this is the way dimensions are defined and structured in Ax2012. Previously we had a fixed number of dimensions, and a fixed source (the dimension code table), but now we can define an attribute that points to pretty much anything (customers, item groups, warehouses, etc).
    I'll be interested in seeing how this affects reporting that works off direct SQL queries or cubes, as we now have to dynamically link tables based on the underlying source table (identified by DimensionAttribute.BackingEntityType). It could make things a bit tricky, and I suspect we'll have to rely more on generating datasets from within Ax, using the new data provider framework for SSRS.
    So an overview of the main tables involved is:


    A unique combination of values used for default dimensions. This acts as a
    container for a list of DimensionAttributeValueSetItem records, which link off
    to the specific attribute and attribute value records.
    This is similar in concept to the InventDim table in Ax2009, which stores unique combination of inventory dimension values. It uses a field called Hash, which stores a hash-code for all of the attached values. This is used by Ax when checking whether it needs to create a new entry, or use an existing one. (NB the dimension controllers rely heavily on server-side caching - If you're doing any investigation into the code it may help to disable this via code. Just make sure it's left as-is for production and testing environments).


    This stores the individual attribute items (I would describe them more as the 'segments'), that make up a value set. This relates to the RecID of the
    DimensionAttributeValueSet via the field of the same name.
    Note that this table doesn't store the actual value. It points to an instance of DimensionAttributeValue (see below), which in-turn links back to the dimension value entitiy (eg Customer table).

    This is a link between an attribute and a value.
    The field EntityInstance points to the RecID of the underlying table/view. NB
    the structure of this is normally that you create a view pointing to the table or tables you want to use for the dimension values. The view can be structured as normal with joins, relations, etc, but will typically only return three fields:
    • Key - RecID of primary table
    • Value - 'Code', such as customer account, item number, etc.
    • Name - The description/name, eg The name on the customer address book entry.
    The convention is that any table used for dimension values is exposed as a view (prefixed with "DimAttribute"). Have a look at the existing DimAttributexxx views in the standard application for plenty of examples.
    The main attribute table. This will have an entry for 'department', 'cost centre', 'purpose', etc, as well as any other dimensions you define. Each DimensionAttribute points to a 'backing entity' type, which is the table/view id of the underlying data-source.
    For 'custom value' dimensions (ie those that don't point to an existing table), this points indirectly to table DimensionFinancialTag.
    Table overview
    * There's a slight caveat here. If the dimension points to a table like CustTable, how does Ax make sure that there is a corresponding entry in DimensionAttributeValue? The answer is that whenever the dimension value is referenced (for example by selecting it on a form), the system checks whether the entry exists, and if not, it's created. This occurs at:
    Data DictionaryTablesDimensionAttributeValueMethodsinsert

    Data DictionaryTablesDimensionAttributeValueMethodsfindByDimensionAttributeAndEntityInst


    And in addition, what if we're referencing the customer dimension, but the underlying customer record is deleted? If you look at CustTable.delete, you'll see a call to DimensionAttributeValue::updateForEntityValueDelete. This goes through any existing references to the corresponding DimensionAttributeValue and clears them. I suspect (at least I'd hope), that if any GL postings have already been made, you won't be able to remove the underlying record.


    The class DimensionDefaultingController is used throughout the application to handle the display of default dimensions on master records (customer, suppliers, etc). If you look at the code in the following stack-trace, you'll see query logic similar to the sample at the beginning of this post.

    The DimensionDefaultingController is created on the form, accepting the datasource and field (which in most cases will be DimensionDefault). On the datasource 'active' event, the controller iterates through the relevant dimension value set, and updates the controls. There's a lot more to cover with respect to how dimensions are displayed/updated from the UI - Look out for a future post.
    Dynamics Ax Internals: Default dimension storage in Ax 2012

    Useful X++ code for ledger dimensions

    Create Ledger Dimension through string values:
    Converts string values to ledgerDimension after validating it against chart of account:
    Creates DefaultDimension from string values:
    Convert LedgerDimension into string value:

    Create Purchase invoice journal and lines through code X++ in Ax2012.

    //Working code and tested in same instance..
    static void createVendorInvoiceJournal(Args args)
        LedgerJournalCheckPost                  jourCheckPost;
        LedgerJournalTable                          jourTable;
        InventTable                                       inventTable;
        DimensionAttributeValueSet            dimAttrValueSet;
        DimensionAttributeValueSetItem     dimAttrValueSetItem;
        DimensionAttributeValue                 dimAttrValue;
        DimensionAttribute                          dimAttr;
        Common                                           dimensionValueEntity;
        AxLedgerJournalTable header = new AxLedgerJournalTable();
        AxLedgerJournalTrans trans = new AxLedgerJournalTrans();
        AxLedgerJournalTrans trans1 = new AxLedgerJournalTrans();
        container            offsetDim;
        str 30      accNo,departmentDim,businessUnitDim,costCenterDim,itemGroupDim;
        str 30      businessUnitDimValue,costCenterDimValue,itemGroupDimValue,departmentDimValue;
        int           indexcount;
        LedgerJournalNameId ledgerJournalNameId = "APInvoice";
        DimensionAttributeValueCombination davc;



        select firstonly RecId from davc where davc.DisplayValue == "CN-001";    

        //dimAttrValueSet = DimensionAttributeValueSet::find(inventTable.DefaultDimension);
        dimAttrValueSet = DimensionAttributeValueSet::find(22565462243);

        while select dimAttrValueSetItem where dimAttrValueSetItem.DimensionAttributeValueSet ==  
            dimAttrValue = DimensionAttributeValue::find 
            dimAttr = DimensionAttribute::find(dimAttrValue.DimensionAttribute);
            dimensionValueEntity = DimensionDefaultingControllerBase::findBackingEntityInstance
            dimAttr, dimAttrValue.EntityInstance);

            if(dimAttr.Name == "Department")
                departmentDim = dimAttr.Name;
                departmentDimValue = dimAttrValue.getValue();
            if(dimAttr.Name == "BusinessUnit")
                businessUnitDim = dimAttr.Name;
                businessUnitDimValue = dimAttrValue.getValue();
            if(dimAttr.Name == "CostCenter")
                costCenterDim = dimAttr.Name;
                costCenterDimValue = dimAttrValue.getValue();
            if(dimAttr.Name == "ItemGroup")
                itemGroupDim = dimAttr.Name;
                itemGroupDimValue = dimAttrValue.getValue();
        accNo = DimensionAttributeValueCombination::getDisplayValue(WNXParameters::find().VendorLedgerDimension);
        indexcount = 2; trans1.parmJournalNum(header.ledgerJournalTable().JournalNum);
        //First is  Display value, followed by Main Account and then dimensions.
        offsetDim =
        //offsetDim = ["110180", "110180", 2, "BusinessUnit", "001", "Department", "022"];
        //Manual input
        //offsetDim = ["112000", "112000", 0]; //Manual input
        trans1.parmTaxItemGroup("UB");; jourTable = header.ledgerJournalTable();
        if (jourTable.RecId > 0)
            jourCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(jourTable, NoYes::Yes, NoYes::Yes);
            // Post only if there is succesful validation.
            if (jourCheckPost.validate())

    Vender Creation in Ax2012.

    static void createVendorRecord(Args _args)
        VendTable       vendTable, vendTableRef;
        DirPartyTable dirPartyTable;

        VendTable.AccountNum = NumberSeq::newGetNum(VendParameters::numRefVendAccount()).num();
        vendTableRef = VendTable::find(WNXParameters::find().VendorAccount);
        vendTable.initValue(); vendTable.VendGroup = vendTableRef.VendGroup;
        vendTable.Currency = vendTableRef.Currency;
       dirPartyTable = DirPartyTable::findRec(22565449577);//Customer Master PartyId
            vendTable.Party = dirPartyTable.RecId;
            info("vendor not created");