Container Functions D365FO-AX 2012

Container Functions D365FO-AX 2012


Today, I am Sharing the functions of container, I have explored during in my career.


Container View

conView


Parameters

cconView(container,Caption,false);


reference screenshot



Insert in container



conIns


Parameters

conIns(container,position,anytype of value);

Example

   container   objContainer;
    int     position=1;
    // insert in container
   objContainer =conIns(objContainer,position,"Sohail Sheikh");

reference screenshot




Length of container 


conLen


Parameters

conLen(containerobject); // will return int

 Example

 container   objContainer=["Sohail Sheikh"];
    int     position=1,len=0;
    

 // container length   
   len=conLen(objContainer);
    info(strFmt("%1",len));

reference screenshot

Pull Data from container


conpeek


Parameters


conpeek(container,position)// will return anytype

Example
  container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        
    // pull data from container   
    objValue=conPeek(objContainer,position);
        info(strFmt("%1",objValue));
 
reference screenshot




Replace Data of container

conpoke

Parameters

conPoke(container,position,anyvalue)// will return container

Example
   container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        
    
     objContainer=conPoke(objContainer,position,"Sheikh Sohail Hussain");
    objValue=conPeek(objContainer,position);    
    info(strFmt("%1",objValue));

reference screenshot



Container Insert Operator 



Parameters


Example
    container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        // insert using operator 
    objContainer+="Inserted";
       
    

    info(strFmt("%1,%2",conPeek(objContainer,1),conPeek(objContainer,2)));

reference screenshot




Find value in Container  

conFind


Parameters

conFind(container,anytype)// will return true or false


Example
 container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        // insert using operator 
    objContainer+="Inserted";
    
      if(conFind(objContainer,"Inserted"))
    {
        info("Value found");
    }

   
reference screenshot





Delete value in Container  

conDel


Parameters

conDel(container,startPosition,EndPosition)// will return container

Example
container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        // insert using operator 
    objContainer+="Inserted";
    
    info(strFmt("Container length Before delete %1",conLen(objContainer)));
    objContainer=conDel(objContainer,2,2);
  
   
   info(strFmt("Container length After delete %1",conLen(objContainer)));

    
reference screenshot





Container  to Str

con2Str


Parameters

conStr(container)// string

Example

  container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        // insert using operator 
    objContainer+="Inserted";
    
    info(con2Str(objContainer));

reference screenshot




Container  Null

conNull


Parameters
conNull()// set the container null

Example
 container   objContainer=["Sohail Sheikh"];
    int     position=1;
    str objValue;

        // insert using operator 
    objContainer+="Inserted";
    
    info(strFmt("Container length Before set null %1",conLen(objContainer)));

 objContainer=conNull(); 
   

   info(strFmt("Container length After set null %1",conLen(objContainer)));


reference screenshot



Str to container

str2con


Parameters

str2Con(stringValues,separator);// will return container

 str objValue;
    container   objContainer;
    objContainer=str2con("Sheikh,Sohail",",");
    
    info(strFmt("%1",con2Str(objContainer)));



reference screenshot



Batch Job Schedule X++ D365FO


Batch Job Schedule D365FO


With the following X++ sample code you can schedule a Batch job.



Sample Code




static void batchJobSchedule(Args _args)
    {
        BatchHeader objBatchheader;
        SysRecurrenceData sysRecurrenceData;
        Batch batch;
        BatchJob batchJob;
        RetailCDXScheduleRunner objRetailSchedule;
        BatchInfo objBatchInfo;
        BatchRetries noOfRetriesOnFailure = 0;
        ;

        // Setup the RunBaseBatch Job
        objBatchheader = Batchheader::construct();
        objRetailSchedule = new RetailCDXScheduleRunner();
        objBatchInfo = objRetailSchedule.batchInfo();
        objBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);
        objBatchInfo.parmCaption("Description should be here"); // Description Batch Job
        objBatchInfo.parmGroupId('YourBatchGroup'); // Batch Gorup
        objBatchInfo.parmBatchExecute(NoYes::Yes);
        objBatchheader.addTask(objRetailSchedule);

        // Set the recurrence data
        sysRecurrenceData = SysRecurrence::defaultRecurrence();
        SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), 20)); // Set range of recurrence
        SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);
        SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute); // Set reccurence pattern
        objBatchheader.parmRecurrenceData(sysRecurrenceData);
        // Set the batch alert configurations
        objBatchheader.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::Yes);
        objBatchheader.save();

        // Update the frequency to run the job to every two minutes
        ttsbegin;
        select forupdate batchJob
            join batch
            where batchJob.RecId == batch.BatchJobId
            && batch.ClassNumber == classnum(RetailConnScheduleRunner);

        sysRecurrenceData = batchJob.RecurrenceData;
        sysRecurrenceData = conpoke(sysRecurrenceData, 8, [10]);
        batchJob.RecurrenceData = sysRecurrenceData;
        batchJob.update();
        ttscommit;
    }


