Simple Dialog using X++ – Dynamics 365 for Finance and Operations

Scenario: Sometimes we need a simple dialog having some fields and we do not want to use dialog form ,instead of that we can create dialog thru X++ code.

Below is the code you can use to create simple dialog.

Example Code:

      

//Declare dialog variables       

Dialog                  dialog;       

DialogField             fieldfDate, fieldtDate;       

FromDate _fromDate, _toDate;       

;       

dialog = new Dialog(“Select start and end date”);       

//define fields to show on the dialog       

fieldfDate = dialog.addField(extendedTypeStr(TransDate));       

fieldtDate = dialog.addField(extendedTypeStr(TransDate));              

dialog.run();       

if (dialog.closedOk())       

{

           //get values from the dialog fields

            _fromDate = fieldfDate.value();

            _toDate = fieldtDate.value();   

}

Introduction to Form Patterns – Dynamics 365 for Finance and Operations

Form Patterns are introduced in Dynamics 365 for Finance and Operations, In Dynamics AX2012 we used form styles. These Patterns provide a base structure based on particular style (including required and optional controls), and also provide many default control properties. Patterns have made the form development very easier and after applying the pattern its validate and give the gurantee to the developers that its correct and consistant.

Patterns help validate form and control structures, and also use of control in some places.Form patterns provide many default control properties, and these also contribute to a more guided development experience.

List of Top Level Form Patterns

Form pattern What it’s used for
Details Master (two variants) A form that displays the details of a complex entity
Details Transaction A form that displays the details of a complex transaction entity and its lines (for example, and order and its lines)
Dialog (six variants) A form that is used as a dialog to gather a set of information
Drop Dialog (two variants) A form that is used as a drop dialog to gather a small set of information to provide context for an action
FactBox (two variants) A Microsoft Dynamics AX 2012 FactBox that displays information about a related record or set of records
List Page A Dynamics AX 2012 List Page
Lookup (three variants) A form that is used as a lookup
Simple Details (four variants) A form that is focused on a single record
Simple List A form that displays details for a simple entity as a grid that has fewer than 10 fields per record
Simple List & Details (three variants) A form that displays information about an entity of medium complexity
Table of Contents A form that displays setup information or loosely related information sets
Task (two variants) A legacy form pattern that is used to display master or transaction entities
Wizard A form that displays a set of tab pages to the user to gather information in a predetermined order
Operational Workspace A form that is used to display an overview of an activity and is meant to be a primary means of navigation
Workspace Panorama Sections (three variants) A form that is used to show content for a panorama section (via a Form Part Control) in the Operational Workspace

 

This is just an introduction of the form patterns will describe each pattern in details in separate post.

Read Data from Excel file – Dynamics 365 for Finance and Operations – Excel Operations X++

Scenario : upload/Import the data using excel

Solution: Below is the code snippet to use for the data upload using excel

Note: SysExcel classes has been depreciated in the dynamics 365

Microsoft office interop reference is used in the dynamics 365. You can find that in the reference node of solution explorer.

 

Code :

 

using System.IO;

using OfficeOpenXml;

using OfficeOpenXml.ExcelPackage;

using OfficeOpenXml.ExcelRange;

class BEUploadExcelLeaveTransactions

{

    /// <summary>

    /// Runs the class with the specified arguments.

    /// </summary>

    /// <param name = “_args”>The specified arguments.</param>

    public static void main(Args _args)

    {

        

        System.IO.Stream            stream;

        

        FileUploadBuild             fileUploadBuild;

        DialogGroup                 dialogUploadGroup;

        FormBuildControl            formBuildControl;

        Dialog                      dialog = new Dialog(‘Import the data from the Excel’);

        dialogUploadGroup          = dialog.addGroup(‘@SYS54759’);

        formBuildControl        = dialog.formBuildDesign().control(dialogUploadGroup.name());

        fileUploadBuild         = formBuildControl.addControlEx(classstr(FileUpload), ‘Upload’);

        fileUploadBuild.style(FileUploadStyle::MinimalWithFilename);

        fileUploadBuild.fileTypesAccepted(‘.xlsx’);

        if (dialog.run() && dialog.closedOk())

        {

            Fileupload fileUploadControl     = dialog.formRun().control(dialog.formRun().controlId(‘Upload’));

            FileUploadTemporaryStorageResult fileUploadResult = fileUploadControl.getFileUploadResult();

            if (fileUploadResult != null && fileUploadResult.getUploadStatus())

            {

                stream = fileUploadResult.openResult();

                using (ExcelPackage ePackage = new ExcelPackage(stream))

                {

                    int                         rowCount, i;

                    ePackage.Load(stream);

                    ExcelWorksheet  eWorksheet   = ePackage.get_Workbook().get_Worksheets().get_Item(1);

                    OfficeOpenXml.ExcelRange    eRange       = eWorksheet.Cells;

                    rowCount                  = eWorksheet.Dimension.End.Row – eWorksheet.Dimension.Start.Row + 1;

                    for (i = 2; i<= rowCount; i++)

                    {

                        info(eRange.get_Item(i, 1).value);

                        info(eRange.get_Item(i, 2).value);

                    }

                }

            }

            else

            {

               throw error(‘Error here’);

            }

        }

    }

}

