Wednesday, October 4, 2023

How to send Lasernet report PDF on email.

Calling Lasernet Report from X++ Code in Dynamics 365 Finance and Operations

Calling Lasernet Report from X++ Code in Dynamics 365 Finance and Operations

Published on October 4, 2023 by Your Name

Hi All,

I hope everybody is doing great and learning isn't stopped. Today, I am here with another article that will help us call a Lasernet report from X++ code in Dynamics 365 Finance and Operations. Let me explain my requirement. I have a requirement to send the SalesPackingSlipReport over email, but we don't want to use the standard report designs because we have implemented the ISV solution "Lasernet." So, here comes the challenge: how can we call it? I got some input from the below blog, but after that, I faced lots of problems, but finally, I have achieved it.

Lasernet User Guide

Prerequisites to follow
step 1 :


class FPPrintReport
{
    public static void main(Args _args)
    {
        CustPackingSlipJour custPackingSlipJour = CustPackingSlipJour::findRecId(5637146826);
        FPPrintReport::sendPackingSlipByEmail('200030-SHI-UK01', custPackingSlipJour, 
        	'vijay.yelmame14@gmail.com', 'Test.pdf');
    }

    public static void sendPackingSlipByEmail(WHSShipmentId _shipmentId, 
    	CustPackingSlipJour custPackingSlipJour, Email _ToEmail, Filename _fileName)
    {
        CustFormletterParameters custFormParm = CustFormletterParameters::find();

        if (custFormParm.TestEnableEmailPackSlipReport)
        {
            SalesPackingSlipController formLetterController = SalesPackingSlipController::construct();
            SRSPrintDestinationSettings destinationSettings = new SRSPrintDestinationSettings();
            destinationSettings.printMediumType(SRSPrintMediumType::LAC);

            LACDestinationSettings LACDestinationSettings = new LACDestinationSettings();
            LACDestinationSettings.destTypes4Print(LACDestTypes4Print::Email);
            
            LACDestinationSettings.emailFrom(custFormParm.TestFromEmailAddress);
            LACDestinationSettings.emailTo(_ToEmail);
            LACDestinationSettings.emailSubject(strFmt(custFormParm.TestEmailSubject, _shipmentId));
            LACDestinationSettings.emailBody(custFormParm.TestEmailBody);
            LACDestinationSettings.allowForcedReRun(NoYes::Yes);
            LACDestinationSettings.emailFromName('Test Test');

            destinationSettings.lacDestinationSettings(LACDestinationSettings);

            LACReport report = LACReport::find(ssrsReportStr(Salespackingslip, Report));
            LACResendReport::resendReportFromRecord(report.ReportName, custPackingSlipJour, destinationSettings, true);
        }
    }
}

That's it! You can now follow these steps to call Lasernet reports from your X++ code in Dynamics 365 Finance and Operations. This solution should help you send your SalesPackingSlipReport over email using Lasernet.

If you have any questions or encounter any issues, please feel free to ask. Happy coding!

Monday, August 21, 2023

X++ Code to import file using data entity

internal final class TestDataEntityImport
{
    public static void main(Args _args)
    {
        FileUploadTemporaryStorageResult    fileUpload;
        AsciiStreamIo                       file;
        System.IO.Stream                    stream;

        fileUpload  = File::GetFileFromUser() as FileUploadTemporaryStorageResult;

        file        = AsciiStreamIo::constructForRead(fileUpload.openResult());

        stream      = file.getStream();
        
        TestDataEntityImport  TestDataEntityImport = new TestDataEntityImport();

        TestDataEntityImport.importFromBlob(stream,fileUpload.getFileName());
    }

    public DMFDefinitionGroup findDMFDefinitionGroup(Filename   _fileName)
    {
        DMFDefinitionGroup definitionGroup;
        
        if (strStartsWith(_fileName, 'Test'))
        {
            select firstonly definitionGroup
                where definitionGroup.DefinitionGroupName == 'TestVendorPlantImport'; //DMF import data project
        }

        return definitionGroup;
    }