Enable AOS Authorization field using security privilege

Enable AOS Authorization field using security privilege 


Yesterday one of my team member were facing Access Denied error on some fields of table HcmPersonDetails while selecting the record. even she provide the complete rights on this table.




After spending few hours on this issue we found difference in fields properties.
AOS Authorization set as Yes.





Resolution

For the resolution, I have suggested her to add all the required fields in the privilege as well and perform build and sync the database. 





Please feel free to contact me if you are facing any issue while implementing of this blog.

Email SSRS Report As Attachment D365FO


SSRS Report Email Attachment Dynamics 365FO



In one of my projects, We have a requirement to send the SSRS report as an attachment to an Email.

As everyone knows that this task is too simple in AX 2012, Where we save the file in client or server file systems and then send it as an Email attachment.

But the things are a bit more complicated when it comes to D365 in the cloud. You are no longer able to save the file locally as storage.

Following is the code to convert the SSRS report in Binaries 




public class ConvertReportPDF
{

    public static void main(Args _args)
    {
       
  
        Filename                        fileName = "P000173_AbcTest.pdf";
        SrsReportRunController    controller = new SrsReportRunController();
        SLD_TaxProfileContract   contract = new SLD_TaxProfileContract();
        SRSPrintDestinationSettings     settings;
        Array                           arrayFiles;
        System.Byte[]                   reportBytes = new System.Byte[0]();
        SRSProxy                        srsProxy;
        SRSReportRunService             srsReportRunService = new SrsReportRunService();
        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[]  parameterValueArray;
        Map reportParametersMap;
        SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();
        ;

  
        contract.parmAccountNum('K-VDR-000001');
        contract.parmAccountType(SLD_AccountType::Vendor);
        // Provide details to controller and add contract
        controller.parmArgs(_args);
        controller.parmReportName(ssrsReportStr(SLD_TaxProfile, Report));
        controller.parmShowDialog(false);
        controller.parmLoadFromSysLastValue(false);
        controller.parmReportContract().parmRdpContract(contract);
        // Provide printer settings
        settings = controller.parmReportContract().parmPrintSettings();
        settings.printMediumType(SRSPrintMediumType::File);
        settings.fileName(fileName);
        settings.fileFormat(SRSReportFileFormat::PDF);

        // Below is a part of code responsible for rendering the report
        controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
        controller.parmReportContract().parmReportExecutionInfo(executionInfo);

        srsReportRunService.getReportDataContract(controller.parmreportcontract().parmReportName());
        srsReportRunService.preRunReport(controller.parmreportcontract());
        reportParametersMap = srsReportRunService.createParamMapFromContract(controller.parmReportContract());
        parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);

        srsProxy = SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig());
        // Actual rendering to byte array
        reportBytes = srsproxy.renderReportToByteArray(controller.parmreportcontract().parmreportpath(),
                                              parameterValueArray,
                                              settings.fileFormat(),
                                              settings.deviceinfo());
    



        // You can also convert the report Bytes into an xpp BinData object if needed
        container binData;
        Binary binaryData;
        System.IO.MemoryStream mstream = new System.IO.MemoryStream(reportBytes);
        binaryData = Binary::constructFromMemoryStream(mstream);
       // System.IO.File::WriteAllBytes("C:\\backup\\"+fileName,reportBytes); // You can save the file on your local instance for verification
       

        if(binaryData)
        {
            binData = binaryData.getContainer();
        }
        Map map=new Map (Types::String,Types::String);
        map.insert("message","Its working fine for me");
        SLD_EmailAttachment::sendPDFEamilAttachment("EmailRecpt","en-us","ShaikhSohailHussain@gmail.com",map,binData,"P000173_AbcTest");
    }

}


USE following code to send as Email Attachment 



class SLD_EmailAttachment