Models Export and Import: Dynamics 365 for Finace and Operations

Scenario:

Export model from one dev environment to another dev enviornment

Steps to perform:

  1. Export model from enviornment using command prompt
  2. Import Model in another enviornment using command prompt
  3. Resolve conflicts
  4. Complete build of models and Synchonization of Database

 

Export Model:

Export the model using utilily name ModelUtil.exe located in the below path

K:\AosService\PackagesLocalDirectory\Bin

K:\ Drive can be varrried for local VM C:\ or J:\ 

Command:

ModelUtil.exe -export -metadatastorepath= [path of the metadata 
store] -modelname=[name of the model to export] -outputpath=[path 
of folder where model file should be saved]

 

Example:

ModelUtil.exe -export -metadatastorepath= K:\AosService\PackagesLocalDirectory -modelname=D365FnOModel -outputpath=C:\Users\Userf3d496631\Desktop\US\devmodelsbackup

Screen Shot 2019-09-08 at 4.47.49 PM

 

Import model:

To install or import a model file use below code

ModelUtil.exe -import -metadatastorepath=[path of the metadata store 
where model should be imported] -file=[full path of the file to 
import]

Example:

ModelUtil.exe -Import -metadatastorepath= K:\AosService\PackagesLocalDirectory -file=C:\Users\Userf3d46296631\Desktop\US\devmodelsbackup\D365FnOModel

Screen Shot 2019-09-08 at 4.59.11 PM.png

 

Delete a Model:

If model already exists in the destination environment. Delete the model using modelutility.exe

ModelUtil.exe -delete -metadatastorepath=[path of the metadata store]
 -modelname=[name of the model to delete]

Example:

ModelUtil.exe -Delete -metadatastorepath= K:\AosService\PackagesLocalDirectory -modelName=D365FnOModel

Screen Shot 2019-09-08 at 5.02.35 PM.png

 

Resolve the conflicts after importing:

 

Screen Shot 2019-09-08 at 5.04.05 PM.png

 

Build and sycnhronize:

after resolving all the conlicts build the model(all models would be better but it will take long time) and synchronize the database

 

Export to Excel thru code X++ – Dynamics 365 For Finance and Operations

Below code is used to export the data in the excel file using X++ code

 

using System.IO;

using OfficeOpenXml;

using OfficeOpenXml.Style;

using OfficeOpenXml.Table;

class ExportToExcel

{        

    /// <summary>

    /// Runs the class with the specified arguments.

    /// </summary>

    /// <param name = “_args”>The specified arguments.</param>

    public static void main(Args _args)

    {

       HcmWotker hcmWorker;

        MemoryStream memoryStream = new MemoryStream();

        using (var package = new ExcelPackage(memoryStream))

        {

            var currentRow = 1;

            Filename fileName = “Test.Xlsx”;

            var worksheets = package.get_Workbook().get_Worksheets();

            var CustTableWorksheet = worksheets.Add(“Export”);

            var cells = CustTableWorksheet.get_Cells();

            OfficeOpenXml.ExcelRange cell = cells.get_Item(currentRow, 1);

            System.String value = “Personnel Number”;

            cell.set_Value(value);

            cell = null;

            value = “Name”;

            cell = cells.get_Item(currentRow, 2);

            cell.set_Value(value);

            while select hcmWorker

            {

                currentRow ++;

                cell = null;

                cell = cells.get_Item(currentRow, 1);

                cell.set_Value(hcmworker.PersonnelNumber);

                cell = null;

                cell = cells.get_Item(currentRow, 2);

                cell.set_Value(hcmworker.Name());

            }

            package.Save();

            file::SendFileToUser(memoryStream, fileName);

           

        }

    }

}

Send email thru code with Report as attachment – Dynamics 365 Finance and Operations

Scenario: Send email thru X++ code with the report as attachment

Below is the code responsible for sending email thru code with the attachment

Guide lines to use below code

Just copy paste the code in the runnable class(job), perform below steps