    public DMFDefinitionGroupEntity findDMFDefinitionGroupEntity(DMFDefinitionGroup _definitionGroup)
    {
        DMFDefinitionGroupEntity definitionGroupEntity;
        DMFEntity dmfEntity;

        select firstonly RecId, Entity from definitionGroupEntity
            exists join dmfEntity
        where definitionGroupEntity.DefinitionGroup == _definitionGroup.DefinitionGroupName
           && dmfEntity.EntityName == definitionGroupEntity.Entity;

        if (!definitionGroupEntity)
        {
            throw error(strFmt("@DMF:DMFNoEntityExists", _definitionGroup.DefinitionGroupName));
        }

        return definitionGroupEntity;
    }

    public DMFLocalFilePath applyTransforms(SharedServiceUnitFileID _uploadedStatement, DMFDefinitionGroup definitionGroup)
    {
        DMFDefinitionGroupEntity    definitionGroupEntity = this.findDMFDefinitionGroupEntity(definitionGroup);
        DMFExecutionId              executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

        DMFDefinitionGroupExecution execution = DMFDefinitionGroupExecution::find(
            definitionGroup.DefinitionGroupName,
            definitionGroupEntity.Entity,
            executionId,
            true);

        execution.IsTransformed = NoYes::No;
        DMFLocalFilePath filePath = execution.applyTransforms(_uploadedStatement);

        DMFExecution e = DMFExecution::find(executionId, true);
        e.delete();

        return filePath;
    }

    public void importFromBlob(System.IO.Stream  _memory, str _fileName)
    {
        SharedServiceUnitFileID     fileId;
        DMFDefinitionGroup          definitionGroup;
        DMFDefinitionGroupEntity    definitionGroupEntity;
        DMFExecutionId              executionId;
        DMFDefinitionGroupExecution execution;

        //Should be used to get file into FileUploadTemporaryStorageResult object
        FileUploadTemporaryStorageResult result = File::SendFileToTempStore_GetResult(_memory, _fileName);

        if (result && result.getUploadStatus())
        {
            fileId = result.getFileId();

            definitionGroup = this.findDMFDefinitionGroup(_fileName);

            this.applyTransforms(fileId, definitionGroup);

            definitionGroupEntity = this.findDMFDefinitionGroupEntity(definitionGroup);
            executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

            // Find execution
            execution = DMFDefinitionGroupExecution::find(definitionGroup.DefinitionGroupName, definitionGroupEntity.Entity, executionId, true);
            execution.FilePath = fileId;
            execution.IsTransformed = NoYes::Yes;
            execution.IsSelected = NoYes::Yes;
            execution.ExecuteTargetStep = NoYes::Yes;
            execution.update();

            setPrefix(strFmt("@SYS73667", _fileName));

            // Import the file via quick import DMF
            DMFQuickImportExport::doPGImport(definitionGroup.DefinitionGroupName, executionId, true);

            //deletes file
            result.deleteResult();
        }
    }

}
Importing Files Using Data Management in D365FO/X++

Data migration and integration are critical aspects of any business application, and Microsoft Dynamics 365 Finance and Operations (D365FO) offers a powerful toolset to facilitate these tasks. One of the key features for importing data is the Data Management framework (DMF). In this blog post, we'll explore how to use X++ code to import files using the Data Management framework in D365FO. This code is useful in scenarios where you want to call data entity import throgh integration and also by this code you dont need to worry about how many columns user is going to add later.

Background

The X++ code provided in this blog post demonstrates how to import files using the Data Management framework in D365FO. This code is encapsulated within the TestDataEntityImport class and consists of several methods that work together to achieve a successful file import.


internal final class TestDataEntityImport
{
    public static void main(Args _args)
    {
        FileUploadTemporaryStorageResult fileUpload;
        AsciiStreamIo file;
        System.IO.Stream stream;

        fileUpload = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
        file = AsciiStreamIo::constructForRead(fileUpload.openResult());
        stream = file.getStream();
        
        TestDataEntityImport TestDataEntityImport = new TestDataEntityImport();
        TestDataEntityImport.importFromBlob(stream, fileUpload.getFileName());
    }