{


  

    public static void sendPDFEamilAttachment( SysEmailId      _emailId,
        LanguageId      _language,
        SysEmailAddress             _emailAddr,
        Map             _mappings,container _binData,str _fileName)
    {
        SysEmailItemId                   nextEmailItemId;
        SysEmailTable                    sysEmailTable;
        SysEmailMessageTable             sysEmailMessageTable;
        SysEmailContents                 sysEmailContents;
        SysOutgoingEmailTable            outgoingEmailTable;
        SysOutgoingEmailData             outgoingEmailData;
        Filename filename, FileExtension;
      
        FileExtension=".pdf";
       
        select sysEmailTable
               join    sysEmailMessageTable
                where sysEmailMessageTable.EmailId==sysEmailTable.EmailId
                    && sysEmailMessageTable.EmailId== _emailId
                    && sysEmailMessageTable.LanguageId==_language;
       
        if(sysEmailTable.RecId>0)
        {
            sysEmailContents=SysEmailMessage::stringExpand(sysEmailMessageTable.Mail, _mappings);
            nextEmailItemId = EventInbox::nextEventId();
      
            filename =strFmt("%1_%2.pdf",nextEmailItemId,_fileName);
    
    
            outgoingEmailTable.clear();
            outgoingEmailTable.Origin=sysEmailTable.Description;
            outgoingEmailTable.EmailItemId = nextEmailItemId;
            outgoingEmailTable.IsSystemEmail = NoYes::Yes;
            outgoingEmailTable.Sender = sysEmailTable.SenderAddr;
            outgoingEmailTable.SenderName = sysEmailTable.SenderName;
            outgoingEmailTable.Recipient = _emailAddr;
            outgoingEmailTable.Subject = SysEmailMessage::stringExpand(sysEmailMessageTable.Subject, _mappings);
            outgoingEmailTable.Priority = eMailPriority::High;
            outgoingEmailTable.WithRetries = NoYes::NO;
            outgoingEmailTable.RetryNum = 0;
            outgoingEmailTable.UserId = curUserId();
            outgoingEmailTable.Status = SysEmailStatus::Unsent;
            outgoingEmailTable.Message =  sysEmailContents;
            outgoingEmailTable.LatestStatusChangeDateTime = DateTimeUtil::getSystemDateTime();
            outgoingEmailTable.TemplateId= _emailId;
            outgoingEmailTable.insert();


            if(conLen(_binData)>0)
            {
                outgoingEmailData.clear();

                outgoingEmailData.EmailItemId = nextEmailItemId;
                outgoingEmailData.DataId = 1;
                outgoingEmailData.EmailDataType = SysEmailDataType::Attachment;
                outgoingEmailData.Data = _binData;
                outgoingEmailData.FileName = filename;
                outgoingEmailData.FileExtension =FileExtension;

                outgoingEmailData.insert();
            }
        }
    }

}



Display method for table extension D365FO


A display method for table extension D365FO


As we all know there is no option to create a method in table extension and most of the time we have a requirement to create a display method.

Following are the steps.



Step-1  

Create a class Extension of the table where you can write the display method.

[ExtensionOf(tableStr(CustTable))]
final class CustTable_Extension
{
}


Step-2  

Create the display methods in the class 

public static class CustTable_Extension
{
[SysClientCacheDataMethodAttribute(true)]  
public static display Name custGroupName(CustTable _this)
{
return  CustGroup::find(_this.CustGroup).Name;
}
}



Send Email in CC AX-2012


Send Email in CC AX-2012


Most of the developer have requirement in their project to send email in CC and in default Dynamics AX-2012 & D365FO this functionality is not available.


But there is the Standard class SysEmailDistributor which is responsible to send the complete AX emails.. we can achieve our goal and send email in CC as well..


Open the class and check the process method where you can find  object of SysMailerNet class.

 SysMailerNetAddressField tos,tocc;  // declare a variable <tocc>

 mailer = new SysMailerNet();  

 tocc=mailer.ccs();   // get the SysMailerNetAddressField  object using this method

tocc.add("ShaikhSohailHussain@gmail.com");  //add email address on which you want to send email as CC.



Please feel free to contact me if you are facing any issue during implementation of this blog

Virtual Fields Vs Computed Fields

  Virtual Field: A virtual field in D365FO is a field that doesn't have a direct representation in the database. It's a field that y...