Monday, July 15, 2024

MultiSelect lookup in D365f&o

   public void MultiSelectLookup(FormStringControl _control)

        {

            Query   query = new  query();

            QueryBuildDataSource qbds;

            Container cont;

            qbds = query.addDataSource(tableNum(PRO_ZPayrollStaging));

            qbds.addSelectionField(fieldNum(PRO_ZPayrollStaging, JournalBatchnumber));

            qbds.orderMode(ordermode::GroupBy); //skip for duplicate values

            qbds.addSortField(FieldNum(PRO_ZPayrollStaging,JournalBatchnumber));

            SysLookupMultiSelectGrid::lookup(query, _control, _control, _control, cont);

        }


        /// <summary>

        ///

        /// </summary>

        public void lookup()

        {

            super();

            this.MultiSelectLookup(this);

        }

......................................

Output :





Tuesday, July 9, 2024

No report data table with name [Table Name] in report scheme for data provider [SSRS Report] in Dynamics 365 F&O - Error

 Hey Dynamics 365 FinOps developer, If you are working on an SSRS data provider report, you may have experienced this error.

"(X) - No report data table with name [Table Name] in report scheme for data provider xxxxxxDP"

This error takes much of developers time to debug the root cause. So why and when this error actually raises. The answer is when your SSRS report table crosses the length of characters more than 40. So, if you are facing this error make sure your report temp/regular table length cannot be more than forty.

Other Way :

1.Rename the report dataset name.(error table name)

2.After renaming , select the dp class and table.

3.Deploy the report, restart sql services, clear the cache.

Monday, July 8, 2024

Send email with report attachment in D365 F&O

  public static void sendEmail(System.IO.MemoryStream   _mstream, Filename    _fileName, str _requestID)

    {

        Map                                     templateTokens;

        str                                     emailSubject,emailBody;

        Filename                                fileName;

        SysEmailTable                           SysEmailTable;

        var messageBuilder      = new SysMailerMessageBuilder();

        templateTokens          = new Map(Types::String, Types::String);

        select SysEmailTable;

        emailSubject = "Vendor Request Report";

        templateTokens.insert("@SYS74341", emailSubject);

        templateTokens.insert("@SYS4009003", _fileName);

        emailBody =  strFmt("A vendor request has been registed with the vendor request id %1 please find the attached document for more information.",_requestID);

        emailBody = SysEmailMessage::stringExpand(emailBody, SysEmailTable::htmlEncodeParameters(templateTokens));

        emailBody = strReplace(emailBody, '\n', '<br>');

        emailBody +='<br><br>Thanks,<br>' +'Daxarch'; // for thanks

        messageBuilder.addTo("lohith.m@daxarch.in")

                                    .setSubject(emailSubject)

                                    .setBody(emailBody)

                                    .addCC("");


        messageBuilder.setFrom("lohithmudigonda.m@gmail.com" , "Thiru") ; //sendor mail must be configured in front end.

        messageBuilder.addAttachment(_mstream, _fileName);


        SysMailerFactory::sendNonInteractive(messageBuilder.getMessage());


        info(strFmt("Email sent successfully for vendor request %1",_requestID));

    }

............................

Configure the sendor mail id :




Output :




Thursday, July 4, 2024