    public DMFDefinitionGroup findDefinitionGroup(Filename _fileName)
    {
        DMFDefinitionGroup definitionGroup;
        
        if (strStartsWith(_fileName, 'Test'))
        {
            select firstonly definitionGroup
             where definitionGroup.DefinitionGroupName == 'TestVendorPlantImport'; 
                //DMF import data project
        }

        return definitionGroup;
    }
    public DMFLocalFilePath applyTransforms(SharedServiceUnitFileID _uploadedStatement, DMFDefinitionGroup definitionGroup)
    {
        DMFDefinitionGroupEntity    definitionGroupEntity = this.findDMFDefinitionGroupEntity(definitionGroup);
        DMFExecutionId              executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

        DMFDefinitionGroupExecution execution = DMFDefinitionGroupExecution::find(
            definitionGroup.DefinitionGroupName,
            definitionGroupEntity.Entity,
            executionId,
            true);

        execution.IsTransformed = NoYes::No;
        DMFLocalFilePath filePath = execution.applyTransforms(_uploadedStatement);

        DMFExecution e = DMFExecution::find(executionId, true);
        e.delete();

        return filePath;
    }

	public void importFromBlob(System.IO.Stream _memory, str _fileName)
    {
        SharedServiceUnitFileID fileId;
        DMFDefinitionGroup definitionGroup;
        DMFDefinitionGroupEntity definitionGroupEntity;
        DMFExecutionId executionId;
        DMFDefinitionGroupExecution execution;

        // Should be used to get file into FileUploadTemporaryStorageResult object
        FileUploadTemporaryStorageResult result 
        	= File::SendFileToTempStore_GetResult(_memory, _fileName);

        if (result && result.getUploadStatus())
        {
            fileId = result.getFileId();
            definitionGroup = this.findDefinitionGroup(_fileName);
            this.applyTransforms(fileId, definitionGroup);

            definitionGroupEntity = this.findDMFDefinitionGroupEntity(definitionGroup);
            executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

            // Find execution
            execution = DMFDefinitionGroupExecution::find(
                definitionGroup.DefinitionGroupName,
                definitionGroupEntity.Entity,
                executionId,
                true
            );
            
            execution.FilePath = fileId;
            execution.IsTransformed = NoYes::Yes;
            execution.IsSelected = NoYes::Yes;
            execution.ExecuteTargetStep = NoYes::Yes;
            execution.update();

            setPrefix(strFmt("@SYS73667", _fileName));

            // Import the file via quick import DMF
            DMFQuickImportExport::doPGImport(definitionGroup.DefinitionGroupName, executionId, true);

            // Deletes file
            result.deleteResult();
        }
    }
}

Getting Started

The main method serves as the entry point for the file import process. Let's break down the code step by step:

  1. File Upload: The code begins by getting a file from the user using the File::GetFileFromUser() method. The file is uploaded and stored in temporary storage.
  2. File Reading: The uploaded file is then read using an AsciiStreamIo object. This object provides methods to read data from the uploaded file.
  3. Stream Handling: The stream variable is assigned the stream of the file data, which will be used to process the contents of the file.

Conclusion

In this blog post, we've explored how to use X++ code to import files using the Data Management framework in Dynamics 365 Finance and Operations. The provided code demonstrates the step-by-step process of uploading a file, identifying the appropriate DMF Definition Group and Entity, applying transformations, and executing the import.

The Data Management framework in D365FO simplifies data migration and integration tasks, enabling organizations to efficiently import and process large volumes of data. By leveraging the power of X++ and the DMF, businesses can ensure accurate and streamlined data management within their Dynamics 365 environment.

Thursday, August 3, 2023

Attributes cannot be deleted while dependent Provisioned channel product attribute exist. Delete dependent Provisioned channel product attribute and try again.

How to Delete Attributes with Dependent Provisioned Channel Product Attributes in D365 Finance and Operations

Deleting Attributes with Dependent Provisioned Channel Product Attributes

Struggling to remove attributes due to linked Provisioned channel product attributes? Discover a simple solution below!

The Problem:

Trying to delete attributes, but encountering obstacles due to connected Provisioned channel product attributes.

The Solution:

Follow these steps to regain control:

  1. Step 1: Access the Table Browser by adding below line after your dynamics url
    /?mi=SysTableBrowser&prt&limitednav=true&TableName=RETAILPROVISIONEDCHANNELPRODUCTATTRIBUTE&cmp=dat
  2. Step 2: Identify Linked Records
    Locate records connected to the attribute you want to delete. These ties are causing the issue.
  3. Step 3: Delete Dependent Records
    Bid farewell to linked records to break the dependency.

