Unhide the personalised field(s) – D365 operations

Personalisations helps us to hide/unhide/add the fields which we need or do not need. In my previous blog  , we saw on exporting limited fields with the help of personalisation.
In this blog, let us see to unhide the fields which we were hidden.
For instance, let us assume, the field “Orderer” has been hidden from the form “Vendor Invoice Entry”. This field will not be visible even after the form refresh or reload the form. Given below the steps on doing this.
  1. Click on Personalise option again
hide 1
On clicking this option, you will see this personalize table. Click the highlighted one. (this is the option to Unhide) .
As soon as you click this highlighted option, you will see all the hidden fields:
Then click on the field which you wanted to see. (In  this case, click Orderer ). Then click Close in the personalize table. Now you will be able to see the field.



Posted in D365 Operations, Dynamics 365 Operations - Ax 7.0, Uncategorized | Tagged , | Leave a comment

Limited fields export using Export to Excel – D365 Operations

As we all know , “Export to Excel” in a form exports the data of all the fields given in the form`s grid.

There may be situations where the user expects to export only few fields from the form .

There are 2 ways to do this :

  1. Make the Visible property of the field in the form as No. But if the user expects the field to be available, then this is not a feasible solution.
  2. Another ideal way with  less technical intervention is form Personalisation. User can export and import the personalisation . Given below the steps to do it.
    •  Personalise the form by hiding the unnecessary fields. (When the session is refreshed, user will be able to see all the fields in the form)
    • Export the personalisation. It is exported as XML file which has the changes for hidden fields.
    • Whenever user needs to use “Export to Excel” , below steps are to be followed
    • Same approach can be used for Exporting the personalisation as well.
    • 1
    • 2
    • 3


Posted in Uncategorized | 1 Comment

Extract security objects details for a role

There are situations where we feel it would be handy to get a report having the details of  all the security objects which are used by a role.

There is another option of getting these details by navigating to AOT>Roles> Choose a role name -> right click> Addins-> Security tools. In this case, we see a lengthy report (listed for each field).

I have a simple job which creates a csv file and gives details about RoleName, AOTRoleName,Label,Description,Menu Item , Menu item Type, Menu item label,Duty, Privilege,Access level.

public void AE_SecurityReport()

 SecurityRoleAOTName roleAOTName ;
 SecurityRoleName roleName;
 SecurityRole securityRole;

 TreeNode treeNode;
 TreeNode treeNodeDuty = infolog.findNode(@'\Security\Duties\');
 TreeNode treeNodePriv = infolog.findNode(@'\Security\Privileges\');
 TreeNode treeNodePrivNew;
 TreeNode treeNodeDutyNew;
 TreeNode treeNodeObj;
 TreeNodeTraverser treenodeT;
 TreeNode treeNodeRole;
 TreeNode treeMenu;

 Set setDuty ;
 Set setPrivilege;
 Set setMenuItem;

 SetEnumerator setEnumerator ;

 SysModelElement modelElement;
 SysModelElementType modelElementType;

 UtilElementName name;
 TreeNodePath path;

 str maintainlicenseType;
 str viewlicenseType;
 str menuLabelName;
 str roleAccess;
 str configurationKey;

 String50 menuName;
 String255 securityPrivilege, securityDuty, securityMenuPath;
 String50 engLabel, frLabel, engDescription, frDescription;

 Label objLabel = new Label();
 CommaTextIo commaTextIo;
 FileIOPermission permission;
 FileName fileName;

 container getPrivilegeDetails(
        SecurityRoleAOTName _roleName, MenuItemName _menuItemName)
        SecurityTaskEntryPoint secTaskEntryPoint;
        SecurityRole secRole;
        SecurityRoleTaskGrant secRoleTaskGrant;
        SecurityEntryPointLink secEntryPointLink;
        SecurableObject secObject;
        SecurityTask secTask,secTaskDuty;
        SecuritySubTask secSubTask;
        String255 secPrivilege, secDuty;
        container conPrivDuty, conSecDuty ,conAccess ;
        container conSecPrivilege;

        Select secRole where secRole.AotName == _roleName;
        select secObject where secObject.Name == _menuItemName &&
          (secObject.Type == SecurableType::MenuItemDisplay ||
           secObject.Type == SecurableType::MenuItemAction ||
           secObject.Type == SecurableType::MenuItemOutput);
        select secEntryPointLink where secEntryPointLink.EntryPoint == secObject.RecId;

      while select SecurityTask from secRoleTaskGrant
            where secRoleTaskGrant.SecurityRole == secRole.RecId
      join SecuritySubTask from secSubTask
           where secSubTask.SecurityTask == secRoleTaskGrant.RecId
      join AotName from secTask
           where secTask.RecId == secSubTask.SecuritySubTask
              && secTask.Type == SecurityTaskType::Privilege
      join AotName from secTaskDuty
          where secTaskDuty.RecId == secSubTask.SecurityTask
             && secTaskDuty.Type == SecurityTaskType::Duty
      join PermissionGroup from secTaskEntryPoint
         where secTaskEntryPoint.EntryPoint == secEntryPointLink.RecId &&
               secTaskEntryPoint.SecurityTask == secSubTask.SecuritySubTask
           conSecPrivilege += secTask.AotName;
           conSecDuty += secTaskDuty.AotName;
           conAccess += enum2str(secTaskEntryPoint.PermissionGroup);
    conPrivDuty = [conSecPrivilege, conSecDuty,conAccess];
    return conPrivDuty;
 permission = new FileIOPermission(fileName,#io_write);
 commaTextIo = new CommaTextIo(fileName,#io_write);
 commaTextIo.write('RoleName,AOTRoleName,Label,Description,MenuItemType,MenutItemName,MenuItem Label,Duty,Privilege,Access Level');

 select Name,AotName from securityRole where securityRole.AotName == "Production Manager";
 roleAOTName = securityRole.AotName;
 treeNode = TreeNode::findNode(@'\Security\Roles\'+ roleAOTName).AOTfirstChild();
 treeNodeRole = treeNode::findNode(@'\Security\Roles\'+ roleAOTName);

// Loop through the roles to get Duties
 treenodeT = null;
 setDuty = new Set(Types::String);
 treenodeT = new TreeNodeTraverser(treeNode, false);
 setEnumerator = null;
 setPrivilege = new Set(Types::String);
 // Loop thru the duties to get privileges
 setEnumerator = setDuty.getEnumerator();
 while (setEnumerator.moveNext())
      treeNodeDutyNew = treeNodeDuty.AOTfindChild(setEnumerator.current()).AOTfirstChild();
      treenodeT = new TreeNodeTraverser(treeNodeDutyNew, false);

// Loop thru the privileges to get Entry points
 setEnumerator = null;
 setMenuItem = new Set(Types::String);
 setEnumerator = setPrivilege.getEnumerator();

while (setEnumerator.moveNext())
      treeNodePrivNew = treeNodePriv.AOTfindChild(setEnumerator.current()).AOTfirstChild();
      treenodeT = new TreeNodeTraverser(treeNodePrivNew, false);

// loop thru the menu items to get the properties
 setEnumerator = null;
 setEnumerator = setMenuItem.getEnumerator();
 while (setEnumerator.moveNext())
     name = setEnumerator.current();
     select firstOnly1 modelelement 
         where modelelement.Name == name
      && (modelelement.ElementType == enum2int(UtilElementType::OutputTool) ||
          modelelement.ElementType == enum2int(UtilElementType::ActionTool) ||
          modelelement.ElementType == enum2int(UtilElementType::DisplayTool));

     switch (modelelement.ElementType)
         case enum2int(UtilElementType::OutputTool) :
         path = #MenuItemsOutputPath;

         case enum2int(UtilElementType::ActionTool) :
         path = #MenuItemsActionPath;

         case enum2int(UtilElementType::DisplayTool) :
         path = #MenuItemsDisplayPath;

         default :
         path = '';
 if (path)
       select modelElementType where modelelementtype.TreeNodeName == path;
       treeNodeObj = infolog.findNode(path).AOTfindChild(name);
       menuLabelName = treeNodeObj.AOTgetProperty('Label');
       menuName = treeNodeObj.AOTgetProperty('Name');
       engLabel = SysLabel::labelId2String(treeNodeRole.AOTgetProperty('Label'), 'en-us');
       frLabel = SysLabel::labelId2String(treeNodeRole.AOTgetProperty('Label'), 'fr');
       engDescription = SysLabel::labelId2String(treeNodeRole.AOTgetProperty('Description'), 'en-us');
       frDescription = SysLabel::labelId2String(treeNodeRole.AOTgetProperty('Description'), 'Fr');

       treeMenu = infolog.findNode(#MenusPath);
       treenodeT = new TreeNodeTraverser(treeMenu, false);

       securityMenuPath = ' ';
            securityMenuPath = treenodeT.currentNode().treeNodePath();
      securityPrivilege = conPeek(getPrivilegeDetails(roleAOTName, menuName),1);
      securityDuty = conPeek(getPrivilegeDetails(roleAOTName, menuName),2);
      roleAccess = conPeek(getPrivilegeDetails(roleAOTName, menuName),3);
      maintainlicenseType = treeNodeObj.AOTgetProperty('MaintainUserLicense');
      viewlicenseType = treeNodeObj.AOTgetProperty('ViewUserLicense');
      configurationkey = treeNodeObj.AOTgetProperty('ConfigurationKey');

      commaTextIo.write(roleName,roleAOTName,engLabel, engDescription, modelElementType.Name, treeNodeObj.AOTname(), objLabel.extractString(menuLabelName), securityDuty, securityPrivilege, roleAccess);
Posted in Ax 2012, Ax Security, Ax2012, Dynamics Ax, Uncategorized | Tagged , | Leave a comment

Publish button not enabled in “Open in Excel” – D365 operations

I had a strange issue when trying to Publish the changes from “Open in Excel”.

Publish button was not enabled.  It was greyed out .

Just to brief about the set up:

I created a data entity with ReqItemTable as Primary data source and added the remaining datasources (InventDim/ReqItemGroup) to the data entity.

I mapped the needed fieds in AUTO REPORT.
Now I get the option “Open in Excel” in my form and I could export the fields succesfully.
But the button “Publish” is disabled .


What was the solution: Simple – One of field which was present in Entity key was missing in the AutoReport fields. On adding that, Publish button is enabled and I am able to proceed with updating the changes.



Posted in D365 Operations, Excel D365, Uncategorized | Tagged , , | Leave a comment

Roles of current user – D365 operations

There are situations where we need to enable/disable a control based on the users role.

I have written a code which is split into 2 sections :

First part of the code checks – the roles assigned to the user and returns the roles in a list

Second part of the code takes 2 parameters – First parameter is list from the above result, Second one is also a list which checks has the roles to be verified. This is needed to enable or disable a control.

This logic is applicable for Ax2012 as well.



Posted in Ax 2012, D365 Operations, Dynamics 365 Operations - Ax 7.0, Uncategorized | Tagged | Leave a comment

D365 Operations – Change the label of a dialog field

Without overlayering, is it possible to change the label of a dialog field ? Yes!!! You can do this in Post event handler of dialog method.

But I had to chose the option of referring the field name in my code. Given below the code snippet:

/// <summary>
/// Change the dialog label
/// </summary>
/// <param name=”args”></param>
[PostHandlerFor(classStr(ReqItemJournalUpdate),                                              methodStr(ReqItemJournalUpdate, dialog))]
public static void ReqItemJournalUpdate_Post_dialog(XppPrePostArgs args)
    Dialog dlg ; 
    Map                        mapDlgFields ;
    MapEnumerator mapEnums;
    dlg                      = Args.getReturnValue();
    mapDlgFields = dlg.name2dialogClass();
    mapEnums      = mapDlgFields.getEnumerator();
    while (mapEnums.moveNext())
             if(mapEnums.currentKey() == “Fld4_1”)
                  dlg.form().design().control(“Fld4_1”).label(“This is new label for this field”);

Intellisense doesnot work for retrieving the property name “Label”. So we need to feed it and you will not the build doesn’t give any errors.


Posted in D365 Operations, Uncategorized | Tagged | Leave a comment

D365 Operations – Change Dialog caption

Without overlayering, is it possible to change the Caption of a Runbase dialog class in D365 Operations. YES!!!! You can!!!!

Create a post event Handler of Description method and use

/// <summary>
/// Change the value for caption
/// </summary>
/// <param name=”args”></param>
                                  staticMethodStr(ReqItemJournalUpdate, description))]
public static void ReqItemJournalUpdate_Post_description(XppPrePostArgs args)
     Args.setReturnValue(“This is a new caption”);
Build the solution and execute now. You will see the new caption.
Posted in D365 Operations, Dynamics 365 Operations - Ax 7.0, Uncategorized | Tagged | Leave a comment