Just replace the report contract name and paramters values

add send from and to email addresses,

Code:

//Set  variables

Filename fileName = “attFileName.pdf”; 

SrsReportRunController controller = new SrsReportRunController(); 

ReportContract contract = new ReportContract();

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();

//set the report contract parameters

contract.parm1stParameter(“firstParameter value”);

contract.parm2ndtParameter(‘2ndParamter value’);

//3rd paramter

//4th paramter

//set the report controller paramters

controller.parmArgs(_args);

//set report name and desing name

controller.parmReportName(ssrsReportStr(ReportName, NewDesign));

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);       

if(binaryData)       

{

            binData = binaryData.getContainer();     

}       

System.Byte[] binData1;       

System.IO.Stream stream1;       

// Turn the Bytes into a stream       

for(int i = 0; i < conLen(binData); i++)        

{

            binData1 = conPeek(binData,i+1);

            stream1 = new System.IO.MemoryStream(binData1);       

} 

//email sending settings

var mail = SysMailerFactory::getNonInteractiveMailer(); 

var messageBuilder = new SysMailerMessageBuilder();        

messageBuilder.reset()

                .setFrom(‘example@Email.com’) // From email address

                .addTo(‘example@email.com’) // To Email address

                .setSubject(‘Email Subject’) // Email Subject

                .setBody(‘Email Body’);        //Email Body

if (stream1 != null)       

{

//add attachment to the email

            messageBuilder.addAttachment(stream1,filename+”.pdf”);       

}

//send email

mail.sendNonInteractive(messageBuilder.getMessage());

}

Run report and send thru email attachment – Dynamics 365 for Finance and Operations

In Dynamics 365 we use SysMailerFactory class to send an email thru X++ code,

Below is the code to send an email with the attachment. You can comment the attachment code if you want only to send an email thru X++

//Define variables

Filename fileName = “AbcTest.pdf”;
SrsReportRunController controller = new SrsReportRunController();
ReportContractClass contract = new ReportContractClass();
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();

//Pass contract variables
contract.parm1(); //Some contract class method for parameter
contract.parm2(); //Some contract class method for parameter

//Controller class for the report name and set contract class for controller

controller.parmArgs(_args);
controller.parmReportName(ssrsReportStr(); // Report name and design
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);
if(binaryData)
{
binData = binaryData.getContainer();
}

System.Byte[] binData1;
System.IO.Stream stream1;

// Turn the Bytes into a stream
for(int i = 0; i < conLen(binData); i++)
{
binData1 = conPeek(binData,i+1);
stream1 = new System.IO.MemoryStream(binData1);
}

var mail = SysMailerFactory::getNonInteractiveMailer();
var messageBuilder = new SysMailerMessageBuilder();
// for (i = 1; i <= conLen(_notifyCon); i++)
// {
// notifyEmailsStr = conPeek(_notifyCon, i);
// select firstonly RecId, Email from sysUser where sysUser.Id == notifyEmailsStr;
// if (sysUser.RecId && sysUser.Email != ”)
//{
messageBuilder.reset()
.setFrom(‘from email address’)
.addTo(‘to email address’)
.setSubject(‘Email Subject’)
.setBody(‘Email Body’);

if (stream1 != null)
{
messageBuilder.addAttachment(stream1,’abcd.pdf’);
}
mail.sendNonInteractive(messageBuilder.getMessage());

Override form control lookup – Dynamics 365 Finance and Operations

To overrie the string control use SysTableLookup sysTableLookup;

To override the reference group control use SysReferenceTableLookup sysReferenceTableLookup;

Below is the example of reference control

[FormControlEventHandler(formControlStr(HcmDiscussionNewDialog, HcmDiscussion_PerfPeriod), FormControlEventType::Lookup)]
public static void HcmDiscussion_PerfPeriod_OnLookup(FormControl sender, FormControlEventArgs e)
{
SysReferenceTableLookup sysReferenceTableLookup;
Query query = new Query();

sysReferenceTableLookup =SysReferenceTableLookup::newParameters(tableNum(HcmPerfPeriod),sender);
sysReferenceTableLookup.addLookupfield(fieldNum(HcmPerfPeriod,PerfPeriodId));
sysReferenceTableLookup.addLookupfield(fieldNum(HcmPerfPeriod,StartDate));
sysReferenceTableLookup.addLookupfield(fieldNum(HcmPerfPeriod,EndDate));

sysReferenceTableLookup.parmQuery(query);
sysReferenceTableLookup.performFormLookup();

//Cancel the super

FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;

ce.CancelSuperCall();

}