For more insights and learning on #MicrosoftLearn and #D365FO, check out Microsoft Learn's Dynamics 365 Finance and Operations resources.

Thursday, July 20, 2023

How to send SalesPackingSlip report over the email to Customer in D365FO using X++ code

Generate Sales Packing Slip Report and Email It

Hi All,

In this blog we are going to learn about how to generate a Sales Packing Slip report and send it to the customer's primary email address.

Step 1 Image

Step 1: Create a new class


internal final class TestPackingSlipJournalExportService
{
    SRSCatalogItemName reportDesignLocal;
    str documentTitle;
    System.IO.MemoryStream reportMemoryStream;
    SRSPrintMediumType printMedium;
    LanguageId languageId;
    System.Byte[] reportBytes;

    public static TestPackingSlipJournalExportService construct(SRSPrintMediumType _printMedium)
    {
        TestPackingSlipJournalExportService service = new TestPackingSlipJournalExportService();
        service.parmPrintMedium(_printMedium);
        return service;
    }

    public SRSPrintMediumType parmPrintMedium(SRSPrintMediumType _printMedium = printMedium)
    {
        printMedium = _printMedium;
        return printMedium;
    }

   
    /// Export packing slip journal.   
    public System.Byte[] exportPackingSlipJournal(RecId _custPackingSlipJourRecId, str _fileName)
    {
        SalesPackingSlipContract salesPackingSlipContract;
        SalesPackingSlipController formLetterController = SalesPackingSlipController::construct();
        CustPackingSlipJour custPackingSlipJour = CustPackingSlipJour::findRecId(_custPackingSlipJourRecId);

        Common printMgmtReferencedTable;
        FormLetterReport formLetterReport;
        PrintMgmtPrintSettingDetail printSettingDetail;
        SalesTable salesTable = custPackingSlipJour.salesTable();

        PrintMgmtReportFormatName printMgmtReportFormatName = PrintMgmtDocType::construct(PrintMgmtDocumentType::SalesOrderPackingSlip).getDefaultReportFormat();
        reportDesignLocal = printMgmtReportFormatName;

        if (!reportDesignLocal)
        {
            reportDesignLocal = ssrsReportStr(SalesPackingSlip, Report);
        }

        formLetterReport = FormLetterReport::construct(PrintMgmtDocumentType::SalesOrderPackingSlip);

        // Determine where to start looking for Print Mgmt settings
        printMgmtReferencedTable = salesTable;
        languageId = salesTable.LanguageId ? salesTable.LanguageId : custPackingSlipJour.LanguageId;

        formLetterReport.loadPrintSettings(custPackingSlipJour, printMgmtReferencedTable, custPackingSlipJour.LanguageId);

        if (formLetterReport.moveNextPrintSetting())
        {
            printSettingDetail = formLetterReport.getCurrentPrintSetting();
            formLetterReport.parmReportRun().loadSettingDetail(printSettingDetail);
        }

        formLetterReport.parmPrintType(PrintCopyOriginal::Original);
        salesPackingSlipContract = new SalesPackingSlipContract();

        salesPackingSlipContract.parmRecordId(custPackingSlipJour.RecId);
        salesPackingSlipContract.parmTableId(custPackingSlipJour.TableId);
        salesPackingSlipContract.parmDocumentTitle("@ExtendedItallianLocalization:DeliveryNote");

        this.generateReport(salesPackingSlipContract, _fileName);
        return this.getReportBytes();
    }

    private void generateReport(Object _rdpContract, str _fileName)
    {
        SrsReportRunController srsReportRunController = new SrsReportRunController();
        srsReportRunController.parmReportName(reportDesignLocal);
        srsReportRunController.parmExecutionMode(SysOperationExecutionMode::Synchronous);
        srsReportRunController.parmShowDialog(false);
        srsReportRunController.parmReportContract().parmRdpContract(_rdpContract);

        if (languageId)
        {
            srsReportRunController.parmReportContract().parmRdlContract().parmLanguageId(languageId);
            srsReportRunController.parmReportContract().parmRdlContract().parmLabelLanguageId(languageId);
        }

        srsReportRunController.parmReportContract().parmReportExecutionInfo(new SRSReportExecutionInfo());
        srsReportRunController.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());