Code to download the SSRS report to pdf in D365F&O X++

  public static void main(Args _args)

    {

        Filename                        fileName = "VendorRequest.pdf";

        SrsReportRunController          controller = new SrsReportRunController();

        SRSReportExecutionInfo          executionInfo = new SRSReportExecutionInfo();

        PRO_VendRequestContract         contract = new  PRO_VendRequestContract();

        Map                             reportParametersMap;

        SRSProxy                        srsProxy;

        System.IO.MemoryStream          mstream;

        SRSPrintDestinationSettings     settings;

        System.Byte[]                   reportBytes = new System.Byte[0]();

        SRSReportRunService             srsReportRunService = new SrsReportRunService();

        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[]  parameterValueArray;

//normal code for calling report.

        PRO_VendRequestController   pRO_VendRequestController = pRO_VendRequestController::construct();

        pRO_VendRequestController.parmReportName(ssrsReportStr(PRO_VendRequest, Report));

        pRO_VendRequestController.parmArgs(_args);

        pRO_VendRequestController.parmShowDialog(false);

        pRO_VendRequestController.startOperation();


        //set controller parameters

        controller.parmReportName(ssrsReportStr(PRO_VendRequest, 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);


        //set proxy and service values

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


        //conver the byte array to memory stream

        mstream         = new System.IO.MemoryStream(reportBytes);

        File::SendFileToUser(mstream, fileName);

    }

Monday, July 1, 2024

Generate Ledger dimension for MainAccount in D365F&O X++

     public static void main(Args _args)

    {

        MainAccount mainaccount;

        LedgerDimensionDefaultAccount   lda;

        

        mainaccount = MainAccount::findByMainAccountId("110110");

        lda = LedgerDefaultAccountHelper::getDefaultAccountFromMainAccountRecId(mainaccount.RecId);

        Info(strFmt("%1",lda));

    }

......................................

Other Way :

  public static void main(Args _args)

    {

        DimensionDynamicAccount     offsetLedgerDim;

        Array                       acctDimAttrArray  = new Array(Types::String);

        acctDimAttrArray.value(1,"MainAccount");


        Array                       acctDimArray     = new Array(Types::String);

        acctDimArray.value(1,'112010');


        DefaultDimensionIntegrationValues DefaultDimensionIntegrationValues   = DimensionResolver::getEntityDisplayValue

            (acctDimAttrArray, acctDimArray, extendedTypeStr(DimensionDynamicAccount), LedgerJournalACType::Ledger);

        DimensionDynamicAccountResolver DimensionDynamicAccountResolver     = DimensionDynamicAccountResolver::newResolver

                (DefaultDimensionIntegrationValues, LedgerJournalACType::Ledger, curExt());

        offsetLedgerDim = DimensionDynamicAccountResolver.resolve();

        info(strFmt("%1",offsetLedgerDim));

    }

After runinng the job a recid will be generated.

if you are getting an error like : No active format for data entities has been set up. Set up an active format for each dimension format type. then do the following step.

in my code i've given a value for main account only, so i have added main account in dimension configuration.


Reference:

https://community.dynamics.com/blogs/post/?postid=ad1c7df5-fff2-43c1-9791-7ad80e545eec

For error resolving :
http://www.dynamicsaxhelp.com/Resolved/No-active-format-for-data-entities-has-been-set-up/46






Friday, May 31, 2024

X++ code to attach a file in D365F&O

 using Microsoft.Dynamics.ApplicationPlatform.Services.Instrumentation;

using Microsoft.DynamicsOnline.Infrastructure.Components.SharedServiceUnitStorage;

using Microsoft.Dynamics.AX.Framework.FileManagement;

internal final class RunnableClass1

{

    /// <summary>

    /// Class entry point. The system will call this method when a designated menu 

    /// is selected or when execution starts and this class is set as the startup class.

    /// </summary>

    /// <param name = "_args">The specified arguments.</param>

   

    public static void main(Args _args)

    {

        boolean                     ret = false;

        str docfiletype;

        Microsoft.Dynamics.AX.Framework.FileManagement.IDocumentStorageProvider storageProvider;

        DocuRef     docuref;

        str downloadUrl;

        Filename    _Filename = 'GeneralLedger-General journal custom.xlsx';

        FilePath    _filePath = @'C:\Users\Admin41df0ec1e1\Downloads\GeneralLedger-General journal.xlsx';

        System.IO.Stream    _stream;

        _stream = File::UseFileFromURL(_filePath);

        str _contentType = System.Web.MimeMapping::GetMimeMapping(_filePath);

        DocuType fileType = DocuType::find(DocuType::typeFile());

        storageProvider = Docu::GetStorageProvider(fileType, true, curUserId());


        if(storageProvider)

        {

            str uniqueFileName = storageProvider.GenerateUniqueName(_Filename);

            str fileNameWithoutExtension = System.IO.Path::GetFileNameWithoutExtension(_filePath);

            str fileExtension = Docu::GetFileExtension(uniqueFileName);

  

            if(Docu::validateExtension(fileExtension))

            {

                guid FileId = newGuid();

                DocuValue docValue;

                docValue.Name = fileNameWithoutExtension;

                docValue.FileId = FileId;

                docValue.FileName = uniqueFileName;

                docValue.FileType = "xlsx";//fileExtension;

                docValue.OriginalFileName = _Filename;

                docValue.Type = DocuValueType::Others;

                docValue.StorageProviderId = storageProvider.ProviderId;

                DocumentLocation location = storageProvider.SaveFile(docValue.FileId, uniqueFileName, contentType, stream);

                

                if (location != null)

                {

                    if(location.NavigationUri)

                    {

                        docValue.Path = location.get_NavigationUri().ToString();

                    }


                    if(location.AccessUri)

                    {

                        docValue.AccessInformation = location.get_AccessUri().ToString();

                        //info(docValue.AccessInformation);

                    }


                    if (docValue.validateWrite())

                    {

                       

                        docValue.insert();

                        DocuUploadResult DocuUploadResult =  new DocuUploadResult(_fileName, _contentType, false, "", newGuid());

                        DocuUploadResult.fileId(FileId);

                         docuref = DocuUploadResult.createDocuRef(9615,68719508511,DocuType::typeFile());

                        if(docuref)

                        {

                            ret =  true;

                        }

                        else

                        {

                            ret =  false;

                        }

                    }        

                }

             }

        }

    }


}

Thursday, May 23, 2024

Cannot stop DynamicsAxBatch service on computer Dynamics 365 for finance and operations

 


The message already shows the service name. ” DynamicsAXBatch” You can copy it from Service detail dialog.

So Open CMD with run as administrator and run the following command and get  pid

sc queryex DynamicsAxBatch


Now I have IP.

And kill the Process Id 

taskkill /f /pid 11524  

Now I start the service again.

Project is successfully complied             





Cursor moves to top when refreshing list page grid in D365F&O

    My requirement is to be the cursor on the same record when a button is clicked, but the cursor is moving according to the formdatasource setposition property, but it should be on the same record.

            FormDataSource              inventTestGroup_ds = sender.formRun().dataSource();

           int position = inventTestGroup_ds.getPosition();

            inventTestGroup_ds.refresh();

            inventTestGroup_ds.reread();

            inventTestGroup_ds.research(true);

            inventTestGroup_ds.setPosition(position);



Wednesday, April 17, 2024

How to add custom element in SalesLedgerDimension of ItemGroups in D365F&O

My requirement is to add a custom element in item group of salesledgerdimension

InventoryManagement>Inventory>Item Groups

Add the Custom element in the following base enums :

1.InventAccountType

2.InventAccountTypeSales

3.LedgerPostingType.




Create a class and add these eventhandlers.

internal final class DaxInventGroupForm_EventHandler

{

   /// <summary>

   ///

   /// </summary>

   /// <param name="_inventAccountType"></param>

   /// <param name="_result"></param>

   [SubscribesTo(tableStr(InventItemGroupForm), delegateStr(InventItemGroupForm, ledgerDimensionDescriptionDelegate))]

   public static void InventItemGroupForm_ledgerDimensionDescriptionDelegate(InventAccountType _inventAccountType, EventHandlerResult _result)

   {

       switch(_inventAccountType)

       {

        case InventAccountType::Dax:

           _result.result(enum2str(InventAccountTypeSales::Dax));

           break;

       }

   }

   [SubscribesTo(tableStr(InventItemGroupForm), staticDelegateStr(InventItemGroupForm, getGroupForAccountTypeDelegate))]

   public static void inventItemGroupForm_getGroupForAccountTypeDelegate(InventAccountType _inventAccountType, EventHandlerResult _result)

   {

       switch (_inventAccountType)

       {

           case InventAccountType::Dax:

               _result.result(ItemGroupLedgerDimensionGroup::Sales);

               break;

       }

   }

//Method to stop the error which generates i.e., Enumerated text Daxarch does not exits

   [SubscribesTo(tableStr(InventPosting), staticDelegateStr(InventPosting, accountType2LedgerPostingTypeDelegate))]

   public static void inventPostingAccountTypeToLedgerPostingTypeDelegate(InventAccountType _inventAccountType, EventHandlerResult _result)

   {

       switch(_inventAccountType)

       {

           case InventAccountType::Dax:

               _result.result(LedgerPostingType::Dax);

               break;

       }

   }

}

.................

Output:




Code to create Purchase Order ,Confirmation, Partial Product Receipt and partial Invoice in D365F&O X++

 public static void main(Args _args)

   {

       PurchPurchaseOrderHeaderV2Entity    purchPurchaseOrderHeaderV2Entity;

       PurchPurchaseOrderLineV2Entity      purchPurchaseOrderLineV2Entity;

       PurchFormLetter                     purchFormLetter;

       PurchFormletterParmData             purchFormLetterParmData;

       PurchParmUpdate                     purchParmUpdate;

       PurchParmTable                      purchParmTable;

       NumberSeq                           numberSeq;

       MarkupTrans                         markupTrans;

       PurchLine                           purchLine;

       SourceDocumentLine                  sourcedoucumentline;

       PurchParmLine                       purchParmLine;

       PurchTable                          purchTable;

       PurchId                             purchId;

       Num                                 packingSlipId;

 

       numberSeq = NumberSeq::newGetNum(PurchParameters::numRefPurchId());

       numberSeq.used();

       

       purchPurchaseOrderHeaderV2Entity.initValue();

       purchPurchaseOrderHeaderV2Entity.PurchaseOrderNumber = numberSeq.num();

       purchPurchaseOrderHeaderV2Entity.PurchaseOrderName = "custom Order";

       purchPurchaseOrderHeaderV2Entity.OrderVendorAccountNumber = "1001";

       purchPurchaseOrderHeaderV2Entity.insert();

 

       purchPurchaseOrderLineV2Entity.PurchaseOrderNumber =  purchPurchaseOrderHeaderV2Entity.PurchaseOrderNumber;

       purchPurchaseOrderLineV2Entity.ItemNumber = '1000';

       purchPurchaseOrderLineV2Entity.PurchasePrice = 10;

       purchPurchaseOrderLineV2Entity.PurchasePriceQuantity = 2;

       purchPurchaseOrderLineV2Entity.OrderedPurchaseQuantity = 10;

       purchPurchaseOrderLineV2Entity.ReceivingSiteId = '1';

       purchPurchaseOrderLineV2Entity.ReceivingWarehouseId = '11';

       purchPurchaseOrderLineV2Entity.insert();

 

       purchId       = purchPurchaseOrderLineV2Entity.PurchaseOrderNumber;

       packingSlipId = "MA"+ purchId;

       purchTable    = PurchTable::find(purchId);

 

       select purchLine

           where purchLine.RecId == purchPurchaseOrderLineV2Entity.RecId;

 

       //creating a maintain charges record for line

       markupTrans.initFromMarkupTable(MarkupTable::find(MarkupModuleType::Vend,  "FREIGHT"));

       markupTrans.initFromPurchLine(purchLine);

       markupTrans.LineNum = MarkupTrans::lastLineNum(markupTrans.TransTableId, markupTrans.TransRecId)+1;

       markupTrans.modifiedField(fieldNum(markupTrans ,Value ));

       markupTrans.MarkupCode = "FREIGHT";

       markupTrans.Txt = "Freight";

       markupTrans.MarkupCategory = MarkupCategory::Fixed;

       markupTrans.Value = 200;

       markupTrans.MCROriginalMiscChargeValue = 200;

       markupTrans.CurrencyCode = "USD";

       markupTrans.ModuleType = MarkupModuleType::Vend;

       markupTrans.ModuleCategory = HeadingLine::Line;

       markupTrans.TransDate = today();

       markupTrans.insert();

 

       purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);

       purchFormLetter.update(purchPurchaseOrderHeaderV2Entity, strFmt("Inv_%1", purchPurchaseOrderHeaderV2Entity.PurchaseOrderNumber));

 

       ttsBegin;

       // Create PurchParamUpdate table

       purchFormLetterParmData = PurchFormletterParmData::newData(

       DocumentStatus::PackingSlip,

       VersioningUpdateType::Initial);

 

       purchFormLetterParmData.parmOnlyCreateParmUpdate(true);

       purchFormLetterParmData.createData(false);

       purchParmUpdate = purchFormLetterParmData.parmParmUpdate();

 

       //Set PurchParmTable table

       purchParmTable.clear();

       purchParmTable.TransDate                = SystemDateGet();

       purchParmTable.Ordering                 = DocumentStatus::PackingSlip;

       purchParmTable.ParmJobStatus            = ParmJobStatus::Waiting;

       purchParmTable.Num                      = packingSlipId;

       purchParmTable.PurchId                  = purchTable.PurchId;

       purchParmTable.PurchName                = purchTable.PurchName;

       purchParmTable.DeliveryName             = purchTable.DeliveryName;

       purchParmTable.DeliveryPostalAddress    = purchTable.DeliveryPostalAddress;

       purchParmTable.OrderAccount             = purchTable.OrderAccount;

       purchParmTable.CurrencyCode             = purchTable.CurrencyCode;

       purchParmTable.InvoiceAccount           = purchTable.InvoiceAccount;

       purchParmTable.ParmId                   = purchParmUpdate.ParmId;

       purchParmTable.insert();

 

       // Set PurchParmLine table

       while select purchLine

       where purchLine.PurchId == purchTable.purchId

       {

           purchParmLine.InitFromPurchLine(purchLine);

 

           purchParmLine.ReceiveNow    = 5;//PurchLine.PurchQty;

           purchParmLine.ParmId        = purchParmTable.ParmId;

           purchParmLine.TableRefId    = purchParmTable.TableRefId;

           purchParmLine.setQty(DocumentStatus::PackingSlip, false, true);

           purchParmLine.setLineAmount();

           purchParmLine.insert();

       }

 

       purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);

       purchFormLetter.transDate(systemDateGet());

       purchFormLetter.proforma(false);

       purchFormLetter.specQty(PurchUpdate::All);

       purchFormLetter.purchTable(purchTable);

 

       // This is the ID we hard code as the product receipt ID, if we do the posting via UI

       // user would have the option to manually enter this value

       purchFormLetter.parmParmTableNum(purchParmTable.ParmId);

       purchFormLetter.parmId(purchParmTable.ParmId);

       purchFormLetter.purchParmUpdate(purchFormLetterParmData.parmParmUpdate());

       purchFormLetter.run();

       ttsCommit;

       

       //posting of invoice

       purchFormLetter = purchFormLetter::construct(DocumentStatus::Invoice);

       purchFormLetter.update(purchTable, "Inv_"+purchTable.PurchId,systemdateget(),PurchUpdate::PackingSlip); // Transaction date

       info(purchTable.PurchId);

   }

...............................