        SRSPrintDestinationSettings printerSettings = srsReportRunController.parmReportContract().parmPrintSettings();
        printerSettings.printMediumType(printMedium);
        printerSettings.fileFormat(SRSReportFileFormat::PDF);
        printerSettings.parmFileName(_fileName);
        printerSettings.overwriteFile(true);

        SRSReportRunService srsReportRunService = new SRSReportRunService();
        srsReportRunService.getReportDataContract(srsReportRunController.parmReportContract().parmReportName());
        srsReportRunService.preRunReport(srsReportRunController.parmReportContract());

        Map reportParametersMap = srsReportRunService.createParamMapFromContract(srsReportRunController.parmReportContract());
        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);

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

    public System.Byte[] getReportBytes()
    {
        return reportBytes;
    }
}

    

Step 2: Call the above-created class and get the report bytes

Step 3: Convert the report byte into a stream and pass it as an attachment to the email

You can get the following 3 parameters like below:

  • CustPackingSlipJour = CustPackingSlipJour::findRecId(_custPackingSlipJourRecId);
  • Email = CustPackingSlipJour.salesTable().customerEmail();
  • FileName = "Test.pdf"

public static void sendPackingSlipByEmail(CustPackingSlipJour _custPackingSlipJour, Email _ToEmail, Filename _fileName)
{
    TestPackingSlipJournalExportService service = TestPackingSlipJournalExportService::construct(SRSPrintMediumType::File);
    System.Byte[] reportBytes = service.exportPackingSlipJournal(_custPackingSlipJour.RecId, _fileName);

    if (reportBytes)
    {
        SysMailerMessageBuilder messageBuilder = new SysMailerMessageBuilder();

        try
        {
            System.IO.Stream stream = new System.IO.MemoryStream(reportBytes);
            stream.Position = 0;
            messageBuilder.setBody("Packing Slip id - " + _custPackingSlipJour.PackingSlipId);
            messageBuilder.setSubject("Packing slip journal confirmation");
            messageBuilder.addTo(_ToEmail);
            messageBuilder.addAttachment(stream, _fileName);
            messageBuilder.setFrom('no-reply@Test.com');

            SysMailerFactory::sendNonInteractive(messageBuilder.getMessage());
        }
        catch
        {
            exceptionTextFallThrough();
        }
    }
}

    

Step 4: Result in email

Step 4 Image

If condition in computed column.

If Condition in Computed Column

If Condition in Computed Column

Hi all,

Here, we will see how to use the if condition in a computed column. In my requirement, I want to return 0 if RefType is SaftyInvent; otherwise, the value of future days from the same view.

For detailed understanding about computed columns, please check the previous blog.

TestReqTransView is a view created using the ReqTrans table.

X++ Code

private static server str compColumnDelayDays()
{
    DictView reqTransView = new DictView(tableNum(TestReqTransView));
    str reqTransDs = reqTransView.query().dataSourceTable(tableNum(ReqTrans)).name();

    return SysComputedColumn::if(
        SysComputedColumn::equalExpression(
            SysComputedColumn::comparisonField(
                dataentityviewstr(TestReqTransView),
                reqTransDs,
                fieldStr(ReqTrans, Reftype)
            ),
            SysComputedColumn::comparisonLiteral(ReqRefType::SafetyInvent)
        ),
        '0',
        SysComputedColumn::returnField(
            tableStr(TestReqTransView),
            reqTransDs,
            fieldId2name(tableNum(TestReqTransView), fieldNum(TestReqTransView, FUTURESDAYS))
        )
    );
}
    

Mark invent quantity in D365FO using X++

   

Hi All,
Below is the code to mark sales line with correspond Purch line. I used this for completing the marking for migrated purchase line.

X++ Code

 /// <summary>
 /// Mark sales line with purch line
 /// </summary>
 /// <param name = "_issueInventTransId">SalesLine inventrans Recid</param>
 /// <param name = "_receiptInventTransId">PurchLine inventtrans RecId</param>

 public static void completeInventMarking(InventTransId _issueInventTransId, InventTransId _receiptInventTransId)
    {

        InventTransId       issueInventTransId   = _issueInventTransId;
        InventTransId       receiptInventTransId = _receiptInventTransId;
        TmpInventTransMark  tmpInventTransMark;
        Map                 mapUpdated;

        InventTransOriginId receiptInventTransOriginId  =                         InventTransOrigin::findByInventTransId(receiptInventTransId).RecId;

        InventTrans         receiptInventTrans  = InventTrans::findByInventTransOrigin(receiptInventTransOriginId);

         InventTransOriginId issueInventTransOriginId    =   InventTransOrigin::findByInventTransId(issueInventTransId).RecId;

        InventTrans         issueInventTrans            =   InventTrans::findByInventTransOrigin(issueInventTransOriginId);

    InventTransMarkCollection collection = TmpInventTransMark::markingCollection(             InventTransOrigin::find(receiptInventTransOriginId),receiptInventTrans.inventDim(),         receiptInventTrans.Qty);

 collection.insertCollectionToTmpTable(tmpInventTransMark); 

 select firstonly tmpInventTransMark
            where tmpInventTransMark.InventTransOrigin == issueInventTrans.InventTransOrigin                            && tmpInventTransMark.InventDimId       == issueInventTrans.InventDimId;

 if (tmpInventTransMark.RecId != 0)
{
            Qty qtyToMark = issueInventTrans.Qty;

            tmpInventTransMark.QtyMarkNow =  qtyToMark;
            tmpInventTransMark.QtyRemain  -= tmpInventTransMark.QtyMarkNow;

            mapUpdated = new Map(Types::Int64, Types::Record);

            mapUpdated.insert(tmpInventTransMark.RecId, tmpInventTransMark);

             TmpInventTransMark::updateTmpMark(
                        receiptInventTransOriginId,
                        receiptInventTrans.inventDim(),
                        -qtyToMark,
                        mapUpdated.pack());
        }

    }

SalesPackingSlip Report and saving it as a PDF file using x++ code

Calling Sales Packing Slip Report through X++ Code

Hello Blogger Viewers,

Today, I am excited to share with you some X++ code that allows you to call the Sales Packing Slip report programmatically. This can be useful in scenarios where you need to automate the process of generating packing slip reports. Let's dive into the code!

        
SrsReportRunController ssrsController = new SrsReportRunController();
SalesPackingSlipContract salesPackingSlipContract = new SalesPackingSlipContract();
CustPackingSlipJour custPackingSlipJour;
SRSPrintDestinationSettings printerSettings;

select custPackingSlipJour where custPackingSlipJour.PackingSlipId == "200258-PAS-UK01";

// Define which report design to run.
ssrsController.parmReportName(ssrsReportStr(SalesPackingSlip, Report));

// Define how we want to execute the report (right now or batch style).
ssrsController.parmExecutionMode(SysOperationExecutionMode::Synchronous);

// Hide the report dialog.
ssrsController.parmShowDialog(false);

// Set the record and table IDs for the report contract.
salesPackingSlipContract.parmRecordId(custPackingSlipJour.RecId);
salesPackingSlipContract.parmTableId(custPackingSlipJour.TableId);

// Link the contract to the controller so we know how to run the data provider.
ssrsController.parmReportContract().parmRdpContract(salesPackingSlipContract);

// Link the printer settings to the controller.
printerSettings = ssrsController.parmReportContract().parmPrintSettings();

// Set the print medium type to HTML and always overwrite the file if it exists.
printerSettings.printMediumType(SRSPrintMediumType::File);
printerSettings.fileFormat(SRSReportFileFormat::PDF);
printerSettings.overwriteFile(true);
printerSettings.fileName(@'C:\'+'PackingListReport'+custPackingSlipJour.PackingSlipId+'.pdf');

// Start the report execution.
ssrsController.startOperation();
        
    

After executing this code, you will be able to see the generated PDF file in your "Downloads" folder. This approach provides a convenient way to automate the process of generating Sales Packing Slip reports.

I hope you find this code snippet helpful for your X++ development. If you have any questions or suggestions, feel free to leave a comment below.

Happy coding!

Update Values During Data Entity Import in D365FO

Update Values During Data Entity Import in D365FO Updating Field Values During Data Entity Import in Dynamics 365 Finance ...